Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Приветствую!
Пользую Laravel 5.6, php 7.2, mysql 5.(6?), разработка под виндой 10. Потом планирую все это перенести под FreeBSD. В общем, это все не важно.
Возникла необходимость склепать несколько сайтов небольшого размера. Начал читать доки по Laravel 5. Идеология вроде достаточна понятна. Решил начать с того, что хочу смастерить в самом начале шаблон мультиязычного сайта. Нашел статью по этому вопросу. Прочитал - тоже все понятно. Но возникли вопросы по статье:
1) Автор статьи решил использовать middleware-решение. В комментах ему посоветовали другой вариант - просто использовать локаль в маршрутах. А автор статьи, и комментирующий обозвали друг друга огородостроителями :-) Кто из них прав? Если оба неправы - то как правильно?
2) Автор статьи в своем решении в некоторых местах парсит URL, потом его склеивает. А нельзя ли это решение упростить? А именно, прописывать в маршрутах URL без указания языка, до обработки брать текущую локаль из куков, и вставлять язык из куков или по умолчанию и отправлять на последующую обработку? Мне кажется, если получится избавиться от парсинга/склейки URL, то будет кода по-меньше. Ваше мнение?
И вопрос не по статье
Как посоветуете организовать хранение в БД мультиязычных материалов? Например различных новостей, событий, галлерей ... & etc.
Не в сети
Опыта в laravel у меня мало, но не вижу проблем в использовании middleware. Я у себя реализовал так:
В app.php добавляем ’locales’ ⇒ [’ru’, ’az’],
Создаем middleware Locale
class Locale
{
public function handle($request, Closure $next)
{
if (!empty(Route::getRoutes()->match($request)->parameters['lang'])) {
$langs = Config::get('app.locales');
if (($key = array_search(Route::getRoutes()->match($request)->parameters['lang'], $langs)) !== false) {
App::setLocale($langs[$key]);
} else {
abort('404');
}
}
return $next($request);
}
}
В AppServiceProvider регистрируем метод
public function boot()
{
Response::macro('myUrl', function ($alias, $current_lang, $default_lang, $params = false) {
if ($current_lang != $default_lang) {
is_array($params) ? $params['lang'] = $current_lang : $params = ['lang' => $current_lang];
}
return is_array($params) ? route($alias, $params) : route($alias);
});
}
В роутах пишем маршрут. (lang?) означает что это необязательный параметр
Route::get('/articles/{lang?}', ['as' => 'articles', 'uses' => 'ArticlesController@index']);
Route::get('/article/{id}/{lang?}', ['as' => 'article', 'uses' => 'ArticlesController@page']);
Формируем ссылки ($current_lang и $default_lang вы можете сформировать в контроллере)
<a href = "{{response()->myUrl('articles', $current_lang, $default_lang)}}">Новости</a>
<a href = "{{response()->myUrl('article', $current_lang, $default_lang, ['id' => 10])}}">Страница конкретной новости</a>
Изменено novichok (14.04.2018 14:36:01)
Не в сети
Насчет хранения в БД;
Таблица langs
id, lang
Таблица articles
id, date
Таблица article_lang
article_id, lang_id, title, descr .... и т.д
Не в сети
Идем в app\Http\Middleware, создаем файл LocaleMiddleware.php
// LocaleMiddleware.php
<?php
namespace App\Http\Middleware;
use Closure;
use App;
use Request;
class LocaleMiddleware
{
public static $mainLanguage = 'ru';
public static $languages = ['en', 'ru'];
public static function getLocale() {
$uri = Request::path();
$segmentsURI = explode('/',$uri);
if (!empty($segmentsURI[0]) && in_array($segmentsURI[0], self::$languages)) {
return $segmentsURI[0];
} else {
return self::$mainLanguage;
}
}
public function handle($request, Closure $next) {
$locale = self::getLocale();
if($locale) App::setLocale($locale);
return $next($request);
}
}
Далее открываем папку config и редактируем файл app.php
нужно добавить в providers на выше созданный файл
App\Providers\RouteServiceProvider::class,
Последний шаг, открываем routes/web.php
В самый верх добавляем:
Route::get('/', function () {
return redirect('/'. App\Http\Middleware\LocaleMiddleware::$mainLanguage);
});
Route::get('lang/{lang}', function ($lang) {
$referer = Redirect::back()->getTargetUrl();
$parse_url = parse_url($referer, PHP_URL_PATH);
$segments = explode('/', $parse_url);
if (in_array($segments[1], App\Http\Middleware\LocaleMiddleware::$languages)) {
unset($segments[1]);
}
array_splice($segments, 1, 0, $lang);
$url = Request::root().implode("/", $segments);
if(parse_url($referer, PHP_URL_QUERY)){
$url = $url.'?'. parse_url($referer, PHP_URL_QUERY);
}
return redirect($url);
})->name('lang');
теперь оборачиваем все роуты в обертку
Route::group(['prefix' => App\Http\Middleware\LocaleMiddleware::getLocale()], function(){
Auth::routes();
Route::get('logout','Auth\LoginController@logout');
Route::get('/', 'HomeController@index')->name('home');
});
Не в сети
Всем большое спасибо!
Остался вопрос инициализации текущего языка, если у клиента сохранились куки.
novichok, в простейшем случае - прокатит. Но я планирую создать схему с конструируемыми "материалами". Ожидается, будет на порядок сложнее.
Не в сети
Насчет хранения в куках можно написать что-то типа:
middleware Locale
class Locale
{
public function handle($request, Closure $next)
{
$langs = Config::get('app.locales');
if(!is_null($request->cookie('lang'))){
if (($key = array_search($request->cookie('lang'), $langs)) === false){
abort('404');
}
App::setLocale($langs[$key]);
} else {
Cookie::queue('lang', Config::get('app.locale'), 60); /* На 60 минут */
}
return $next($request);
}
}
Route::get('/set-locale/{lang?}', function($lang){
$langs = Config::get('app.locales');
if (($key = array_search($lang, $langs)) === false){
abort('404');
}
return back()->cookie('lang', $langs[$key], 60);
});
Изменено novichok (14.04.2018 17:11:00)
Не в сети
Не в сети
Страницы 1