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

Translation Bundle Laravel Package

tbaronnat/translation-bundle

A Symfony bundle for managing application translations from a database instead of flat files. It provides services and tooling to store, retrieve, and organize translation messages across locales, simplifying multilingual content maintenance.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a low-adoption package (no stars, no dependents), so treat the source as the documentation. Budget 20 minutes to read it before wiring anything into a project.

  1. Check compatibility first. Open the repo's composer.json and confirm the Symfony/PHP constraints match your app. A bundle described only as "simple translation bundle system with Symfony integration" is likely built against one Symfony major version; on a newer skeleton it may boot but fail on deprecated service definitions.
  2. Install and register.
    composer require tbaronnat/translation-bundle
    
    Flex will only auto-register the bundle if a recipe exists. If config/bundles.php is unchanged afterwards, add the bundle class manually — grab its exact FQCN from the package's src/ directory rather than guessing.
  3. Where to look first, in this order:
    • src/DependencyInjection/Configuration.php — the config tree. The root key is normally the underscored bundle name; confirm it here before writing any YAML, or you'll get "unrecognized option" on boot.
    • src/DependencyInjection/*Extension.php and Resources/config/services.* — which services exist and whether the bundle decorates translator or registers a separate loader.
    • Any Entity/, Model/, or Repository/ classes — this tells you whether translations live in the database, in files, or both.
    • src/Command/ and src/Controller/ — the day-to-day surface area.
  4. Discover what it gives you.
    php bin/console list | grep -i translat
    php bin/console debug:router | grep -i translat
    php bin/console debug:container --tag=translation.loader
    
  5. First use case: import your existing translations/messages.en.yaml (or whatever the bundle consumes), edit one string through the bundle's UI or command, then load a page that renders it. That single round-trip proves the loader is actually winning over Symfony's default file loader — which is the only thing that matters about this package.

Implementation Patterns

Decide the source of truth up front. There are two viable postures and you must pick one deliberately:

  • Bundle-first: the bundle's store is canonical, and you export to YAML for version control in CI. Good for content teams editing copy without deploys.
  • Files-first: YAML stays canonical, the bundle is only an editing/override layer for hotfixes. Good for engineering-led teams who want diffs in code review.

Mixing the two without a rule produces strings that "revert themselves" after the next deploy.

If it decorates the translator, check the decoration priority in the service definition. A DB-backed loader that runs last will never override your file translations. When layering, ensure your file catalogues remain as a fallback so a missing DB row doesn't blank out a page.

Standard workflow for a content edit:

// Wrap the write in a transaction and invalidate whatever cache the bundle uses
DB::transaction(fn () => $repo->upsert($domain, $locale, $key, $value));
Cache::forget("translations.{$locale}");

Then verify with php bin/console debug:translation <locale> <domain> — it reports which loader supplied each message, which is the fastest way to confirm your edit took effect.

Export for CI. A small custom command that dumps the bundle's store to translations/*.yaml gives you reviewable diffs and a rollback path, and insulates you if the package is later abandoned:

foreach ($repo->allByLocale($locale) as $row) {
    $catalogue[$row->getDomain()][$row->getKey()] = $row->getValue();
}

Guard any admin routes. If the bundle ships a controller, it likely ships no firewall rules. Add access_control entries before enabling it anywhere reachable from the internet — an editable translation store is effectively a content-injection endpoint.

Testing. Boot the kernel in a functional test, write a row through the bundle's service, and assert $translator->trans('key', [], 'domain', 'fr') returns it. Use a separate test database so you're not asserting against seed data.

Gotchas and Tips

  • No community safety net. Zero stars and zero dependents means no Stack Overflow answers and no blog posts. Pin the exact version in composer.json, and if you depend on it heavily, fork it or be prepared to vendor the loader into your own codebase — it's likely a few hundred lines.
  • Cache is the number one false alarm. Translation catalogues are compiled and cached. After an edit, php bin/console cache:clear in dev, and remember opcache in prod. If edits "don't appear," check this before debugging the loader.
  • Root config key mismatch. Always confirm the alias in Configuration::getRootNode(). Writing translation_bundle: when the extension expects something else produces a confusing "unrecognized option" rather than a helpful error.
  • Service is private by default on modern Symfony. debug:container --show-private to find it; don't assume you can $container->get() it from a controller — inject it.
  • Domain handling. Symfony message keys are scoped by domain (messages, validators, security). A naive DB loader that keys only on locale + key will silently collide across bundles. Verify the schema has a domain column; if it doesn't, don't store validator messages there.
  • Fallback locale. DB loaders frequently bypass framework.translator.fallbacks. Test explicitly: request a key that exists only in the fallback locale and confirm it resolves rather than returning the raw key.
  • Schema management. If the bundle ships entities, generate a migration (doctrine:migrations:diff) and commit it. Don't rely on doctrine:schema:update in any environment you care about, and don't assume the bundle's own migrations run under your app's migration config.
  • Extension points worth knowing: decorate the bundle's loader or repository service in services.yaml to add caching or auditing without forking; use a compiler pass if you need to swap the implementation wholesale. Both are cheaper than editing vendor code.
  • Unmaintained risk. With no stars, assume no upstream fixes. Add a smoke test that asserts a known translation resolves, so a future Symfony upgrade that breaks the bundle fails loudly in CI rather than silently rendering raw keys in production.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel