Installation
composer require c4/translation-bundle
Add to config/app.php under providers:
C4\TranslationBundle\TranslationBundle::class,
Configuration Publish the default config:
php artisan vendor:publish --provider="C4\TranslationBundle\TranslationBundle" --tag="config"
Key settings to review:
default_locale (e.g., en)supported_locales (e.g., ['en', 'fr', 'de'])fallback_locale (e.g., en)First Use Case: Basic Translation
Define translations in resources/lang/{locale}/messages.php:
return [
'welcome' => 'Welcome, :name!',
];
Use in Blade:
{{ trans('messages.welcome', ['name' => 'John']) }}
Or in PHP:
__('messages.welcome', ['name' => 'John']);
Dynamic Locale Switching Use middleware to set locale from URL or session:
// app/Http/Middleware/SetLocale.php
public function handle($request, Closure $next) {
$locale = $request->segment(1) ?? config('app.locale');
app()->setLocale($locale);
return $next($request);
}
Register in app/Http/Kernel.php:
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\SetLocale::class,
// ...
],
];
Locale Prefix in Routes
Configure routes to handle /{locale}/...:
Route::prefix('{locale}')->where('locale', implode('|', config('translation.supported_locales')))->group(function () {
Route::get('/', 'HomeController@index');
});
resources/lang/{locale}/{namespace}.json:
// resources/lang/fr/messages.json
{
"welcome": "Bienvenue, :name !"
}
__('messages.welcome', ['name' => 'Marie']);
// config/translation.php
'validation' => [
'custom' => [
'required' => [
'fr' => 'Le champ :attribute est requis.',
'de' => 'Das Feld :attribute ist erforderlich.',
],
],
];
config/translation.php:
'fallbacks' => [
'fr' => ['en'],
'de' => ['en'],
],
en if fr or de are missing.messages.php).config/translation.php:
'namespaces' => [
'validation' => 'validation',
'auth' => 'auth',
],
{{ trans('validation.required', ['attribute' => 'email']) }}
php artisan translation:dump
Locale Not Set
app()->getLocale() returns null, translations will fail silently.config('app.locale') is set and middleware is applied.Missing Fallback Config
fallback_locale is not set, missing translations will return the key instead of the key itself.fallback_locale in config/translation.php.JSON Syntax Errors
Caching Issues
php artisan view:clear
php artisan cache:clear
Namespace Conflicts
messages.php and messages.json), the last loaded file wins.Route Locale Conflicts
{locale} in routes, ensure it doesn’t conflict with other route parameters.where() constraints:
Route::get('/{locale}/user/{id}', function ($locale, $id) { ... })
->where('locale', implode('|', config('translation.supported_locales')));
Check Loaded Translations Dump all loaded translations for debugging:
dd(app('translator')->getLoader()->getNamespaces());
Verify Locale Log the current locale to ensure it’s set correctly:
\Log::debug('Current locale:', ['locale' => app()->getLocale()]);
Test Fallback Logic Temporarily remove a translation file to test fallback:
mv resources/lang/fr/messages.php resources/lang/fr/messages.php.bak
Custom Loaders Extend the loader to support additional file formats (e.g., YAML):
// app/Providers/TranslationServiceProvider.php
public function boot() {
$loader = $this->app['translator']->getLoader();
$loader->addLoader('yaml', function () {
return new YamlLoader();
});
}
Dynamic Translation Sources Fetch translations from an API or database:
$loader = $this->app['translator']->getLoader();
$loader->addLoader('api', function () {
return new ApiTranslationLoader();
});
Middleware for Locale Persistence Store locale in session or cookies for better UX:
// app/Http/Middleware/PersistLocale.php
public function handle($request, Closure $next) {
if ($request->hasCookie('locale')) {
app()->setLocale($request->cookie('locale'));
}
return $next($request);
}
Translation Editor Build a simple admin interface to edit translations via a form:
// routes/web.php
Route::get('/admin/translations', 'TranslationController@edit');
Route::post('/admin/translations', 'TranslationController@update');
Cache Translations Enable translation caching for production:
// config/translation.php
'cache' => env('APP_ENV') === 'production',
Preload Translations Preload translations for critical locales during boot:
// app/Providers/AppServiceProvider.php
public function boot() {
app('translator')->load('messages', 'en');
app('translator')->load('messages', 'fr');
}
Avoid Over-Translating Only translate strings that appear in the UI. Avoid translating:
if ($user->is_active)).How can I help you explore Laravel packages today?