We've covered the core string Localization, but there are more aspects that we can translate. For example, routes:
Take a look at the URL bar
In the images, you should see that the routes are translated as well. This is done by the mcamara/laravel-localization package.
This package helps you manage your routes in multiple languages. It also provides a great set of middlewares and helpers to help you with translations - such as detecting the user's language and redirecting them to the correct route, translating routes, etc.
Installation
To install the package, there are quite a few steps. First, we need to install the package:
composer require mcamara/laravel-localization
Then, we need to publish the config file:
php artisan vendor:publish --provider="Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider"
And finally register the middleware in the app/Http/Kernel.php
file:
app/Http/Kernel.php
protected $routeMiddleware = [ // ... 'localize' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class, 'localizationRedirect' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class, 'localeSessionRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class, 'localeCookieRedirect' => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class, 'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class];
This way, we have everything we need to start translating!
Setting Up the Routes
To set our routes, we need to modify how they are defined a little bit by adding a parent group:
routes/web.php
Route::group([ 'prefix' => LaravelLocalization::setLocale(), 'middleware' => ['localeSessionRedirect', 'localizationRedirect']], function () { Route::get('/', function () { return view('welcome'); }); // ... require __DIR__ . '/auth.php';});
This code will achieve the following:
- Prefix the routes with a locale (e.g.
/en/
or/es/
) - Redirect the user to the correct locale if they are not using it
Combined with default configuration values found in config/laravellocalization.php
- it will also attempt to guess the user's locale based on the browser's settings.
Enabling Different Languages
To enable different languages, we need to modify the config/laravellocalization.php
file:
config/laravellocalization.php
// ...'supportedLocales' => [ 'en' => ['name' => 'English', 'script' => 'Latn', 'native' => 'English', 'regional' => 'en_GB'], //'en-AU' => ['name' => 'Australian English', 'script' => 'Latn', 'native' => 'Australian English', 'regional' => 'en_AU'], //'en-GB' => ['name' => 'British English', 'script' => 'Latn', 'native' => 'British English', 'regional' => 'en_GB'], //'en-CA' => ['name' => 'Canadian English', 'script' => 'Latn', 'native' => 'Canadian English', 'regional' => 'en_CA'], //'en-US' => ['name' => 'U.S. English', 'script' => 'Latn', 'native' => 'U.S. English', 'regional' => 'en_US'], 'es' => ['name' => 'Spanish', 'script' => 'Latn', 'native' => 'español', 'regional' => 'es_ES'],],// ...
Adding the Language Switcher
Lastly, we need to add a language switcher to our application. We can do this by adding a simple blade template:
resources/views/layouts/navigation.blade.php
{{-- ... --}}@foreach(LaravelLocalization::getSupportedLocales() as $localeCode => $properties) <x-nav-link rel="alternate" hreflang="{{ $localeCode }}" :active="$localeCode === app()->getLocale()" href="{{ LaravelLocalization::getLocalizedURL($localeCode, null, [], true) }}"> {{ ucfirst($properties['native']) }} </x-nav-link>@endforeach<x-dropdown align="right" width="48">{{-- ... --}}
This will add a language switcher to the top of the page:
Fixing Route Caching
By default, the Mcmara package will not work with route caching. To fix this, we need to add a few lines to the RouteServiceProvider.php
file:
app/Providers/RouteServiceProvider.php
// ... class RouteServiceProvider extends ServiceProvider{use \Mcamara\LaravelLocalization\Traits\LoadsTranslatedCachedRoutes; // ...
And change the artisan command we use. Instead of php artisan route:cache
we should use php artisan route:trans:cache
.
Clearing route cache works with php artisan route:clear
but it will leave some mess in the bootstrap/cache
folder. To avoid it - we should also use the php artisan route:trans:clear
command.
Displaying All Routes
Another command that differs while using this package is php artisan route:list
. While it still works, it will only give you a base overview:
But if we use php artisan route:trans:list {locale}
we will get a more detailed overview:
Extended Package Functionality
While we've covered the base package functionality to get your routes going - there are a few more things that you can do with the package.
- Show or hide the default locale in the URL
- Ignore specific routes
- Translating the routes
All of these require a bit more work, so let's get started!
Showing or Hiding the Default Locale in URL
By default, the Mcmara package will show the default locale in the URL:
/en/dashboard
/es/dashboard
This is not always desirable, so we can change this by modifying the config/laravellocalization.php
file:
config/laravellocalization.php
// ...'hideDefaultLocaleInURL' => true,// ...
After this change you'll have the following URLs:
/dashboard
/es/dashboard
Ignoring Specific Routes
There are cases where it doesn't matter if the route is localized or not. For example, a route that checks for messages from a queue.
routes/web.php
Route::group([ 'prefix' => LaravelLocalization::setLocale(), 'middleware' => ['localeSessionRedirect', 'localizationRedirect']], function () { // ... Route::get('/queue-check', QueueCheckController)->name('queue.check'); // ...});
Trying to load this page (or make a JSON request to it) will result in a URL change to:
/en/queue-check
Which might not be what we want. Even if we defined the route in a prefixed group - we can ignore the route by adding it to the config/laravellocalization.php
file:
config/laravellocalization.php
// ...'urlsIgnored' => [ '/queue-check',],// ...
And now it will not contain any locale prefix:
/queue-check
Translating the Routes
Another great extension to the package is the ability to translate the routes. This is especially useful if you want to have a different URL for the same page in different languages. For example, if you want to have a different URL for the dashboard page in Spanish:
/en/dashboard
/es/panel
To achieve this, we need to modify the routes/web.php
file and add a middleware:
routes/web.php
Route::group([ 'prefix' => LaravelLocalization::setLocale(), 'middleware' => ['localeSessionRedirect', 'localizationRedirect', 'localize'] // <- Add `localize` middleware], function () { // ...});
This way, we told the system that we expect the routes to be translated. Now we need to add the translations to the resources/lang/{locale}/routes.php
file:
resources/lang/en/routes.php
return [ 'dashboard' => 'dashboard',];
And the translation for Spanish:
resources/lang/es/routes.php
return [ 'dashboard' => 'panel',];
The last step before seeing it in action is to add the translated routes to the routes/web.php
file by adding LaravelLocalization::transRoute('routes.dashboard')
instead of the route path:
routes/web.php
Route::get(LaravelLocalization::transRoute('routes.dashboard'), [DashboardController::class, 'index'])->middleware(['auth', 'verified'])->name('dashboard');
Once this is done, switching languages will switch the URL as well:
/en/dashboard
/es/panel
Translated Routes Issues
While this is a great feature, there are a few issues with it. One of those is described in the package documentation - the POST
method is not working with translated routes.
To fix this, you have to use the LaravelLocalization::localizeUrl($route)
facade instead of the route()
helper. So it might be best to translate only the GET
routes.
Conclusion
This package is really versatile in terms of route localization control. Combining this with previously covered static text translation - you'll definitely have a great time with your multilingual application.
It's a great Package!
Thanks a lot for clarification! I was strugling trying to make this package worked for some time, this article really helped.
using the mcamara/laravellocalisation package I ran into a problem with livewire: calls to livewire/update on a language other than the default language were being sent in 404.
I analysed the code there livewire and saw that what failed was Livewire\Mechanisms\PersistentMiddleware\PersistentMiddleware::getRouteFromRequest($request) linking routes with
failing this request returns 404.
To solve i ended prepending to /livewire/update the current locale so livewire can find its endpoint
This is very helpful! Fixed the error for me on my search component. Many thanks! But in Laravel 11, you need to add this method to the boot method of the
App/Providers/AppServiceProvider.php
file instead, as there is noApp\Providers\RouteServiceProvider.php
file anymore.Thank you for the info, i have to migrate from 10 to 11 and your suggestion is really useful :)