Не так давно я решил поближе познакомиться с набирающим популярность фреймворком Laravel, благо документации и статей по нему достаточно. Но какое обучение без практики? Решено было перенести на него довольно простенький самописный сайт, который спокойно себе висел на хостинге и бед не приносил.

Одной из особенностей сайта было переключение языка интерфейса, реализованный путем yaml файла словаря и простого парсера. Перенести его на логику фреймворка было делом скорее механическим, чем творческим, а вот заставить его запоминать выбранный язык оказалось чуть сложнее. Ниже я представляю свой вариант реализации этой задачи.

Настройка конфигурации приложения


Для начала нужно указать желаемую локаль и добавить массив используемых нами языков в config/app.php
'locale' => 'ru',               # Устанавливаем стандартную локаль для приложения
'locales' => ['ru', 'en'],      # Указываем, какие языки будем использовать в приложении. 
                                # Нам понадобится это в дальнейшем.

Создаем словари


Словари в Laravel представляют собой просто php-массивы. Как их создавать хорошо описано в документации. Нам нужно по словарю на каждый язык, используемый в приложении. Создаем в resources/lang по папке на каждый язык (у меня всего два, en и ru) и в каждой папке создаем свой словарь, например messages.php. Как ими пользоваться в шаблонах, думаю, отдельно объяснять не нужно.

Создаем Middleware


По умолчанию Laravel всегда загружается с языком, выбранном в конфигурации. Чтобы изменить его, нам нужно перехватить запрос до того, как тот получит view и установить язык методом App::setLocale();. Middleware это такой кусок кода, который будет выполняться при каждом запросе страницы пользователем и позволит нам это сделать. В нем мы будем проверять, какой язык пользователь уже выбирал (мы указываем его в сессии пользователя) если он уже заходил на наш сайт, а если такового не найдется — добавлять к сессии язык по умолчанию (например ru).

Заодно мы будем проверять, что выбранный пользователем язык валидный (для этого мы указали ранее в конфигурации доступные языки).

Используя консоль и artisan создаем middleware для нашего переключателя. Назовем его, например, Locale.

php artisan make:middleware Locale

И пишем наш код в метод handle. Здесь нам пригодятся указанные в конфиге переменные.
   public function handle($request, Closure $next)
    {   
        $raw_locale = Session::get('locale');     # Если пользователь уже был на нашем сайте, 
                                                  # то в сессии будет значение выбранного им языка.

        if (in_array($raw_locale, Config::get('app.locales'))) {  # Проверяем, что у пользователя в сессии установлен доступный язык 
            $locale = $raw_locale;                                # (а не какая-нибудь бяка) 
        }                                                         # И присваиваем значение переменной $locale.
        else $locale = Config::get('app.locale');                 # В ином случае присваиваем ей язык по умолчанию

        App::setLocale($locale);                                  # Устанавливаем локаль приложения

        return $next($request);                                   # И позволяем приложению работать дальше
    }

Не забываем добавить в начало файла
use App;
use Config;
use Session;


Регистрируем наш Middleware


В файле app/Http/Kernel.php добавляем наш middleware в конец массива, чтобы он выполнялся при каждой загрузке приложения.
protected $middleware = [
        ...
        \App\Http\Middleware\Locale::class,
    ];

Создаем route для переключения языка


Регистрируем путь, по которому будем переключать язык в сессии пользователя. Я для этого выбрал ссылку вида mysite/setlocale/en. При нажатии на неё мы изменяем значение lang (ранее установленное нашим middleware) на то, которое указано в конце ссылки. Попутно проверяем, что выбранный язык валидный уже знакомым методом и перенаправляем пользователя на ту же страницу, с которой был вызван скрипт.

Route::get('setlocale/{locale}', function ($locale) {
    
    if (in_array($locale, \Config::get('app.locales'))) {   # Проверяем, что у пользователя выбран доступный язык 
    	Session::put('locale', $locale);                    # И устанавливаем его в сессии под именем locale
    }

    return redirect()->back();                              # Редиректим его <s>взад</s> на ту же страницу

});

Вот и всё.

Комментарии (5)


  1. CuamckuyKot
    10.08.2015 12:58
    +3

    Как мы раньше жили без Middleware? Вспоминаю древний CodeIgniter.


    1. AmdY
      10.08.2015 20:45

      Возможно, вы удивитесь, но в столь же древнем фреймворке seagull уже было Middleware, называлось filter chain. Сейчас многие фишки того времени прошли ребрендинг и набирают популрность: composer — pear, pear libs — symfony components, middleware — seagull filter chain, zephir — pecl


  1. Londeren
    10.08.2015 21:22

    Набрал популярность этот фреймворк довольно давно, о чем говорят 11+к звезд на гитхабе


  1. likerRr
    11.08.2015 09:12

    А почему язык храните в сессии, а не в куках?


    1. uncle_alex
      11.08.2015 18:11
      +1

      Принципиальной разницы нет, можно и в куках, просто заменив фасад на Cookie::