Localization Implementation in Laravel with Language Switcher

In this tutorial we will go over on how we can implement a multi-language website in Laravel using Laravel Localization and also create a simple language switcher to change the default language.

1. Create New Laravel Application

For this demonstration I am creating a new Laravel Application, you can ignore this step if you already have the Laravel application installed in your system.

Run the following command to create a new Laravel application.

composer create-project laravel/laravel laravel-localization-demo

Once you have the project ready, you can move on to the next step.

2. Configuring the Locale for All Http Requests

The default language for your Laravel’s application is stored in the config/app.php configuration file’s locale configuration option.

 'locale' => 'en',

Laravel’s gives you the option to change the locale for a single Http Request by executing the setLocale method on App Facade App::setLocale($locale);, But what if once the language is changed you don’t want to worry about setting the Locale and this should be taken care by an automatic code logic.

Let’s create middleware which will pick the language set in the session and will set the locale for each and every http request.

php artisan make:middleware Language

Here is the Language Middleware code


<?php

namespace App\Http\Middleware;

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

class Language
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */    public function handle($request, Closure $next)
    {
        if (Session()->has('applocale') AND array_key_exists(Session()->get('applocale'), config('languages'))) {
            App::setLocale(Session()->get('applocale'));
        }
        else { // This is optional as Laravel will automatically set the fallback language if there is none specified
            App::setLocale(config('app.fallback_locale'));
        }
        return $next($request);
    }
}

In this middleware we are checking if the session has applocale variable set and if the language belongs to the languages specified in the languages file. If yes we use the setLocale method to change the application language.

Next up, Add the middleware entry into the Kernel.php file


    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\Language::class,
        ],

 

As you can guess, our next step should be to create a languages config file where we can specify the list of languages supported by the application.

Create a new file named languages.php inside the config directory


<?php
return [
    'en' => 'English',
    'fr' => 'Français',
    'es' => 'Spanish'
];

For this demonstration I have specified three languages in the configuration file.

3. Language Switcher Backend Code

In the previous step we created a Middleware which will change the application’s language depending upon the value set in the session. In this step we will work on the backend code which will set the language value in the application’s session.

Let’s create a simple controller method which accepts the language user wants to change and simply sets the language in the session.

Create new controller

php artisan make:controller LanguageController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Redirect;

class LanguageController extends Controller
{
    
    public function switchLang($lang)
    {
        if (array_key_exists($lang, Config::get('languages'))) {
            Session::put('applocale', $lang);
        }
        return Redirect::back();
    }
}

Let’s also add the corresponding route entry in the web.php file to hit the controller method

Route::get('lang/{lang}', ['as' => 'lang.switch', 'uses' => 'App\Http\Controllers\LanguageController@switchLang']);

 

Alright, since we have the backend code ready we can move on to the front end part wherein we will create the ability on frontend to switch languages.

4. Creating Language Switcher Front End

In this step we’ll be creating a simple language switcher, On the front end I will be using Bootstrap Framework.

Here are the steps to install the Bootstrap Framework with Auth scaffolding


//Add composer dependency for Laravel Pacakge
composer require laravel/ui
//Install Bootstrap with Auth scaffolding
php artisan ui bootstrap --auth
//npm commands
npm install
npm run dev

Once the Bootstrap is installed we can utilize the app layout file to create the language switcher.

Open the app.blade.php file located under resources > views > layouts and add the following snippted just after the login and register links in the navbar.


<li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        {{ Config::get('languages')[App::getLocale()] }}
    </a>
    <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
    @foreach (Config::get('languages') as $lang => $language)
        @if ($lang != App::getLocale())
                <a class="dropdown-item" href="{{ route('lang.switch', $lang) }}"> {{$language}}</a>
        @endif
    @endforeach
    </div>
</li>

This will create a dropdown with the list of languages which the user can choose from and will also show the default language on the top.

5. Adding Flags to the Language Options

How about we add the visual cue in the form of a flag just next to the language in the dropdown. Here is what needs to be done in order to achieve that.

We will make use of the library flag-icon-css to display the country / language flag just next to the language.

Install flag-icon-css

npm install flag-icon-css

 

Once the package is installed, you can import the scss file by including the following lines in the app.scss file located in resources > scss folder


// Flag Icon CSS
@import '~flag-icon-css/sass/flag-icon';

Run npm run dev command again to compile the scss into css.

Now we can update the languages.php file located in the config directory to include the flag-icon code associated with each language.


<?php

return [
    'en' => [
        'display' => 'English',
        'flag-icon' => 'us'
    ],
    'fr' => [
        'display' => 'Français',
        'flag-icon' => 'fr'
    ],
    'es' => [
        'display' => 'Spanish',
        'flag-icon' => 'es'
    ],
];

Let’s modify the code located in app.blade.php file to include the flag-icon as well.


<li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
        <span class="flag-icon flag-icon-{{Config::get('languages')[App::getLocale()]['flag-icon']}}"></span> {{ Config::get('languages')[App::getLocale()]['display'] }}
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
        @foreach (Config::get('languages') as $lang => $language)
            @if ($lang != App::getLocale())
                    <a class="dropdown-item" href="{{ route('lang.switch', $lang) }}"><span class="flag-icon flag-icon-{{$language['flag-icon']}}"></span> {{$language['display']}}</a>
            @endif
        @endforeach
        </div>
</li>

6. Test Localization

Let’s create a sample localization language files as well as a sample page to test if all the pieces of our code works well and if we are able to achieve switching the language.

Add a new following controller method to HomeController

    
public function languageDemo(){
        return view('languageDemo');
    }

Add the corresponding route file

 Route::get('/languageDemo', 'App\Http\Controllers\HomeController@languageDemo');

Create a new blade file named languageDemo.blade.php inside app > resources > views directory with following content


@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <h3>{{__('messages.welcome')}}</h3>
    </div>
</div>
@endsection

We are almost there, notice the echo statement in the above blade file. Let’s create language translations file for each of the specified language.

Go to resources > lang directory and create messages.php file for each of the languages in their directory

messages.php inside en directory


<?php

return [
    'welcome' => 'Welcome to our application!',
];

messages.php file inside es directory


<?php

return [
    'welcome' => '¡Bienvenido a nuestra aplicación!',
];

messages.php file inside fr directory


<?php

return [
    'welcome' => 'Bienvenue sur notre application!',
];

There you go open /languageDemo page and you should be able to see the translations switching as you change the language from the top navbar.

tgugnani: Web Stuff Enthusiast.