laravel-translation-manager maintained by jeffersongoncalves

Laravel Translation Manager
Override any Laravel translation from the database — your app's lang/{locale}/*.php groups, the lang/{locale}.json strings and the lines of every installed package (filament-panels::, validation, your plugins…) — without a deploy. Find the keys missing in each locale, and when you're happy, export the overrides back to lang/ so they live in Git.
The lang files stay the source of truth: the package only lays the database overrides over what the framework's file loader returns. For an admin UI, use jeffersongoncalves/filament-translation-manager.
Installation
composer require jeffersongoncalves/laravel-translation-manager
php artisan migrate
php artisan translation-manager:scan
Optionally publish the config:
php artisan vendor:publish --tag=translation-manager-config
How it works
translation-manager:scanreads every lang file — app groups, JSON, and the groups of each registered package namespace (including the ones you published tolang/vendor) — for every locale, and stores the values in thetranslation_linestable (sourcecolumn). Re-run it after adding keys or installing packages; it never touches your overrides.- An override is a value in the
textcolumn for a locale.__(),trans()and@langreturn it instead of the file value. An empty override falls back to the file. - Overrides are cached per namespace + group and the cache is flushed whenever a line is saved or deleted.
- If the table doesn't exist yet (fresh install, migrations pending) the files are used as-is — translations never break the app.
- Long-running processes (queue workers, Octane) keep the groups they already loaded — restart them after changing overrides.
Usage
use JeffersonGoncalves\TranslationManager\Models\TranslationLine;
// app group: lang/pt_BR/messages.php → messages.welcome
TranslationLine::query()->updateOrCreate(
['namespace' => '*', 'group' => 'messages', 'key' => 'welcome'],
['text' => ['pt_BR' => 'Olá!']],
);
// package line: filament-panels::pages/dashboard.title
TranslationLine::query()
->where(['namespace' => 'filament-panels', 'group' => 'pages/dashboard', 'key' => 'title'])
->first()
?->update(['text' => ['pt_BR' => 'Início']]);
// keys with neither a file value nor an override in a locale
TranslationLine::query()->missing('pt_BR')->get()->map->fullKey();
namespace is * for the app's own lines and group is * for JSON lines. $line->value('pt_BR') returns what __() would, $line->fullKey() the key you'd pass to it.
Export to lang files
php artisan translation-manager:export # every locale
php artisan translation-manager:export --locale=pt_BR # one locale
php artisan translation-manager:export --clear # and drop the exported overrides from the database
| Override | Written to |
|---|---|
| JSON line | lang/{locale}.json |
| App group | lang/{locale}/{group}.php |
| Package line | lang/vendor/{namespace}/{locale}/{group}.php — the file Laravel already lays over the package's own |
Existing keys in those files are kept; only the overridden keys are added or replaced.
Configuration
| Key | Default | |
|---|---|---|
table |
translation_lines |
|
locales |
[] |
locales to scan and manage; empty = every locale found in lang/ plus app.locale and app.fallback_locale |
namespaces.include |
[] |
package namespaces to scan; empty = all |
namespaces.exclude |
[] |
package namespaces to skip |
cache_store |
null |
cache store for the overrides; null = default |
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.