mcamara/laravel-localization
Laravel localization package for i18n: detect locale from browser, redirect and persist locale via session/cookie, define routes once with localized URL prefixes and translatable routes, optional hiding of default locale, plus helpers like language selectors.
Installation:
composer require mcamara/laravel-localization
Publish config:
php artisan vendor:publish --provider="Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider"
Configure Locales (config/laravellocalization.php):
'supportedLocales' => ['en', 'es', 'fr'],
'defaultLocale' => 'en',
'hideDefaultLocaleInURL' => true,
Register Middleware (app/Http/Kernel.php or bootstrap/app.php):
'localize' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
'localeSessionRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
Wrap Routes (routes/web.php):
Route::group(['prefix' => LaravelLocalization::setLocale()], function() {
Route::get('/', function() { return view('home'); });
Route::get('/about', function() { return view('about'); });
});
First Use Case:
Access / → Auto-detects locale (if useAcceptLanguageHeader is true) or redirects to /en.
Access /es/about → Shows Spanish version of /about.
Route Grouping:
Always wrap localized routes in LaravelLocalization::setLocale().
Route::group(['prefix' => LaravelLocalization::setLocale()], function() {
// All localized routes here
});
Middleware Stack: Use these middleware in order for optimal behavior:
'middleware' => [
'localeSessionRedirect', // Persists locale in session
'localizationRedirect', // Handles default locale hiding
'localeViewPath' // Sets view path to `/resources/views/{locale}/`
]
URL Generation:
{{ LaravelLocalization::localizeUrl('/about') }} // e.g., `/es/about`
{{ LaravelLocalization::getLocalizedURL('fr') }} // e.g., `/fr/about`
{{ LaravelLocalization::getNonLocalizedURL('/es/about') }} // `/about`
Dynamic Route Parameters:
Use getURLFromRouteNameTranslated for routes with parameters:
<a href="{{ LaravelLocalization::getURLFromRouteNameTranslated(
App::currentLocale(),
'routes.post',
['id' => $post->id]
) }}">
{{ $post->title }}
</a>
View Localization:
resources/views/{locale}/ (e.g., es/home.blade.php).localeViewPath middleware to auto-switch view paths.Language Switcher:
Use getLocalesOrder() to render a dropdown:
@foreach(LaravelLocalization::getLocalesOrder() as $locale)
<a href="{{ LaravelLocalization::getLocalizedURL($locale) }}">
{{ LaravelLocalization::getLocaleNativeName($locale) }}
</a>
@endforeach
<form action="{{ LaravelLocalization::localizeUrl('/submit') }}" method="POST">
Route::prefix('api')->group(function() {
// Non-localized API routes
});
php artisan route:cache) if using this package (dynamic routes).
Use LaravelLocalization::disableCache() in AppServiceProvider for testing.Route Caching Conflict:
php artisan route:cache fails due to dynamic routes.niels-numbers/laravel-localizer for static routes.POST Requests:
<form action="{{ LaravelLocalization::localizeUrl('/submit') }}" method="POST">
Validation Messages:
resources/lang/{locale}/validation.php or use:
$validator->setAttributeNames([
'field' => trans('validation.attributes.field'),
]);
Duplicate Content (SEO):
/en/page and /page as duplicates.LaravelLocalizationRedirectFilter middleware to canonicalize URLs.Session/Cookie Conflicts:
session()->forget('locale');
// or
Cookie::queue(Cookie::forget('locale'));
dd(LaravelLocalization::getCurrentLocale());
localize middleware runs before localeSessionRedirect or localeCookieRedirect.useAcceptLanguageHeader temporarily in config for testing:
'useAcceptLanguageHeader' => false,
Custom Locale Detection:
Extend Mcamara\LaravelLocalization\Detectors\DetectorInterface to add logic (e.g., user role-based locales).
Dynamic Locale Switching:
Override AppServiceProvider::boot() to force a locale:
LaravelLocalization::setForcedLocale('es');
View Path Overrides:
Modify localeViewPath middleware to use custom paths:
public function handle($request, Closure $next) {
View::addNamespace('custom', resource_path('views/custom/' . app()->getLocale()));
return $next($request);
}
URL Ignore Patterns: Exclude specific routes from localization in config:
'urlsIgnored' => [
'admin/*',
'api/*',
],
LaravelLocalization::disableCache();
localeCookieRedirect instead of localeSessionRedirect if cookies are acceptable.LaravelLocalization::setForcedLocale('fr');
$response = $this->get('/about');
$response->assertRedirect('/fr/about');
LaravelLocalization::disableCache() in tests to avoid stale cached routes.
```markdown
### Common Issues (From README)
| Issue | Solution |
|--------------------------------|--------------------------------------------------------------------------|
| POST not working | Localize form actions: `localizeUrl('/submit')` |
| MethodNotAllowedHttpException | Ensure middleware order: `localize` → `localeSessionRedirect` |
| Validation in default locale | Override `resources/lang/{locale}/validation.php` or use `setAttributeNames` |
How can I help you explore Laravel packages today?