Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Такие у меня routes:
/**
* Frontend pages of site
*/
Route::multilingual('/', 'IndexController@index')->name('index');
/**
* Authentication
*/
Route::get('login', 'Auth\LoginController@show');
Route::post('login', 'Auth\LoginController@login');
Route::get('logout', 'Auth\LoginController@logout')->name('auth.logout');
Route::group(['middleware' => ['registration', 'guest']], function () {
Route::get('register', 'Auth\RegisterController@show');
Route::post('register', 'Auth\RegisterController@register');
});
и т.д.
Первый из них - это для морды сайта,
а остальные - для дашборда, профиля, авторизации/регистрации и т.п.
Управлением языком первого роута занимается отдельный пакет, который позволяет отдавать контент под префиксами (папками) - наподобие "site.com/faq" (для буржуйской версии) и "site.com/ru/faq" (для русской версии).
А управление языком остальных роутов (не морды сайта, а по сути уже всей части user-area) осуществляется уже через осознанный выбор самих пользователей - без префиксов-папок для языков. Согласитесь, было бы странно иметь пути "site.com/dashboard" и "site.com/ru/dashboard". Тут уже в дело вступают Куки (лучше конечно Сессии, но надо чтобы смена языка работала еще до фактической аутентификации пользователя - по сути на страницах самой авторизации/регистрации/восстановления пароля... А плодить сессии под КАЖДОГО просто посетителя как-то не комильфо). И для реализации такого функционала прямо в конце `routes/web.php` (знаю, bad practice) прописано следующее:
Route::get('lang/{locale}', function ($locale) {
if (!in_array($locale, locales())) {
abort(400);
}
Cookie::queue( Cookie::forever('lang', $locale) );
return back();
});
// Вот этот кусок кода надо как-то изолировать от применения к первому роуту: <-------------------------
if (Request::hasCookie('lang')) {
$lang = Cookie::get('lang');
if (in_array($lang, locales()))
locale($lang);
else
Cookie::queue( Cookie::forget('lang') );
}
И оно работает... И не пришлось лишних и внешних package'й создавать, инициализировать их и т.д., только нагружая систему.
Однако эта реализация пересекается с тем отдельным переводчиком у первого роута. И превалирует над ним. В итоге и по "site.com/faq", и по "site.com/ru/faq" одинаково отображается английский язык. Или русский. Смотря какой выбран (сохранен в куки).
Как мне изолировать куки-язычность от первого роута? Я бы прописал в контроллере - но их там тьма тьмущая, а у первого роута наоборот - только один контроллер. Не прописывать же везде в каждом роуте один и тот же код? Иначе нарушается принцип DRY (don't repeat yourself) и вообще код должен быть в одном едином месте. И тут он реально должен быть в каком-нибудь единственном месте (а не "в одном месте..." )
Как быть?
Изменено Fullstack (30.08.2021 06:11:54)
Не в сети
Ничего не знаю про пакет, который ты используешь. Но:
Мне кажется ты смешиваешь локализацию пользовательского интерфейса и локализацию контента. Страницы, которые ты помещаешь в Route::multilingual, вероятно должны выдавать контент на том или ином языке, независимо от того, какой язык является предпочтительным для пользователя, т.е. на каком языке пишутся меню и служебные сообщения. Не обязательно им совпадать!
Исходя из этого, твои два метода выбора языка должны устанавливать разные переменные внутри приложения и ты сможешь использовать их в разных в приложении независимо.
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Не в сети
Страницы, которые ты помещаешь в Route::multilingual, вероятно должны выдавать контент на том или ином языке, независимо от того, какой язык является предпочтительным для пользователя
Верно. Этот контент иденксируется поисковиками, поэтому он должен быть разным, в зависимости от первой части URI (/page, /ru/page, /de/page) (за что и отвечает вышеупомянутый компонент), и разные меню сайта в том числе должны быть на языке, указанном в начале пути роута. А весь пользовательский интерфейс уже в зависимости от выбранного языка самим пользователем (с помощью иконок с флагами, которые успешно ставят нужный язык через роут /lang/{$locale} в Куки).
И вот эту часть кода, устанавливающую язык из Куков:
if (Request::hasCookie('lang')) {
$lang = Cookie::get('lang');
if (in_array($lang, locales()))
locale($lang);
else
Cookie::queue( Cookie::forget('lang') );
}
мне надо как-то изолировать от первого роута, который отвечает за фронтовые страницы самого сайта (информацию о сайте), а на всех остальных роутах уже использовать применение выбранного языка Куками, с помощью кода выше.
По сути мне надо вставить код чтения Куки и применения языка в какую-то часть Laravel, где будет проверка - не первый ли это роут (который называется index).
Изменено Fullstack (30.08.2021 18:24:57)
Не в сети
В общем не нашел какой-нибудь уже существующий класс или функцию для вставки кода чтения Кук, поэтому создал middleware:
> php artisan make:middleware UserLang
<?php
namespace Vanguard\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
class UserLang
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($request->hasCookie('lang')) {
$lang = Cookie::get('lang');
if (in_array($lang, locales()))
locale($lang);
else
Cookie::queue( Cookie::forget('lang') );
}
return $next($request);
}
}
Зарегистрировал его в $routeMiddleware в app/Http/Kernel.php и в роутере заключил пользовательскую часть в группу с использованием этого Middleware. Не знаю о правильности этого решения, Laravel для меня во многом тёмный лес, поэтому если можно сделать лучше, я только рад услышать
Не в сети
Страницы 1