Installation:
composer require braunstetter/localized-routes
Add the bundle to config/bundles.php (Symfony) or register the service provider in config/app.php (Laravel):
// Laravel (if using a custom provider)
Braunstetter\LocalizedRoutesBundle\LocalizedRoutesServiceProvider::class,
Configure Routes:
Update routes/web.php to include the locale prefix in your route definitions:
Route::prefix('{_locale}')->group(function () {
Route::get('/', 'HomeController@index');
});
Ensure _locale is defined in your middleware (e.g., app/Http/Middleware/SetLocale.php).
Middleware Setup:
Add the LocalizedRoutesMiddleware to your HTTP kernel (e.g., app/Http/Kernel.php):
protected $middlewareGroups = [
'web' => [
// ...
\Braunstetter\LocalizedRoutesBundle\Http\Middleware\LocalizedRoutesMiddleware::class,
],
];
First Use Case:
Access /en/home (or your default locale) to test. The middleware will redirect /home to /en/home if the locale is en.
Locale Detection:
app/Http/Middleware/SetLocale.php):
public function handle($request, Closure $next) {
$locale = $request->segment(1) ?? config('app.locale');
app()->setLocale($locale);
return $next($request);
}
Route Grouping:
{_locale} prefix:
Route::prefix('{_locale}')->middleware('locale')->group(function () {
Route::get('/news', 'NewsController@index');
Route::resource('posts', 'PostController');
});
Route::middleware('guest')->group(function () {
Route::get('/login', 'AuthController@login');
});
Dynamic Locale Switching:
@foreach(config('app.locales') as $locale)
<a href="{{ url()->current(), str_replace(url()->current(), '', $locale) }}">
{{ $locale }}
</a>
@endforeach
API Localization:
Route::prefix('{_locale}')->middleware('api', 'locale')->group(function () {
Route::apiResource('posts', 'PostController');
});
Laravel Localization:
Combine with laravel-localization for seamless locale switching and URL generation:
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
LaravelLocalization::setLocale();
Route Caching: Disable route caching during development if locales are dynamic:
Route::getCache()->forever();
Fallback Locales:
Configure fallback locales in config/app.php:
'fallback_locales' => ['en', 'de'],
Locale Conflict:
_locale is also a valid route parameter (e.g., /posts/{_locale}), the middleware may misinterpret it. Solution: Use a unique placeholder like {_lang}:
Route::prefix('{_lang}')->group(...);
Redirect Loops:
LocalizedRoutesMiddleware runs before other middleware that might modify the request (e.g., VerifyCsrfToken). Solution: Order middleware correctly in Kernel.php.Case Sensitivity:
EN vs. en) may cause issues. Solution: Normalize locales in middleware:
$locale = strtolower($request->segment(1));
Caching Issues:
php artisan route:cache) may break dynamic locales. Solution: Clear cache after locale changes:
php artisan route:clear
Check Middleware Order:
Use php artisan route:list to verify routes are prefixed correctly. Missing prefixes often indicate middleware misconfiguration.
Log Locale Detection:
Add debug logs in LocalizedRoutesMiddleware:
\Log::debug('Detected locale:', [$request->segment(1)]);
Test Redirects:
Use php artisan route:debug to trace redirects and ensure no infinite loops.
Custom Locale Sources: Override the default locale detection logic by extending the middleware:
class CustomLocalizedRoutesMiddleware extends LocalizedRoutesMiddleware {
protected function getLocaleFromRequest(Request $request) {
return $request->cookie('locale') ?? parent::getLocaleFromRequest($request);
}
}
Exclude Routes:
Skip localization for specific routes by adding a skip_localization flag:
Route::get('/health', 'HealthController@check')->middleware('skip_localization');
Extend the middleware to check for this flag.
Subdomain Support:
Integrate with laravel-localization for subdomain-based locales (e.g., en.example.com):
Route::prefix('{_locale}')->domain(['{locale}.example.com'])->group(...);
Fallback Logic: Customize fallback behavior in the middleware:
protected function getFallbackLocale($locale) {
return config('app.fallback_locales')[0] ?? config('app.locale');
}
How can I help you explore Laravel packages today?