Ответ 1
Я решил проблему из этой статьи https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale
Благодаря людям, которые внесли слово "не стойкие",
Я использую раскрывающиеся списки для языков, состоящих из английского и голландского.
<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',
];
Я решил проблему из этой статьи https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale
Благодаря людям, которые внесли слово "не стойкие",
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
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, оно соответствует домену и/или маршрутам. Он имеет некоторые преимущества перед решениями, основанными на сеансах:
Это может иметь и недостатки.
setLocale
только изменит язык для остальной части запроса с этого момента.
Чтобы сохранить его, вы можете изучить настройку выбранного языка в сеансе (https://laravel.com/docs/session). Затем вы можете создать миддинг (https://laravel.com/docs/middleware), где вы можете проверить, установлен ли язык в сеансе, а затем применить его для запроса :)