【发布时间】:2021-01-09 10:55:20
【问题描述】:
我正在尝试在 laravel 应用程序中设置本地化,但我的中间件似乎导致了 ERR_TOO_MANY_REDIRECTS 错误。该站点将在每个地区略有不同,我正在使用 laravel lang/ 文件来交换电话号码等。这没问题。当我更改语言环境时,我会从 lang 文件中获得正确的数字。当我只有中间件来检查 cookie 是否已设置为设置也可以工作的语言环境时。
我还有中间件可以忘记本地化路由的前缀,因此我不必使用语言环境参数更新我的方法。
如果在我的中间件中使用允许的语言环境设置了 cookie,我的问题是设置 url 前缀。如果语言环境是“en”,我也想忽略前缀,因为它将是默认值。
下面是代码
routes/web.php
Route::get('/', 'HomeController@index')->name('home');
Route::get('/reader/{identifier}', 'ReaderController@show')->name('reader');
Route::get('/locale/{locale}', SetLocaleController::class)->name('set.locale');
Route::group(['prefix' => '{locale?}', 'where' => ['locale' => implode('|', array_keys(config('app.allowed_locales')))], 'middleware' => 'redirect.localization'], function () {
Route::get('/', 'HomeController@index')->name('home');
Route::middleware('forget.prefix')->get('/reader/{identifier}', 'ReaderController@show')->name('reader');
});
Middleware/Localization.php - 添加到Kernel.php 中的 Web 中间件组。它检查 cookie 并设置语言环境,并应重定向到正确的语言环境前缀。如果没有设置 cookie,那么我们会获取用户的地理位置并进行设置。
public function handle($request, Closure $next)
{
// Get requested url
$segments = collect($request->segments());
if ($segments->count() && Arr::exists(config('app.allowed_locales'), $segments[0])) {
$segments->shift();
}
$locale = Cookie::get('locale');
if ($locale ?? false) {
// Set the app locale.
App::setLocale($locale);
if ($locale != 'en') {
$segments->prepend($locale);
return redirect()->to($segments->implode('/'));
}
} else {
// Check for geo here and set it.
}
return $next($request);
}
Middleware/RedirectLocalization.php - 此中间件仅在路由组上设置为前缀。它检查是否允许传递的语言环境并设置语言环境和 cookie。这是在Kernel.php 的$routeMiddleware 数组中设置的
public function handle($request, Closure $next)
{
$locale = $request->segment(1);
if (Arr::exists(config('app.allowed_locales'), $locale)) {
// Set the app locale.
App::setLocale($locale);
// Save app locale in a Cookie.
Cookie::queue(Cookie::make('locale', $locale, 525600));
}
return $next($request);
}
Controllers/SetLocaleController.php - 在这里可以通过网站上的菜单手动设置区域设置。
public function __invoke($locale, Request $request)
{
$redirectUrl = parse_url(url()->previous());
$segments = Str::of($redirectUrl['path'])->trim('/')->explode('/');
if (Arr::exists(config('app.allowed_locales'), $segments[0])) {
$segments->shift();
}
if (Arr::exists(config('app.allowed_locales'), $locale)) {
// Set the app locale.
App::setLocale($locale);
// Save app locale in a Cookie.
Cookie::queue(Cookie::make('locale', $locale, 525600));
// Add locale to segments for redirect.
if ($locale != 'en') {
$segments->prepend($locale);
}
} else {
// Set locale to current locale.
App::setLocale(config('app.fallback_locale'));
}
// Redirect back
return redirect()->to($segments->implode('/'));
}
Controllers/ReaderController.php - 这里没有什么特别之处,但我想添加它来解释忘记.prefix 中间件。如果我不添加 forget.prefix 中间件,则 $reader 参数将成为语言环境。
public function show($reader, Request $request)
{
$reader = Reader::find($reader);
return view('readers.show', [
'reader' => $reader
]);
}
Middleware/ForgetPrefix.php - 这个中间件移除了前缀,这样我们就可以访问控制器方法中的参数,而无需在控制器中的方法中添加 $locale 参数。
public function handle($request, Closure $next)
{
$request->route()->forgetParameter('locale');
return $next($request);
}
所以我的问题是,如果已在 cookie 中设置了区域设置,我该如何设置 URL 前缀而不会出现太多重定向错误?
【问题讨论】:
标签: laravel localization middleware