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

Translations Bundle Laravel Package

modera/translations-bundle

A Laravel bundle for managing application translations from a database or files, with tools for editing strings across locales, organizing language lines, and keeping multilingual content in sync.

View on GitHub
Deep Wiki
Context7

Getting Started

There is no installation path into a Laravel app. This is a Symfony bundle (Modera\TranslationsBundle, registered via AppKernel::registerBundles() in the Symfony 2/3 era it shipped in — last release 2016-06-10). It has no service provider, no facade, no config/ publish step, no Laravel auto-discovery. composer require modera/translations-bundle inside a Laravel project will install code you cannot boot, because there is no Kernel to register it with.

So "getting started" for a Laravel developer means one of two things:

  1. Reading it as a reference design (the recommended path). Clone the repo and start in the console-command layer — that is where the four-stage loop lives: extract tokens from templates → persist to a DB table → edit → dump back to physical files. Read the extractor first; it is the only piece with transferable logic. Read the dumper second; it shows the output-format decisions you will have to re-make for Laravel.
  2. Running it as intended (only if you actually have a Symfony 2/3 app). composer require modera/translations-bundle, register the bundle in AppKernel, run Doctrine schema update for its entities, configure its translation domains and source paths, then invoke the extract and dump commands. Expect to pin PHP 5.6/7.0-range and Symfony ≤3.x — there is no PHP 8 or Symfony 4+ guarantee, and the repo is a [READ-ONLY] subtree split of a larger Modera monorepo, so any fix is a permanent fork.

Your first use case in Laravel is not "install this." It is: take the four-stage model and implement it natively as four Artisan commands — translations:extract, translations:sync, translations:dump, and a diff check in CI. That is a contained piece of work (roughly a sprint), and it is the only way the pattern survives contact with Laravel's lang/ conventions, which this bundle does not target.

Implementation Patterns

The loop the bundle implements (and what to mirror):

  • Extract — walk source templates and PHP files, find translation calls (trans, transChoice in the Symfony era), derive a key and a group/domain, emit a manifest.
  • Persist — write the manifest into Doctrine-managed tables (message + per-locale value), so the database becomes the working surface and files remain the deploy artifact.
  • Translate — an admin UI where a non-engineer edits values per locale. This is the real value proposition: the DB exists so a translator does not need a Git checkout.
  • Dump — compile DB rows back to physical translation files in Symfony's resource format (Resources/translations/*.yml|xliff).

Mapping each stage to native Laravel:

  • Extractor. Scan app/, resources/views/, routes/ for __('...'), @lang('...'), trans('...'), trans_choice('...'). Match the group from the dotted namespace (messages.welcome → group messages, key welcome), and JSON keys as a separate group (lang/{locale}.json).
  • Persistence. A single translations table: (locale, group, key, value, status, source_hash) with a unique index on the first three. Status (new / translated / stale) is what makes the admin surface usable; source_hash lets you detect when an English string changed and mark downstream locales stale.
  • Resolution order. The standard pattern is DB value overrides file value, file remains the fallback. In Laravel that means decorating the translator or registering a custom loader with priority above FileLoader — do not replace FileLoader, or you lose the ability to boot a fresh checkout before the DB is populated.
  • Translation surface. A Filament or Nova resource over the translations table is the Laravel-native equivalent of the bundle's admin UI. Filter by locale, status, and group; that is the whole screen.
  • Dumper. Write lang/{locale}/{group}.php with var_export and lang/{locale}.json with json_encode(..., JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE). Sort keys deterministically before writing — the single most important detail for reviewable diffs.

Integration tip — the CI gate is the pattern, not the code. After translations:dump, run git diff --exit-code lang/ in CI. If the dump produces changes, the DB and files have drifted and the build should fail. This one check is what keeps the whole pipeline honest, and it is cheaper and more reliable than anything the bundle itself provides.

Workflow that works day-to-day:

  1. Developer adds __('checkout.title') in a blade file.
  2. translations:extract picks it up, translations:sync creates the row in new status.
  3. Translator fills values in the admin UI; status flips to translated.
  4. translations:dump runs as a single-owner job on main (not developer-local), regenerates files, commits.
  5. Deploy ships the files; runtime reads files unless a DB override exists for hotfixes.

Gotchas and Tips

  • Format mismatch is the silent killer. The bundle dumps Symfony resource formats; Laravel's FileLoader reads PHP arrays and JSON. Dumping XLIFF/YAML into lang/ produces "translations exist but nothing renders." If you ever bridge the two, write a one-time converter and a smoke test that asserts a known key resolves per locale.
  • Extraction rules won't match Laravel syntax. A 2016 Symfony extractor knows trans/transChoice and Twig's |trans. It will not match @lang, {{ __('...') }}, or trans_choice. Any port starts with rewriting the extractor, not reusing it.
  • Pluralization. Symfony 2/3 used transChoice range syntax; Laravel uses pipe-delimited pluralization ('apples' => 'one apple|:count apples'). A 2016 extractor will not emit Laravel's format, and there is no ICU MessageFormat or gender/context support to salvage. If you need those, this pattern (and this package) is the wrong tool — that's a TMS problem.
  • Auto-derived keys are a trap. Keys derived from source text change when copy changes, orphaning translations and creating collisions. Prefer explicit keys (checkout.title) and treat the English string purely as content.
  • Dump ordering must be deterministic. Unsorted output produces noisy diffs, merge conflicts across branches, and a CI gate that cries wolf. Sort keys, fix encoding flags, and run the dump from one job.
  • DB-overrides-file needs cache discipline. If you decorate the translator to check the DB first, remember Laravel caches translations per request and via cache:clear. Stale overrides after an admin edit are the most common "why didn't my string show up" ticket.
  • Debugging the resolution order: bind a custom loader, then confirm precedence in tinker (app('translator')->get('group.key')), and check config/app.php locale plus the lang/ path Laravel actually resolves. Most "translations don't load" reports are a loader registration that never took effect.
  • Extension points worth noting: the bundle's abstraction is provider/domain per source; the Laravel analogue is loader + group. That is the seam to replicate if you build natively — do not build around a Symfony-style bundle registration.
  • Compatibility reality. Last release 2016, one star, zero dependents. Expect breakage on PHP 8 (removed functions, stricter typing) and anything Symfony 4+. There are no security patches and no upstream merge path — it is a [READ-ONLY] subtree split, so a fix is a hard fork you own forever. Treat it as a spec, not a dependency; adopt the extract→persist→translate→dump pattern, build it in ~a sprint of native Artisan commands, and gate it in CI.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource