Laravel 5 And His F*cking non-persistent App SetLocale

Laravel 5 And His F*cking non-persistent App SetLocale


Mar 18 2015, 02:34 in Web Development

Hey! Looking for a more SEO Friendly way to manage a multilingual application with Laravel5 ? Check this tutorial!

Edit: This article have been updated to match Laravel 5.2 architecture.

If you ever have worked already with Laravel 5 (if not, you should), and that you needed a decent way to switch language into your application, well good luck.

The thing is, it was really easier with Laravel 4.

Ok I'm not going to explain why and how and all, because you know that I mainly use my website to store snippets and reminder about HOW I SOLVED THIS NIGHTMARE OF A PROBLEM.

Relax.

In most of my applications, I don't really like having the language in the URI, because it messes with my Route file, and I have to update all my links.. Anyway, here's how I managed to build a simple Language Switcher, that will just update the localization of your application, and refresh the page.

First, create a new controller "LanguageController". You can use this command : php artisan make:controller LanguageController

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Requests;
use Config;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;

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

Ok, as you see we use a custom config array to fetch the available languages of the app, so lets create a **languages.php **in the config/ directory :

return [
    'en' => 'English',
    'fr' => 'Français',
];

Good! Now to use our controller, we are going to set up one new route:

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

Be careful, if you use Laravel 5.2, you need to put all your routes, including this new one, into a route group that implements the "web" middleware group (as we will put the middleware in this group)

You should now be able to use a Language dropdown (I often put it in my navbar). Check this example based on boostrap dropdown :

<li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
        {{ Config::get('languages')[App::getLocale()] }}
    </a>
    <ul class="dropdown-menu">
        @foreach (Config::get('languages') as $lang => $language)
            @if ($lang != App::getLocale())
                <li>
                    <a href="{{ route('lang.switch', $lang) }}">{{$language}}</a>
                </li>
            @endif
        @endforeach
    </ul>
</li>

Last thing to do is to set up a new Middleware:

// app/Http/Middleware/Language.php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Application;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;

class Language
{
    public function handle($request, Closure $next)
    {
        if (Session::has('applocale') AND array_key_exists(Session::get('applocale'), Config::get('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::get('app.fallback_locale'));
        }
        return $next($request);
    }
}

And of course we do not forget to update Kernel.php with our new Middleware (check the order I use)

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

That's it !! Enjoy :)


Share:
Like:

Disable AdBlock on this domain and offer me a cup of coffee :)