How to add Language switcher in filament?

In this guide, we will explore how we can add language switcher in filament.

There are some packages like kenepa/translation-manager-plugin, bezhanSalleh/filament-panel-switch to add language switcher in filament instantly with additional features. But in this article, we will add our own. Here is an article to add Language switcher in fialment using kenepa/translation-manager-plugin.

Storing lang

You can store your lang file either in key value or in json format. To publish the lang file you can use the following command:

php artisan lang:publish

It will generate lang/en directory. You can add other languages by your own. For eg, if you want to generate for Spanish language, you can create a directory es inside your lang folder.

Retrieving Lang

Now to retrieve or translate any label, either we can use the helper method __() or translateLabel() in case of laravel filament. For eg:

TextInput::make('title')
->label(__('resource.post.fields.title'))

or
TextInput::make('title')
->label('resource.post.fields.title')
->translateLabel()
en/resource.php
    'post' => [
        'fields' =>[
            'type' => "Type",
            'title' => "Title",
.....
            ]]

Language Switch Component

Now, we will create a new Livewire language switch component. Use the following command:

php artisan make:component LanguageToggle

This will generate us 2 files: one Component and another view file.

// Livewire/LanguageToggle.php

class LanguageToggle extends Component
{
public function render()
    {
        return view('livewire.language-toggle');
    }
}

Now, we will create a config files to store the available locales for our system.

// config/locale.php

<?php
return [
    "en" => ['name'=>"English"],
    'hi' => ['name' => "Hindi"],
    'es' => ['name'=> "Spanish"]
];

Now, we will implement mount() on our component to get the current locale and availableLanguages.

// livewire/LanguageToggle.php
....
use Illuminate\Support\Facades\App;
class LanguageToggle extends Component
{
    public $currentLanguage;
    public $availableLanguages;

    public function mount()
    {
        $this->currentLanguage = App::getLocale();
        $this->availableLanguages = config('languages');
    }
....
}

After that, we will update our blade to create a dropdown for translations and show the current locale.

// livewire/language-toggle.blade.php
<x-filament::dropdown>
    <x-slot name="trigger">
        <x-filament::button
            color="gray"
            outlined>
            <span>{{$availableLanguages[$currentLanguage]['name'] ?? $currentLanguage}}</span>
        </x-filament::button>
    </x-slot>

    <x-filament::dropdown.list>
        @foreach($availableLanguages as $code=>$lang)
        <x-filament::dropdown.list.item
            wire:click="switchLanguage('{{$code}}')"
            >
            {{$lang['name']}}
        </x-filament::dropdown.list.item>
        @endforeach
    </x-filament::dropdown.list>
</x-filament::dropdown>

You can extend your config to add flags or any other important information related to locales.

Finally we will implement switchLanguage() in our component.

// livewire/LanguageToggle
class LanguageToggle{
...
 public function switchLanguage($lang)
    {
       if(array_key_exists($lang,$this->availableLanguages))
       {
            Session::put('locale',$lang);
            App::setLocale($lang);
            $this->currentLanguage = $lang;
            $this->js('window.location.reload()');
       }
    }
...
}

Here we are checking if the lang is in our available lang and if that exist we are setting the system locale to that particular lang.

Final code:

Livewire/LanguageToggle.php
<?php

namespace App\Livewire;

use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Session;
use Livewire\Component;

class LanguageToggle extends Component
{
    public $currentLanguage;
    public $availableLanguages;

    public function mount()
    {
        $this->currentLanguage = App::getLocale();
        $this->availableLanguages = config('languages');
    }

    public function switchLanguage($lang)
    {
       if(array_key_exists($lang,$this->availableLanguages))
       {
            Session::put('locale',$lang);
            App::setLocale($lang);
            $this->currentLanguage = $lang;
            $this->js('window.location.reload()');
       }
    }

    public function render()
    {
        return view('livewire.language-toggle');
    }
}
resources/viewslivewire/language-toggle.blade.php
<x-filament::dropdown>
    <x-slot name="trigger">
        <x-filament::button
            color="gray"
            outlined>
            <span>{{$availableLanguages[$currentLanguage]['name'] ?? $currentLanguage}}</span>
        </x-filament::button>
    </x-slot>

    <x-filament::dropdown.list>
        @foreach($availableLanguages as $code=>$lang)
        <x-filament::dropdown.list.item
            wire:click="switchLanguage('{{$code}}')"
            >
            {{$lang['name']}}
        </x-filament::dropdown.list.item>
        @endforeach
    </x-filament::dropdown.list>
</x-filament::dropdown>

Create a middleware

Now to make the translation persistent, we will create a new middleware that handles the locale.

php artisan make:middleware SetLocale
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Session;
use Symfony\Component\HttpFoundation\Response;

class SetLocale
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $locale = Session::get('locale',config('app.locale'));
        if(array_key_exists($locale,config('languages')))
        {
            App::setLocale($locale);
        }
        return $next($request);
    }
}

Now the final step is to register the middleware. You can register this in your panelProvider.

   public function panel(Panel $panel): Panel
    {
        return $panel->middleware(SetLocale::class)

....
}

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *