Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

I18N Laravel Package

ibexa/i18n

The official translation meta-repository for Ibexa, centralizing locale files synced from Crowdin so translations ship with the product. Enable them via the ibexa.ui.translations.enabled configuration, and contribute new translations through the Ibexa project on Crowdin.

View on GitHub
Deep Wiki
Context7

Getting Started

ibexa/i18n is not a library you call — it is a meta repository of translation resources that is machine-synchronised from Crowdin into the product. Your job as a developer is almost always consumption and overriding, not integration.

Install / confirm it is present

It normally arrives transitively with ibexa/oss, ibexa/experience, or ibexa/content:

composer show ibexa/i18n          # check version tag
ls vendor/ibexa/i18n

Avoid requiring it explicitly in composer.json unless you need to pin a translation snapshot; let the metapackage constraint drive it.

Enable the translations

The README gives the only configuration knob:

# config/packages/ibexa.yaml
ibexa:
    ui:
        translations:
            enabled: true

Then clear the cache so the translator warms its catalogue:

bin/console cache:clear

Where to look first

  1. find vendor/ibexa/i18n -path '*translations*' -name '*.y*ml' (or *.xlf) to see the actual resource files and locale codes.
  2. grep -rn "addResource\|translations" vendor/ibexa/i18n/src to find the DI extension that registers the path — that tells you the translation domain and load order.
  3. bin/console debug:translation <locale> --domain=<domain> to confirm a key resolves and which file wins.

First use case

Enable a second language on a siteaccess and verify a back-office string is translated:

ibexa:
    system:
        my_site:
            languages: [eng-GB, ger-DE]

Then check in Twig, using the domain the extension registers (commonly ibexa, but confirm rather than assume):

{{ 'ibexa.some.key'|trans({}, 'ibexa') }}

If you see the raw key, the catalogue was not loaded — see Gotchas.

Implementation Patterns

Consume keys, never copy files. Importing vendor translation files into your project forks them; the next composer update ibexa/i18n resurrects duplicates and your debug:translation output becomes ambiguous.

Override strings in your app, not in vendor. Put translations/<domain>.<locale>.yaml (e.g. translations/ibexa.en.yaml) in the project root. Symfony's app catalogue is loaded last, so it wins on key collisions. Always verify empirically:

bin/console debug:translation en --domain=ibexa | grep -A3 "my.key"

Namespace your own keys. Use a project prefix (app.*, acme.*) in a project-specific domain and leave the vendor domain untouched. Mixing your keys into the ibexa domain makes future upstream key renames silently shadow your text.

Custom code pattern

// anywhere the TranslatorInterface is injected
echo $translator->trans('app.invoice.title', ['%id%' => $id], 'app');
{# in the admin UI / front end #}
{{ 'app.invoice.title'|trans({'%id%': id}, 'app') }}

In Ibexa templates you may also see the legacy extractor filter used for key collection — keep the key text identical to the label so extraction stays stable:

{{ 'app.invoice.title'|trans|desc('Invoice title') }}

Locale strategy for unsupported languages. If your locale (say nl-BE) has no catalogue, map it to the closest supported one rather than leaving keys raw:

framework:
    translator:
        fallbacks: [en]
    default_locale: en

You can register a fallback chain per locale (nl_BE → nl → en) so a partially translated UI degrades instead of exploding into keys.

Workflow for new/updated translations

  • One-off correction of an existing string → app-level override commit, reviewed like code.
  • New language or large coverage gap → contribute upstream on Crowdin, not via a PR with edited files.
  • Bump translations → depend on a release tag, then composer update ibexa/i18n && bin/console cache:clear in CI and locally.

CI check that costs one line

Fail the build if a required key is untranslated in a shipping locale:

bin/console debug:translation de --domain=ibexa --only-missing

Gotchas and Tips

This repo is generated — direct PRs get clobbered. The README describes an automated pipeline (Crowdin → l10n_main → PR → squash-merge to main). Any edit you push to a translation file is either rejected or lost on the next sync. Fix translations on Crowdin, or override them in your project.

The license is NOASSERTION, and it is not a simple permissive license. The README explicitly splits licensing: Ibexa BUL v2.3+ (with product edition determining terms). Do not extract, rehost, or redistribute the translation catalogue as a standalone dataset — treat it as product content. Get legal sign-off before shipping a derived translation package.

enabled: false (or missing) is the #1 "why are my strings raw" cause. The config is required for the resources to be registered; the package alone does nothing. It also interacts with your siteaccess languages list — a locale not in the siteaccess languages will not be negotiated.

Cache is the #2 cause. Symfony caches catalogues per environment under var/cache/<env>/translations. After a composer update or an override file change, run bin/console cache:clear. If you use a cache pool (Redis/APCu, e.g. in Ibexa Cloud), clear the pool too — otherwise warm-up writes stale entries back.

Locale code mismatch is silent. Symfony uses pt_BR, de_DE, zh_CN style codes and matches filenames exactly. pt-BR in framework.default_locale will not find ibexa.pt_BR.yaml; you get the fallback, not an error. Same trap for the siteaccess languages codes Ibexa uses (eng-GB, ger-DE, por-PT style legacy codes) — check what the siteaccess normalises to before filing a bug.

Load-order ambiguity when overriding. Bundle translations and app translations can be registered in an order that varies by Symfony version and by how the bundle extension adds its path. Never assume your translations/ibexa.en.yaml overrode the vendor key — confirm with debug:translation, and if it loses, register your catalogue explicitly at higher priority in a custom extension rather than fighting the default.

JS strings in the back office travel a different pipeline. Admin UI JavaScript labels are usually extracted and served from a generated catalogue (JSON/translations.js), not the PHP translator. Correcting a YAML entry may not change a label rendered entirely client-side; look for the extraction/warm-up step in the Ibexa build before you spend an afternoon on it.

Pluralization needs intl. ICU plural/select syntax and the | message-choosing format will quietly misbehave without the intl PHP extension. Check php -m | grep intl in every environment image, including CI and local Docker.

Missing keys are not errors. You get the key string back. Add debug:translation --only-missing and a "no unresolved keys" assertion on the paths that matter (checkout, login, notifications) — not on everything, or the check becomes noise.

Low adoption signals a support boundary, not a quality problem. 3 stars and 0 dependents means there is no third-party documentation, no Stack Overflow corpus, and no external API stability contract. Expect to read the DI extension and Symfony's translator source when behaviour surprises you, and pin to release tags (do not track main/l10n_main) so a sync commit cannot change your UI text mid-sprint.

Extension points to remember: the config flag ibexa.ui.translations.enabled, app-level translations/ files, a custom TranslatorInterface decorator or a MessageCatalogue manipulator if you need per-siteaccess text variation, and Crowdin itself for anything that should live upstream.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc