Skip to content

Instantly share code, notes, and snippets.

@askilondz

askilondz/gistlog.yml

Last active Apr 11, 2016
Embed
What would you like to do?
Laravel Localization. A simple approach.

Localization is all the rage. Maybe that's a stretch...but it should be. I don't think there's any doubt of it's importance. It gives your site and content further ability to reach the entire connected world. Making that happen though is another story. Thankfully Laravel has a great localization class for this...but what's the best way to implement it?

I have site with two main localization objectives: detect the user's default browser language to know what language to display your content in...and provide a global dropdown giving the user the ability to translate your content on the fly.

So first...in my config/languages.php I have an array for the languages I'm currently supporting:

    'available' => [
        'en' => 'English',
        'zh' => 'Chinese',
        'ko' => 'Korean',
        'ru' => 'Russian',
        'es' => 'Spanish',
        'de' => 'German',
        'ja' => 'Japanese',
        'ar' => 'Arabic',
        'sw' => 'Swahili'
    ],

Now I created a global middleware that gets called with every route. I'ved called it: SetLocale.

class SetLocale
{
    public function handle($request, Closure $next)
    {
        if (Session::has('locale')) {
            $locale = Session::get('locale', Config::get('app.locale'));
        } else {

            $route_lang = $request->route('lang');
            $locale = is_null($route_lang) ? $request->get('lang') : $route_lang;

            if (!$locale) {
                //Default to browser language
                $locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
            }

            if (!$locale || !array_key_exists($locale, Config::get('languages.available'))) {
                $locale = 'en';
            }
        }

        App::setLocale($locale);

        return $next($request);
    }
}

Here I am first checking if a current locale has already been set in a Session. This gets set from when the user changes location in the dropdown which I'll show shortly. If there is no session...then I determine the language from the browser header, check if it's a language I currently have in my Available array, and default to English en if there is no match.

Next for the dropdown...when a user selects their language I make a call to a single route defined as such:

Route::get('locale', ['as' => 'locale', 'uses' => 'ViewsController@langChange']);

Here's the langChange method this route uses:

public function langChange(Request $request)
{
    $language = $this->getRequestLanguage($request);

    if (is_null($language) || is_null(config("languages.available.".$language))) {
        $language = "en";
    }

    \App::setLocale($language);

    \Session::put('locale', $language);

    return redirect()->back();
}

private function getRequestLanguage(Request $request)
{
    $route_lang = $request->route('lang');
    return is_null($route_lang) ? $request->get('lang') : $route_lang;
}

Here I'm getting the language from the request, making sure it is in fact in my supported languages array, then setting the locale with Laravel's App:setLocale as well as putting it in my Session. Then I simply redirect back to whatever the page was the user was on. The benefit of this is we don't have to worry about passing url parameters in all our routes through in our entire site. Very nice.

published: true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment