Невозможно изменить локаль Laravel

Я использую раскрывающиеся списки для языков, состоящих из английского и голландского.

<form class="" action="{{url('/locale')}}" method="post">
            Locale:
              <select class="" name="locale" onchange="this.form.submit()">

                <option value="en" >English</option>
                <option value="du" >Dutch</option>
              </select>
          </form>

Тогда это мои маршруты.php,

Route::post('/locale', function(){

     \App::setLocale(Request::Input('locale'));

     return redirect()->back();
});

И он не работает.

В моем проекте путь такой же

resources/
 /du
   navigation.php
 /en
  /navigation.php

От голландского (du) 'navigation.php'

<?php
return [
  "home" => 'Home-test-dutch',  
];

и для английского (en) 'navigation.php'

<?php
return [
  "home" => 'Home',  
];

Ответ 2

App::setLocale() не является постоянным, он устанавливает языковой стандарт только для текущего запроса (времени выполнения). Что ты можешь сделать:

Route::post('/locale', function(){

     session(['my_locale' => Request::Input('locale')]);

     return redirect()->back();
});

Это установит session key для текущего пользователя. После того, как нам понадобится Middleware для определения локали.

<?php namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Foundation\Application;

class Language {

    public function __construct(Application $app, Request $request) {
        $this->app = $app;
        $this->request = $request;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $this->app->setLocale(session('my_locale', config('app.locale')));

        return $next($request);
    }

}

Будет получен текущий сеанс, а если он пуст, будет применена локаль по умолчанию, которая установлена в конфигурации вашего приложения.

В app\Http\Kernel.php добавьте ранее созданное Language промежуточное ПО:

protected $middleware = [
   \App\Http\Middleware\Language::class,
];

Как глобальное промежуточное программное обеспечение или просто для веб-сайтов (в зависимости от ваших потребностей). Я надеюсь, что это помогает, и дает представление о том, как все работает.

Сценарий №2 Создайте array со всеми доступными локалями в вашем приложении в app config

'available_locale' => ['fr', 'gr', 'ja'],

Внутри Middleware мы будем проверять URL первого сегмента en fr gr cy, если этот сегмент находится в available_locale, установить язык

public function handle($request, Closure $next)
{
      if(in_array($request->segment(1), config('app.available_locale'))){
            $this->app->setLocale($request->segment(1));
      }else{
            $this->app->setLocale(config('app.locale'));
      }

      return $next($request);
}

Вам нужно будет изменить app\Providers\RouteServiceProvider для установки префикса для всех ваших маршрутов. так что вы можете получить доступ к ним domain.com или domain.com/fr/ с French language Найти: mapWebRoutes и добавить это к нему: (перед добавлением use Illuminate\Http\Request;)

public function map(Request $request)
    {
        $this->mapApiRoutes();
        $this->mapWebRoutes($request);
    }
    protected function mapWebRoutes(Request $request)
    {
        if(in_array($request->segment(1), config('app.available_locale'))){
          $locale = $request->segment(1);
        }else{
          $locale = null;
        }
        Route::group([
           'middleware' => 'web',
           'namespace' => $this->namespace,
           'prefix' => $locale
        ], function ($router) {
             require base_path('routes/web.php');
        });
    }

Это добавит к вашим маршрутам префикс с буквой страны, такой как "fr gr cy", за исключением en для неповторяющегося контента, поэтому лучше не добавлять его в available_locales_array

Ответ 3

App::setLocale() не является постоянным. У меня была аналогичная проблема, поэтому я создал промежуточное ПО:

<?php

namespace App\Http\Middleware;

use Closure;

class SetLocale
{
     /**
      * Handle an incoming request.
      *
      * @param  \Illuminate\Http\Request  $request
      * @param  \Closure  $next
      * @return mixed
      */
    public function handle($request, Closure $next)
    {
        if (strpos($request->getHttpHost(), 'fr.') === 0) {
            \App::setLocale('fr');
        } else {
            \App::setLocale('en');
        }
        return $next($request);
    }
}

И я зарегистрировал это промежуточное ПО в app\Http\Kernel:

protected $middlewareGroups = [
    'web' => [
        // ...
        \App\Http\Middleware\SetLocale::class,
        // ...
    ]
];

Этот скрипт работает для двух доменов: http://example.org (ru) и http://fr.example.org (fr). В качестве промежуточного программного обеспечения он запрашивает каждый запрос, поэтому локаль всегда устанавливается в качестве правильной локали в соответствии с URL-адресом.

Мои маршруты выглядели так:

Route::group(['domain' => 'fr.' . config('app.root-domain')], function () {
    Route::get('a-propos', '[email protected]');
    // ...
}
Route::group(['domain' => config('app.root-domain')], function () {
    Route::get('about', '[email protected]');
    // ...
}

Поэтому он отвечает правильной локали:

И я использую тот же контроллер и тот же вид, всего 2 разных маршрута + глобальное промежуточное ПО.

Надеюсь, это поможет, не уверен, что это лучшее решение BTW. Это решение работает без sessio, оно соответствует домену и/или маршрутам. Он имеет некоторые преимущества перед решениями, основанными на сеансах:

  • Никаких возможных ошибок из-за использования сеанса ("волшебный" языковой переключатель)
  • Вы можете переписать свои маршруты. Французский пользователь может захотеть увидеть "/mon-panier" и английский пользователь "/my-cart" в своем URL-адресе.
  • Лучшее индексирование в google (SEO), потому что вы можете иметь реальный индекс по странам с соответствующим контентом.
  • Я использую его в производстве!

Это может иметь и недостатки.

Ответ 4

setLocale только изменит язык для остальной части запроса с этого момента.

Чтобы сохранить его, вы можете изучить настройку выбранного языка в сеансе (https://laravel.com/docs/session). Затем вы можете создать миддинг (https://laravel.com/docs/middleware), где вы можете проверить, установлен ли язык в сеансе, а затем применить его для запроса :)