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.
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!
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:
/en/
or /es/
)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.
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'],],// ...
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:
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.
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:
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.
All of these require a bit more work, so let's get started!
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
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
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
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.
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.