Shared resolver for a Card's i18n bundle directory.
Two endpoints must agree on exactly one path: the card endpoint
({@see \LaravelUi5\Core\Http\Controllers\CardController}, which injects
sap.app/i18n when a bundle is present) and the bundle endpoint
({@see \LaravelUi5\Core\Http\Controllers\CardI18nController}, which serves the
.properties files). That single source of truth lives here rather than on
{@see Ui5CardInterface}: the convention is fully derivable from the
artifact's public surface (its module + namespace), so it earns no contract
method.
Convention — sibling of the manifest, mirroring {@see \LaravelUi5\Core\Ui5\AbstractUi5Card::getManifest()}:
where <package-root> is dirname($moduleFile, 2) and <slug> is the last
dot-segment of the card namespace. A card opts into i18n simply by having
that directory; absent it, null signals "no bundle" and the card endpoint
skips injection (plain-string cards stay byte-for-byte untouched).
Caveat: this follows the convention, not a consumer's getManifest()
override. A card with a non-standard manifest layout that also wants i18n
must keep its bundle at the conventional path (or the seam can grow a
contract method later — additive, non-breaking).