Back to Course |
Multi-Language Laravel 11: All You Need to Know

Language Switcher from URL

Adding a language selector is crucial to any multilingual application. In this practical example, we'll add a language selector to our navigation bar:

In this first example, we will define the language from the URL segment, like /en/about or /es/register.


Setup

Here's our plan to set up a language selector:

  • Configuration: add a language list to the config - this will be used to display the language selector
  • Middleware: Add a Middleware to handle language change and URL redirection
  • Routes: Modify Routes to use the Middleware
  • Views: Add a language selector to our Views
  • Redirects: Modify our redirects for authentication

Let's start with the configuration:

config/app.php

// ...
'locale' => 'en', // <-- Locate this line and add `available_locales` below it
 
'available_locales' => [
'en',
'es',
],
// ...

Next, we can create our middleware:

php artisan make:middleware SetLocale

app/Http/Middleware/SetLocale.php

use URL;
use Carbon\Carbon;
 
// ...
 
public function handle(Request $request, Closure $next): Response
{
app()->setLocale($request->segment(1)); // <-- Set the application locale
Carbon::setLocale($request->segment(1)); // <-- Set the Carbon locale
 
URL::defaults(['locale' => $request->segment(1)]); // <-- Set the URL defaults
// (for named routes we won't have to specify the locale each time!)
 
return $next($request);
}

Now we need to modify Routes to use the new Middleware and add the locale segment to the URL:

routes/web.php

Route::get('/', function () {
return redirect(app()->getLocale()); // <-- Handles redirect with no locale to the current locale
});
 
Route::prefix('{locale}') // <-- Add the locale segment to the URL
->where(['locale' => '[a-zA-Z]{2}']) // <-- Add a regex to validate the locale
->middleware(\App\Http\Middleware\SetLocale::class) // <-- Add the middleware
->group(function () {
Route::get('/', function () {
return view('welcome');
});
 
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
 
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
 
// ...
});
 
require __DIR__ . '/auth.php';
});

Now we can add the language selector to our views:

resources/views/layouts/navigation.blade.php

{{-- ... --}}
@foreach(config('app.available_locales') as $locale)
<x-nav-link
:href="route(\Illuminate\Support\Facades\Route::currentRouteName(), array_merge(Route::current()->parameters(),['locale' => $locale]))"
:active="app()->getLocale() == $locale">
{{ strtoupper($locale) }}
</x-nav-link>
@endforeach
<x-dropdown align="right" width="48">
{{-- ... --}}

And fix one issue with our Dashboard link:

resources/views/welcome.blade.php

Replace: {{ url('/dashboard') }} with {{ route('dashboard') }}

Finally, we need to modify our redirects for authentication:

Redirect after login:

app/Http/Controllers/Auth/AuthenticatedSessionController.php

public function store(LoginRequest $request): RedirectResponse
{
$request->authenticate();
 
$request->session()->regenerate();
 
return redirect()->intended(route('dashboard', ['locale' => app()->getLocale()]));
}

Redirect after the user session expired:

bootstrap/app.php

return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__ . '/../routes/web.php',
commands: __DIR__ . '/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo(fn() => route('login', ['locale' => app()->getLocale()]));
})

Lastly, there is an issue mentioned where registrations do not redirect correctly. For this, we need to modify the RegisteredUserController:

app/Http/Controllers/Auth/RegisteredUserController.php

// ...
 
public function store(Request $request): RedirectResponse
{
// ...
 
return redirect(route('dashboard', absolute: false));
return redirect(route('dashboard', ['locale' => app()->getLocale()], absolute: false));
}

That is it, we are done! Once the page is loaded - we should see that we were redirected from / to /en and once the user logs in - we should be redirected to /en/dashboard:

And switching between languages should work as expected:


Repository: https://github.com/LaravelDaily/laravel11-localization-course/tree/lesson/ui-switching