Select Language in Laravel Livewire

Video thumbnail

I'll show you how you can manage the language in Laravel. Here you can see that the interface now changes to Spanish, and then to English.

It's very simple: for this, we're going to use Livewire. However, if for some masochistic reason you don't want to use Livewire, you probably have the knowledge to make the changes yourself.
The important thing is to know the functions we need to call, beyond how we implement them; that is, to understand which methods to use for that purpose.

The component and the handling of language

This is the component. Here you can see that, once we receive the language (which comes from this list we have here), in this case I'm using Laravel + Livewire, every time we change the language using wire:model, we call the render() method defined:

<?php

namespace App\Livewire\User;

use Livewire\Attributes\Layout;
use Livewire\Component;

use Illuminate\Support\Facades\App;

#[Layout('layouts.store')]
class UserProfile extends Component
{

    public $language;

    public function render()
    {
        if (!isset($this->language)) {
            // al cargar el componente, este codigo se ejecuta al language NO estar seleccionado 
            // por el usuario
            $this->language = session('locale') ?? App::getLocale();
        } else {
            // se ejecuta desde la vista asociada por el .live
            session(['locale' => $this->language]);
            App::setLocale($this->language);
        }
        
        return view('livewire.user.user-profile');
    }
}

There are many ways to do it, but this was the implementation I came up with. The important thing is that you get the user's language across. I'm showing you how I did it.

So, here's what we do:

  • If it's not defined, I initialize the default language based on the language selected in the system (either in the session, which is where I save it, or using one of the methods to obtain the language at the application level).
  • When we change the language using wire:model, we go here and set the language in the session, since I save it there.
  • And also, very importantly, we must set the language at the framework level, because otherwise, we're not doing anything.

You can also save user preferences here if you want them to be persistent (for example, save them to a database).
In another video, I told you how I recommended saving user preferences without having to create 20 columns for 20 different preferences. What I was doing was saving a small JSON object.
I mentioned this before, and that's exactly what we're doing here.

Interface transition and reload

In the case of Livewire, to reload the entire interface, I also added a small AlpineJS that waits a few seconds for the request (wire:model) and then reloads the entire page.
This is so we can see the change applied to the entire interface, and that's why it's fully reflected:

<flux:select :label="__('Language')" id="language" wire:model.live="language" x-data @change="setTimeout(function(){window.location.reload()}, 100)" class="mt-1 block w-full rounded border-gray-300">
    <option value="es">Español</option>
    <option value="en">English</option>
</flux:select>

Middleware to maintain the language

It's important that changes persist across all requests. If, for example, we return to "Blog" or navigate to another part of the application, the language would revert to the initial language.
To avoid this, we must implement middleware that is responsible for setting the language saved in the session for each request.
Because, again, this isn't persistent: if we reload the page without middleware, it's lost.

This is a pain. To solve it, we implemented the following middleware. As you can see:

$ php artisan make:middleware SetLocale

Then, within that middleware, we set the language we have in the session, if and only if it exists.
You can also pass the default language as a second parameter (if you don't want to use the conditional language), but in this case I defined it like this:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\App;

class SetLocale
{
    public function handle($request, Closure $next)
    {

        if (session('locale')) {
            App::setLocale(session('locale'));
        }
        
        return $next($request);
    }
}

Where do we call this middleware? You can configure it directly in the routes if you prefer:

Route::middleware([SetLocale::class])

But I mean putting it inside the web route group.

bootstrap/app.php

->withMiddleware(function (Middleware $middleware) {
    $middleware->web([
        // Tu middleware personalizado
            \App\Http\Middleware\SetLocale::class,
    ]);
})

Although a cleaner way is to use withMiddleware(), which is now available in Laravel 11.
With this method, you can define it directly in web-type routes, and this way, each request automatically executes this middleware.

Remember that, by definition, middleware executes before each HTTP request from the browser or other application.

Language files

Create your language files in English and Spanish, in this case for English and Spanish.
Define the key-value pairs as an object:

resources/lang/es.json

{
    "Light": "Claro",
    "Dark": "Oscuro",
     ***   
}   

resources/lang/en.json

{
    "Light": "Light",
    "Dark": "Dark",
     ***   
}    

Then, from the views, you simply reference the text using __(), which is the name of the method that takes the field name.
For example:

{{ __('Light') }}

So, in this simple way, we have configured the language in Laravel. It's just two key steps.

I agree to receive announcements of interest about this Blog.

I'll show you the steps to change the language of a project in Laravel.

- Andrés Cruz

En español