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)
....
}
Thank you very much.