Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 14.04.2018 11:57:41

Majestio
Откуда: Минск
Сообщений: 23
Сайт

Мультиязычность в Laravel 5

Приветствую!

Пользую Laravel 5.6, php 7.2, mysql 5.(6?), разработка под виндой 10. Потом планирую все это перенести под FreeBSD. В общем, это все не важно.

Возникла необходимость склепать несколько сайтов небольшого размера. Начал читать доки по Laravel 5. Идеология вроде достаточна понятна. Решил начать с того, что хочу смастерить в самом начале шаблон мультиязычного сайта. Нашел статью по этому вопросу. Прочитал - тоже все понятно. Но возникли вопросы по статье:

1) Автор статьи решил использовать middleware-решение. В комментах ему посоветовали другой вариант - просто использовать локаль в маршрутах. А автор статьи, и комментирующий обозвали друг друга огородостроителями :-) Кто из них прав? Если оба неправы - то как правильно?

2) Автор статьи в своем решении в некоторых местах парсит URL, потом его склеивает. А нельзя ли это решение упростить? А именно, прописывать в маршрутах URL без указания языка, до обработки брать текущую локаль из куков, и вставлять язык из куков или по умолчанию и отправлять на последующую обработку? Мне кажется, если получится избавиться от парсинга/склейки URL, то будет кода по-меньше. Ваше мнение?

И вопрос не по статье

Как посоветуете организовать хранение в БД мультиязычных материалов? Например различных новостей, событий, галлерей ... & etc.

Не в сети

#2 14.04.2018 14:17:42

Re: Мультиязычность в Laravel 5

Опыта в laravel у меня мало, но не вижу проблем в использовании middleware. Я у себя реализовал так:
В app.php добавляем ’locales’ ⇒ [’ru’, ’az’],
Создаем middleware Locale

PHP
class Locale
{
    public function 
handle($requestClosure $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 регистрируем метод

PHP
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?) означает что это необязательный параметр

PHP
Route::get('/articles/{lang?}', ['as' => 'articles''uses' => 'ArticlesController@index']);
Route::get('/article/{id}/{lang?}', ['as' => 'article''uses' => 'ArticlesController@page']);

Формируем ссылки ($current_lang и $default_lang вы можете сформировать в контроллере)

PHP
<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)

Не в сети

#3 14.04.2018 14:20:55

Re: Мультиязычность в Laravel 5

Насчет хранения в БД;
Таблица langs
id, lang

Таблица articles
id, date

Таблица article_lang
article_id, lang_id, title, descr .... и т.д

Не в сети

#4 14.04.2018 14:26:48

Re: Мультиязычность в Laravel 5

У меня сделано так:

Идем в app\Http\Middleware, создаем файл LocaleMiddleware.php

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($requestClosure $next) {
        
$locale self::getLocale();

        if(
$localeApp::setLocale($locale);

        return 
$next($request);
    }

}

Далее открываем папку config и редактируем файл app.php
нужно добавить в providers на выше созданный файл

PHP
App\Providers\RouteServiceProvider::class,

Последний шаг, открываем routes/web.php
В самый верх добавляем:

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($refererPHP_URL_PATH);
    
$segments explode('/'$parse_url);
    if (
in_array($segments[1], App\Http\Middleware\LocaleMiddleware::$languages)) {
        unset(
$segments[1]);
    }

    
array_splice($segments10$lang);
    
$url Request::root().implode("/"$segments);
    if(
parse_url($refererPHP_URL_QUERY)){
        
$url $url.'?'parse_url($refererPHP_URL_QUERY);
    }
    return 
redirect($url);
})->
name('lang');

теперь оборачиваем все роуты в обертку

PHP
Route::group(['prefix' => App\Http\Middleware\LocaleMiddleware::getLocale()], function(){
    
Auth::routes();
    
Route::get('logout','Auth\LoginController@logout');
    
Route::get('/''HomeController@index')->name('home');
});

ссылки будут вида: mysite.com/ru

Не в сети

#5 14.04.2018 14:55:06

Majestio
Откуда: Минск
Сообщений: 23
Сайт

Re: Мультиязычность в Laravel 5

Всем большое спасибо!
Остался вопрос инициализации текущего языка, если у клиента сохранились куки.

novichok, в простейшем случае - прокатит. Но я планирую создать схему с конструируемыми "материалами". Ожидается, будет на порядок сложнее.

Не в сети

#6 14.04.2018 16:31:06

Re: Мультиязычность в Laravel 5

Насчет хранения в куках можно написать что-то типа:
middleware Locale

PHP
class Locale
{
    public function 
handle($requestClosure $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);
    }
}

Создаем роут для смены языка

PHP
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)

Не в сети

#7 14.04.2018 16:36:10

Majestio
Откуда: Минск
Сообщений: 23
Сайт

Re: Мультиязычность в Laravel 5

novichok, и еще раз - большое спасибо!

Не в сети

Подвал раздела