Another example of how we can add a language selector to our application is by using sessions and a DB table to store the user's preferred language.
This example will not use a URL to determine the language which will allow us to use the same URL for all languages.
Our setup process for Database stored language selection will touch these things:
users
table called language
Let's start with the configuration:
config/app.php
// ...'locale' => 'en', // <-- Locate this line and add `available_locales` below it 'available_locales' => [ 'en', 'es',],// ...
Now we need to add a new field to our users
table:
php artisan make:migration add_language_to_users_table
Migration
Schema::table('users', function (Blueprint $table) { $table->string('language')->default('en');});
app/Models/User.php
protected $fillable = [ // ... 'language'];
Let's make a Controller that will switch user's language and save it to remember it for the next time:
app/Http/Controllers/ChangeLanguageController.php
public function __invoke($locale){ // Check if the locale is available and valid if (!in_array($locale, config('app.available_locales'))) { return redirect()->back(); } if (Auth::check()) { // Update the user's language preference in the database Auth::user()->update(['language' => $locale]); } else { // Set the language in the session for guests session()->put('locale', $locale); } // Redirect back to the previous page return redirect()->back();}
Now we can create our Middleware:
php artisan make:middleware SetLocale
app/Http/Middleware/SetLocale.php
use Auth;use Carbon\Carbon; // ... public function handle(Request $request, Closure $next): Response{ // Logged-in users use their own language preference if (Auth::check()) { app()->setLocale(Auth::user()->language); Carbon::setLocale(Auth::user()->language); // Guests use the language set in the session } else { app()->setLocale(session('locale', 'en')); Carbon::setLocale(session('locale', 'en')); } return $next($request);}
Register our middleware in our bootstrap/app.php
file:
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->append(\App\Http\Middleware\SetLocale::class); }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
Display the language selector in our views:
resources/views/layouts/navigation.blade.php
{{-- ... --}}@foreach(config('app.available_locales') as $locale) <x-nav-link :href="route('change-locale', $locale)" :active="app()->getLocale() == $locale"> {{ strtoupper($locale) }} </x-nav-link>@endforeach<x-dropdown align="right" width="48">{{-- ... --}}
And lastly, we need to modify our routes to use our Middleware and contain an endpoint to change the language:
routes/web.php
use App\Http\Controllers\ChangeLanguageController;// ... // Our language change endpointRoute::get('lang/{locale}', ChangeLanguageController::class)->name('change-locale'); Route::middleware(SetLocale::class) // <-- Our middleware to set the language ->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'; });
That's it! Now we can change the language by clicking on the language selector in the navigation bar and it will remember the language for our users indefinitely while guests will have their language set for the current session.
One additional step that we can take to improve the experience and avoid resetting the language for our new users is to take what they set in the session and transform it into a language preference in the database:
app/Http/Controllers/Auth/RegisteredUserController.php
// ...public function store(Request $request): RedirectResponse{ // ... $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), // Here we set the language preference to the language set in the session 'language' => session('locale', config('app.locale')), ]); // ...}// ...
Repository: https://github.com/LaravelDaily/laravel11-localization-course/tree/lesson/session-language-switching