Laravel gives you all the necessary pieces to create an application that works in multiple languages, but it doesn't prescribe all the details of how to implement it. That can be useful, because it provides ultimate flexibility, but it can also be a bit overwhelming if you're not sure where to start.
Here's a very simple middleware-based approach that we have used. Our goal was something that doesn't require code spread throughout the application, and that also allows you to include the desired language in any arbitrary URL, for example sending an email to someone in French and having the links load the site in French.
First, we need to create the files to hold our translation strings:
// resources/lang/en.json
{
"Hello": "Hello"
}
// resources/lang/es.json
{
"Hello": "Hola"
}
// resources/lang/fr.json
{
"Hello": "Bonjour"
}
A real app would have many more translation strings, but we're keeping it simple for this example. Next, we need to create a middleware that will set the correct app locale based on a few pieces of information. First, it will check the URL for a query string. If not present, it will check for a session value. If neither exists, it will default to a fallback language:
// app/Http/Middleware/Localization.php
public function handle(Request $request, Closure $next): Response
{
$allowedLanguages = ['en', 'es', 'fr']; // you could also use an Enum or config file
if (($language = $request->get('lang')) && in_array($language, $allowedLanguages)) {
// a valid language was sent in the query string - use it, and save for future use
$request->session()->put('language', $language);
} else {
// otherwise use the session language or the fallback
$language = $request->session()->get('language', config('app.fallback_locale'));
}
App::setLocale($language);
return $next($request);
}
Register this middleware in app/Http/Kernel.php
to enable it. Now, anywhere in a Blade file, we can use our translation string: {{ __('Hello') }}
Accessing the URL without setting a lang
query string parameter will show it in the default language, as defined in the fallback_locale
key in config/app.php
.
Accessing the URL with a lang
query string parameter will show it in the specified language, and will also set the session value so that future requests will use that language. If some unexpected language is requested, it will use the fallback language.
You can imagine extending this middleware further to using the Accept-Language
header. You could also add a language selector to the UI that sets the lang
query string parameter. Even with additional features like that, all the locale-setting logic can live in this one simple middleware, and not get spread across your routes and controllers.
Here's a sample repository showing a full working example.
Here to help,
Joel
P.S. Even in this simple middleware example, we don't forget validation. We truly believe validation is an extremely important part of any Laravel app.