spatie/laravel-translation-loader
Store Laravel/Lumen translation strings in the database while keeping the familiar __() helper. Mix file and DB translations; DB values override files. Extendable to other translation sources via custom providers.
Start by installing the package via Composer and replacing Laravel’s built-in TranslationServiceProvider with Spatie\TranslationLoader\TranslationServiceProvider in config/app.php. Then publish and run the migration to create the language_lines table. After that, create a sample translation using the LanguageLine model:
use Spatie\TranslationLoader\LanguageLine;
LanguageLine::create([
'group' => 'auth',
'key' => 'failed',
'text' => [
'en' => 'These credentials do not match our records.',
'es' => 'Estas credenciales no coinciden con nuestros registros.',
],
]);
You can immediately use it with the familiar __() helper — no code changes needed:
__('auth.failed'); // → "These credentials do not match our records."
app()->setLocale('es');
__('auth.failed'); // → "Estas credenciales no coinciden con nuestros registros."
lang/en/auth.php), and use the database for dynamic content (e.g., CMS-managed pages, user-generated labels). Database translations override file-based ones.LanguageLine for content managers to add/edit translations. Cache the results with LanguageLine::flushGroupCache('validation') after bulk updates.YamlTranslationLoader) that implements the TranslationLoader interface and register it in translation_loaders config to pull translations from external sources like YAML files or remote APIs.messages.errors.*), store them in a single row with group = '*' and keys like messages.errors.required — the loader treats them like nested arrays.__() call may query the DB unless caching is enabled. Since this package replaces Laravel’s translation loader, consider enabling Laravel’s built-in config caching (config:cache) — though note that the DB loader itself doesn’t cache by default. You may need to implement custom caching in your loader or wrap LanguageLine::getForLocale() in a cache block.group.key, the DB wins. To debug, use app('translation.loader') to inspect which loaders return what.''. Now they return null, so be mindful in views — use {{ __(...) ?? 'fallback' }}.config('translation-loader.model')’s table property, ensure your migrations reference the same (v2.7.3+ fixes hardcoded table name issues).model config option lets you extend LanguageLine (e.g., add status or updated_by fields), but you must ensure it implements the same structure and is mutable via create()/update().How can I help you explore Laravel packages today?