AppDividend
Latest Code Tutorials

How To Create Multilingual Website using Laravel Localization

4

In this tutorial, we will see How To Create Multilingual Website using Laravel Localization. For this example, we will use Laravel 5.8, and we will do it from scratch. If you are not familiar with Laravel 5.8, then please check out my Laravel 5.8 CRUD Example. There are so many different ways, like using the third party packages or build it from scratch using localization of Laravel. You can make the Middleware to handle a localization based on the user’s selected language, or you can use localization based on a specific route.

Create Multilingual Website using Laravel Localization

Laravel’s localization features provide a convenient way to retrieve strings in various languages, allowing us to support the multiple languages within your application quickly. Language strings are stored in the files within the resources/lang directory. Within that directory, there should be a subdirectory for each language supported by the application.

We will create the middleware to check if the locale is set then change the locale of the application. So let’s get started by installing a fresh copy of Laravel. Right now, Laravel’s 5.8 version is the latest version. Yours might be different from me depending on the future.

Step 1: Install Laravel 5.8

Type the following command in your terminal.

laravel new localization

or

composer create-project laravel/laravel localization

 

Laravel Localization

Go inside the project. For this project, we do not need to connect our application to the database because it is a frontend. So, I am not connecting this laravel app to the database. It is related to the frontend and not the database because we do not need for this example.

By default, our application’s local language is English or en.

You can find it on the config >> app.php file.

// app.php 

/*
    |--------------------------------------------------------------------------
    | Application Locale Configuration
    |--------------------------------------------------------------------------
    |
    | The application locale determines the default locale that will be used
    | by the translation service provider. You are free to set this value
    | to any of the locales which will be supported by the application.
    |
    */

    'locale' => 'en',

Here, the locale is set to en.

Now, if you check the resources >> lang folder, there is one folder called en, in which there are some files like auth.php, pagination.php, passwords.php, validation.php.

So, these files are translation files. Let’s check the auth.php file.

<?php

// auth.php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used during authentication for various
    | messages that we need to display to the user. You are free to modify
    | these language lines according to your application's requirements.
    |
    */

    'failed' => 'These credentials do not match our records.',
    'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',

];

So, this file returns an array which has key-value pair. So, here you can define any key you like, but the values are on your language specific statements.

An app.php file’s root folder name is en, so translation to these file’s statement is in English language or en, if the root folder is fr means french translation then the app.php file might look like below.

<?php

// auth.php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Language Lines
    |--------------------------------------------------------------------------
    |
    | The following language lines are used during authentication for various
    | messages that we need to display to the user. You are free to modify
    | these language lines according to your application's requirements.
    |
    */

    'failed' => 'Ces informations d'identification ne correspondent pas à nos enregistrements',
    'throttle' => 'Trop de tentatives de connexion. Veuillez réessayer dans: secondes secondes.',

];

Remember, you need to add the same keys for all of your translation files across the different languages, change the values respective to your languages.

In the above code, we have written two items, which are failed and throttle and the values are translated into the French language.

So, when the user changes the languages, these statements will be displayed because in the view file, we will call it by its key and due to middleware it will map to the correct languages.

Step 2: Creating Translation Files

Okay, now we will go for three languages. English is already there.

  1. French
  2. Spanish
  3. Japanese

So, let’s create a folder inside the resources >> lang folder.

 

Website using Laravel Localization

Now, inside all of the four folders, create a file called sentence.php and add the following code.

For en >> sentence.php file,

<?php

// sentence.php

return [
  'welcome' => 'Welcome Friend'
];

For es >> sentence.php file,

<?php

// sentence.php

return [
  'welcome' => 'Bienvenido amigo'
];

For fr >> sentence.php file,

<?php

// sentence.php

return [
  'welcome' => 'Bienvenue mon ami'
];

And last, jp >> sentence.php file.

<?php

// sentence.php

return [
  'welcome' => 'ようこそ友達'
];

You can put as many texts as you want. I have just taken one text for this demo.

Now we have placed all translations in place, let’s start working on the views and make our application load above translations.

Step 3: Setup the view.

First, create layouts folder inside resources >> views folder and inside that layouts folder, create an app.blade.php file and add the following code.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-light navbar-laravel">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    {{ config('app.name', 'Laravel') }}
                </a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <!-- Left Side Of Navbar -->
                    <ul class="navbar-nav mr-auto">

                    </ul>

                    <!-- Right Side Of Navbar -->
                    <ul class="navbar-nav ml-auto">
                        <li class="nav-item dropdown">
                            <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                Language <span class="caret"></span>
                            </a>
                            <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
                                <a class="dropdown-item" href="lang/en"><img src="{{asset('img/us.png')}}" width="30px" height="20x"> English</a>
                                <a class="dropdown-item" href="lang/fr"><img src="{{asset('img/fr.png')}}" width="30px" height="20x"> French</a>
                                <a class="dropdown-item" href="lang/es"><img src="{{asset('img/es.png')}}" width="30px" height="20x"> Spanish</a>
                                <a class="dropdown-item" href="lang/jp"><img src="{{asset('img/jp.png')}}" width="30px" height="20x"> Japanese</a>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
        <main class="py-4">
            @yield('content')
        </main>
    </div>
</body>
</html>

Now open your welcome.blade.php file, which is by default inside the resources >> views folder and place below code which includes a markup just for a languages dropdown.

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-body">
                    hello
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Step 4: Setup route, controller, and middleware

Now, inside routes >> web.php, add the following route.

Route::get('lang/{locale}', 'HomeController@lang');

Define a lang method inside the HomeController.php file. You can create a controller using the following command.

php artisan make:controller HomeController

Write the following code inside that file.

<?php

// HomeController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App;

class HomeController extends Controller
{
    public function lang($locale)
    {
        App::setLocale($locale);
        session()->put('locale', $locale);
        return redirect()->back();
    }
}

So, this function will see the locale and put it into the session.

Now, create a middleware using the following command.

php artisan make:middleware Localization

It will create a file inside the app >> Http >> Middleware folder.

Now open your newly created middleware file called Localization.php and update the handle method with below code. So, our final file looks like below.

<?php

// Localization.php

namespace App\Http\Middleware;

use Closure;
use App;

class Localization
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (session()->has('locale')) {
            App::setLocale(session()->get('locale'));
        }
        return $next($request);
    }
}

Step 5: Register the Localization Middleware

Now add the middleware in App\Http\Kernel‘s $middlewareGroup’s array like so.

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\Localization::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

Now, one final thing is remaining. Add the following code inside the resources >> views >> layouts >> app.blade.php file.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>

    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-light navbar-laravel">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    {{ config('app.name', 'Laravel') }}
                </a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <!-- Left Side Of Navbar -->
                    <ul class="navbar-nav mr-auto">

                    </ul>

                    <!-- Right Side Of Navbar -->
                    <ul class="navbar-nav ml-auto">
                        @php $locale = session()->get('locale'); @endphp
                        <li class="nav-item dropdown">
                            <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                Language <span class="caret"></span>
                            </a>
                            @switch($locale)
                                @case('fr')
                                <img src="{{asset('img/fr.png')}}" width="30px" height="20x"> French
                                @break
                                @case('es')
                                <img src="{{asset('img/jp.png')}}" width="30px" height="20x"> Spain
                                @break
                                @case('jp')
                                <img src="{{asset('img/jp.png')}}" width="30px" height="20x"> Japanese
                                @break
                                @default
                                <img src="{{asset('img/us.png')}}" width="30px" height="20x"> English
                            @endswitch
                            <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
                                <a class="dropdown-item" href="lang/en"><img src="{{asset('img/us.png')}}" width="30px" height="20x"> English</a>
                                <a class="dropdown-item" href="lang/fr"><img src="{{asset('img/fr.png')}}" width="30px" height="20x"> French</a>
                                <a class="dropdown-item" href="lang/es"><img src="{{asset('img/es.png')}}" width="30px" height="20x"> Spanish</a>
                                <a class="dropdown-item" href="lang/jp"><img src="{{asset('img/jp.png')}}" width="30px" height="20x"> Japanese</a>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
        <main class="py-4">
            @yield('content')
        </main>
    </div>
</body>
</html>

In the above code, if we change the language, dropdown still shows Language instead of the current locale. We can fix by adding a switch statement and check what locale we have and based on that we will show the current locale with a flag icon like below.

Finally, add the following code inside the resources >> views >> welcome.blade.php file.

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-body">
                <p>{{ trans('sentence.welcome')}}</p>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Here, I have used the trans() function which will take one argument, and it is the filename.array_key_name.

Now, if you have done all correct till now, then go to the root route inside the browser, and you will see the drop-down with the four languages.

Select the language, and you will see the welcome message in a different language.

Finally, How To Create Multilingual Website using Laravel Localization Tutorial With Example is over.

4 Comments
  1. Ty says

    Using session as your locale is not good for SEO.

  2. Martin says

    Thank you for this tutorial.

  3. محمد ابراهيم says

    how setup this in web.php route file

    localhost:8000 which get lang strings from resources/lang/en directory

    localhost:8000/en default which get lang strings from resources/lang/en directory
    localhost:8000/ar which get lang strings from resources/lang/ar directory

  4. Gal says

    One issue I had and have since fixed, is that the links for changing the language need to be absolute to work on every page. I had some pages with URLs like ‘example.com/one/two’, and when i clicked on the link to change the language it redirected me to the URL ‘example.com/one/lang/en’ – which does not exist and just gives a 404. To fix this just make your language changing links absolute.

    Before (doesn’t work on all pages)
    English

    After (notice the forward slash before ‘lang’) – WORKS
    English

    Other than that thank you for an amazing tutorial!

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.