Не так давно я решил поближе познакомиться с набирающим популярность фреймворком Laravel, благо документации и статей по нему достаточно. Но какое обучение без практики? Решено было перенести на него довольно простенький самописный сайт, который спокойно себе висел на хостинге и бед не приносил.
Одной из особенностей сайта было переключение языка интерфейса, реализованный путем yaml файла словаря и простого парсера. Перенести его на логику фреймворка было делом скорее механическим, чем творческим, а вот заставить его запоминать выбранный язык оказалось чуть сложнее. Ниже я представляю свой вариант реализации этой задачи.
Для начала нужно указать желаемую локаль и добавить массив используемых нами языков в config/app.php
Словари в Laravel представляют собой просто php-массивы. Как их создавать хорошо описано в документации. Нам нужно по словарю на каждый язык, используемый в приложении. Создаем в resources/lang по папке на каждый язык (у меня всего два, en и ru) и в каждой папке создаем свой словарь, например messages.php. Как ими пользоваться в шаблонах, думаю, отдельно объяснять не нужно.
По умолчанию Laravel всегда загружается с языком, выбранном в конфигурации. Чтобы изменить его, нам нужно перехватить запрос до того, как тот получит view и установить язык методом App::setLocale();. Middleware это такой кусок кода, который будет выполняться при каждом запросе страницы пользователем и позволит нам это сделать. В нем мы будем проверять, какой язык пользователь уже выбирал (мы указываем его в сессии пользователя) если он уже заходил на наш сайт, а если такового не найдется — добавлять к сессии язык по умолчанию (например ru).
Заодно мы будем проверять, что выбранный пользователем язык валидный (для этого мы указали ранее в конфигурации доступные языки).
Используя консоль и artisan создаем middleware для нашего переключателя. Назовем его, например, Locale.
И пишем наш код в метод handle. Здесь нам пригодятся указанные в конфиге переменные.
Не забываем добавить в начало файла
В файле app/Http/Kernel.php добавляем наш middleware в конец массива, чтобы он выполнялся при каждой загрузке приложения.
Регистрируем путь, по которому будем переключать язык в сессии пользователя. Я для этого выбрал ссылку вида mysite/setlocale/en. При нажатии на неё мы изменяем значение lang (ранее установленное нашим middleware) на то, которое указано в конце ссылки. Попутно проверяем, что выбранный язык валидный уже знакомым методом и перенаправляем пользователя на ту же страницу, с которой был вызван скрипт.
Вот и всё.
Одной из особенностей сайта было переключение языка интерфейса, реализованный путем 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)
Londeren
10.08.2015 21:22Набрал популярность этот фреймворк довольно давно, о чем говорят 11+к звезд на гитхабе
likerRr
11.08.2015 09:12А почему язык храните в сессии, а не в куках?
uncle_alex
11.08.2015 18:11+1Принципиальной разницы нет, можно и в куках, просто заменив фасад на Cookie::
CuamckuyKot
Как мы раньше жили без Middleware? Вспоминаю древний CodeIgniter.
AmdY
Возможно, вы удивитесь, но в столь же древнем фреймворке seagull уже было Middleware, называлось filter chain. Сейчас многие фишки того времени прошли ребрендинг и набирают популрность: composer — pear, pear libs — symfony components, middleware — seagull filter chain, zephir — pecl