In this how to guide, I will show you how to create a multilingual website using the Laravel localization feature. For this example i will be creating a new Laravel 5.8 project from scratch, so you can follow along. If you are not familiar with Laravel 5.8, please refer to the official documentation.

There is a lot of different ways to accomplish this inclucing usage of third party packages or just by building it from scratch with Laravel. In this example i will implement Middleware to handle the localization. This will be based on the users selected language or by using a specific localization specific route.

Content in this article

  • Create a multilingual website using Laravel localization options

Create a multilingual website using Laravel localization options

By using Laravel’s localization feature you will get access to a convenient way of retrieving string in various languages. This allows for support of multiple languages within our application very fast. The language strings will be stored in php files located within the installation, so no need for a Database. The directory for the language files is resources / lang. Within this directory we will be creating a folder for each language you need to support on your website application.

We will register middleware to check if the locale is set and then change the language in the application based on the locale. If you got any questions, please let me know in the comments. If you feel ready – then let’s get started by installation af fresh copy of Laravel. At the moment i’m writing this article, Laravel 5.8 is the latest released version.

Step 1 – Install Laravel 5.8

I’m using a MAC so i will open up my terminal and enter the following code:

laravel new localizationApp

or

composer create-project laravel/laravel localizationApp

Okay, first thing to do is to go inside the project. As i said earlier we won’t need to connect the application to a database, the reason is that this is a frontend application and we won’t be handling any data. All files will be stored locally inside resources / lang.

By default our application’s local language is English or en. You can find it in 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. Inside this folder you will find the default files for Laravel, this includes:  auth.php, pagination.php, passwords.php, validation.php.

These files are translation files for Laravel. Let’s check the auth.php file, to see how it looks.

<?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.',

];

As you might have noticed this file got a key-value pair for each string. This allows you to define any key you like, and then write the value in your desired language.

The root folder for this language is en which means that the translation files in the folder is in English. I’m from Denmark, which means that my origin langugage is Danish. When adding a danish language to the application, i would have to create a new folder named da where i would include all danish translations for the application.

If you where from Germany, you would add a new folder named de for Deutschland. Here you would include the same files as for the danish language, but with the value in German.

<?php

// auth.php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Language Lines in Danish
    |--------------------------------------------------------------------------
    |
    | 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' => 'Disse oplysninger matcher ikke vores data om dig',
    'throttle' => 'Du har for mange login forsøg. Prøv venligst igen om :seconds sekunder.',

];

You must remember to include / add the same keys for all of your translation files for each language you would add. Also remember to change the value to match the language you are translating the app into.

In my example above, i simply copied the auth.php file to the danish folder (da) and translated the two string failed and throttle. As you can see the key is the same and the value has been changed.

Each time a user changes the language in the application. The value from our strings in the translation file will be shown. All because we use the same key in the view files and due to the middleware we registered, it will mapped to the correct languages.

Step 2 – Create Translation files for your application

I showed how the functionality works. Now i will show you exactly what to do in order to make this work, i the following example, i will be adding two new languages – Danish and Deutsch. Our application will end up with the following languages:

  • English
  • Danish
  • Deutsch

First start by creating a folder inside the resources / lang folder.

IMAGE HERE

Now, inside all three folders, create a file called common.php and add the following code. For en / common.php file:

<?php

// common.php

return [
  'hello' => 'Hello my friend'
];

For da / common.php file:

<?php

// common.php

return [
  'hello' => 'Hej min ven'
];

For de / common.php file:

<?php

// common.php

return [
  'hello' => 'Hallo mein Freund'
];

You are able to put as many key-value pairs as you like inside this file. I only added one text in this demo. If you where to add more than one text it would look like the following:

<?php

// common.php

return [
  'hello' => 'Hello my friend',
  'goodbye' => 'Goodbye my friend'
];

So far we have created folders for each language and translation files for each of them. Let’s start working on the views and make our application load above translations when asked to.

Step 3 – Configure the view

First, create the layouts folder inside the resources / views folder and inside that layouts folder, you have to create an app.blade.php file and add the following code to it.

<!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 Localization App') }}</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 Localization App') }}
                </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/da"><img src="{{asset('img/da.png')}}" width="30px" height="20x"> Danish</a>
                                <a class="dropdown-item" href="lang/de"><img src="{{asset('img/de.png')}}" width="30px" height="20x"> Deutsch</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 folderand place this codesnippet. This will include a markup that will include a dropdown showing available languages.

@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 the route, controller, and middleware functionality

Go to routes / web.php, and add the following route to the configuration:

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

Inside the HomeController.php file, you have to define a lang method. You can create a controller using the following command for PHP Artisan:

php artisan make:controller HomeController

Add the following code to the newly created HomeController 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();
    }
}

This function will see the locale and put it into the session for the current user. Now you have to create some new middleware using the following command for PHP Artisan

php artisan make:middleware Localization

It will create a file inside app / Http / Middleware folder. Go to your newly created middleware file called Localization.php and update the handle method with the codesnippet below. Your final middleware file should like like the following:

<?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 in the application

Now add the middleware in App \ Http \ Kernel‘$middlewareGroup’s array like i have done in the example below:

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 we only need to do one thing. 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 Localization Application') }}</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 Localization Application') }}
                </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('es')
                                <img src="{{asset('img/da.png')}}" width="30px" height="20x"> Danish
                                @break
                                @case('de')
                                <img src="{{asset('img/de.png')}}" width="30px" height="20x"> Deutsch
                                @break
                                @default
                                <img src="{{asset('img/en.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/en.png')}}" width="30px" height="20x"> English</a>
                                <a class="dropdown-item" href="lang/da"><img src="{{asset('img/da.png')}}" width="30px" height="20x"> Danish</a>
                                <a class="dropdown-item" href="lang/de"><img src="{{asset('img/de.png')}}" width="30px" height="20x"> Deutsch</a>
                                </div>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
        <main class="py-4">
            @yield('content')
        </main>
    </div>
</body>
</html>

In the code i included above, our dropdown still shows Language even if we change the current locale. We can fix this by adding a switch statement and the check what locale we have. Based on what locale the user selects we can display a flag icon like i have done in my example below.

Final thing to do is adding the following code inside resources / views / welcome.blade.php.

@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('common.welcome')}}</p>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Here, I have used the trans() function which takes one argument. Luckily for us we only need one argument for getting the corresponding translation. The argument will look like the following: filename.array_key_name.

If you followed my guide you can go to your main site in your browser. Here you will see a dropdown with the three languages, we made translations for.

Select the language you would like to see the translation in. Now the welcome message will change each time based on the value you entered in the translation file.

I hope this short guide, have given you an example of how to properly turn your Laravel Application into a multilingual Laravel application without any thirdparty libraries.

Leave a Reply