chinleung/laravel-locales
Add multi-locale support to Laravel with simple config and helper functions. Define supported locales via app.locales or a published config, and use locale() to get/set the current locale and locales() to get/set supported locales.
Installation:
composer require chinleung/laravel-locales
For Laravel 13 projects, ensure version ^3.0 is specified.
Publish Configuration:
php artisan vendor:publish --provider="ChinLeung\LaravelLocales\LaravelLocalesServiceProvider" --tag="config"
This generates config/locales.php with default settings.
Update config/app.php:
Add your supported locales to the locales array:
'locales' => ['en', 'fr', 'es', 'zh'],
First Use Case: Dynamically set and retrieve the current locale in a controller or Blade template:
// Set locale
locale('fr');
// Get current locale
$currentLocale = locale(); // 'fr'
Locale Switching in Controllers:
use ChinLeung\LaravelLocales\Facades\Locales;
public function switchLocale($locale)
{
if (in_array($locale, Locales::getSupportedLocales())) {
Locales::setLocale($locale);
return redirect()->back();
}
abort(400, 'Unsupported locale');
}
Middleware Integration:
Register the locale middleware in app/Http/Kernel.php:
protected $middlewareGroups = [
'web' => [
// ...
\ChinLeung\LaravelLocales\Middleware\SetLocale::class,
],
];
Configure the middleware in config/locales.php:
'middleware' => [
'default' => 'en',
'cookie' => 'locale',
'header' => 'X-Locale',
],
Route Localization:
Use the locale middleware in route groups:
Route::middleware(['locale'])->group(function () {
Route::get('/blog', [BlogController::class, 'index']);
});
Blade Helpers:
<!-- Display current locale -->
<p>Current locale: {{ locale() }}</p>
<!-- Generate localized URLs -->
<a href="{{ localized_url('blog', 'fr') }}">Blog (FR)</a>
Dynamic Locale Detection: Override the default locale logic in a service provider:
public function boot()
{
Locales::macro('detectLocale', function () {
return request()->ip() === '123.45.67.89' ? 'zh' : 'en';
});
}
spatie/laravel-translatable for content localization by extending the middleware logic.config/locales.php:
'fallback_locale' => 'en',
locales() helper to mock supported locales in tests:
locales(['en', 'fr']);
$this->assertEquals(['en', 'fr'], Locales::getSupportedLocales());
Middleware Overrides:
If you use custom middleware that modifies $request->locale, it may conflict with the package’s SetLocale middleware. Ensure sequencing in app/Http/Kernel.php:
protected $middlewarePriority = [
\ChinLeung\LaravelLocales\Middleware\SetLocale::class,
// Other middleware...
];
Associative Arrays in Config:
The package supports associative arrays for locales (e.g., ['en' => 'English']), but this can cause issues with route generation. Stick to simple arrays unless explicitly needed:
// Avoid unless necessary
locales(['en' => 'English', 'fr' => 'Français']);
Session vs. Cookie Persistence:
By default, the package uses cookies to store locale preferences. If you rely on sessions, ensure config/locales.php is configured to use session storage:
'middleware' => [
'cookie' => false,
'session' => true,
],
Route Caching: Clear route cache after adding/removing locales:
php artisan route:clear
Laravel 13 Specifics:
app() facade macros. Ensure your project’s AppServiceProvider doesn’t override these.bootstrap/app.php configuration if you encounter bootstrapping issues.Locale Not Updating?:
Check if the middleware is registered and the locale cookie/session is being set. Use:
dd(request()->cookie('locale')); // For cookie storage
dd(session('locale')); // For session storage
Unsupported Locale Errors:
Verify the locale is in the app.locales array or set via locales() helper. Use:
dd(Locales::getSupportedLocales());
Route Localization Issues:
Ensure route groups with the locale middleware are properly structured. Test with:
php artisan route:list
Custom Locale Detection:
Extend the Locales facade to add custom logic:
Locales::extend('custom', function () {
return request()->header('Accept-Language') ?: config('app.locale');
});
Dynamic Locale Switching: Create a custom request macro to handle locale switching:
use Illuminate\Http\Request;
Request::macro('setLocale', function ($locale) {
if (in_array($locale, Locales::getSupportedLocales())) {
Locales::setLocale($locale);
return true;
}
return false;
});
Locale-Aware Redirects:
Override the redirect() method in a service provider:
public function boot()
{
\Illuminate\Support\Facades\Redirect::macro('localized', function ($path, $locale = null) {
$locale = $locale ?: Locales::getLocale();
return redirect()->to($locale . '/' . ltrim($path, '/'));
});
}
Priority Order:
The locales() helper takes precedence over app.locales. Override carefully:
locales(['en', 'fr']); // Temporarily overrides app.locales
Default Locale:
The package defaults to 'en'. Change it in config/app.php:
'locale' => 'fr',
Middleware Configuration:
The SetLocale middleware checks for locales in this order:
/{locale}/blog).locale).locale).X-Locale).app.locale.Avoid Repeated Calls:
Cache the result of Locales::getSupportedLocales() if called frequently:
$locales = cache()->remember('supported_locales', now()->addHours(1), function () {
return Locales::getSupportedLocales();
});
Minimize Middleware Overhead:
Only apply the locale middleware to route groups that need it, not globally.
How can I help you explore Laravel packages today?