Laravel 5.6路由Locale设置异常:始终默认'en'问题求助
这个问题我之前也碰到过!你原来的写法有个关键误区——App::setLocale()是在路由注册的时候执行的,不是用户请求到来的时候。当你的Laravel应用启动加载路由文件时,两个路由组里的setLocale会依次跑一遍,最后执行的是en那个,所以不管你访问fr/home还是en/home,Locale都会被定格成en,这就是为啥始终返回'en'的原因。
给你推荐最优雅的解决方案:用中间件来动态设置Locale,因为中间件是在请求处理流程中触发的,能精准对应当前请求的前缀。
步骤1:创建Locale中间件
先运行Artisan命令生成中间件:
php artisan make:middleware SetLocale
然后打开app/Http/Middleware/SetLocale.php,把逻辑改成这样:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\App; class SetLocale { public function handle($request, Closure $next) { // 从路由前缀获取locale值 if ($locale = $request->route('locale')) { // 先验证是否是我们允许的语言,避免非法值 if (in_array($locale, ['en', 'fr'])) { App::setLocale($locale); } } return $next($request); } }
步骤2:注册中间件
打开app/Http/Kernel.php,在$routeMiddleware数组里添加这个中间件的别名:
protected $routeMiddleware = [ // 其他中间件... 'setlocale' => \App\Http\Middleware\SetLocale::class, ];
步骤3:重构路由定义
不用再写重复的路由组了,用参数化前缀+中间件的方式,简洁又灵活:
Route::group(['prefix' => '{locale}', 'middleware' => 'setlocale'], function () { Route::get('home', 'HomeController@index'); // 所有需要多语言支持的路由都可以放在这个组里 });
如果你实在想分开写两个前缀(比如有特殊需求),也可以给每个组单独加中间件:
Route::group(['prefix' => 'fr', 'middleware' => 'setlocale'], function () { Route::get('home', 'HomeController@index'); }); Route::group(['prefix' => 'en', 'middleware' => 'setlocale'], function () { Route::get('home', 'HomeController@index'); });
不过参数化的方式显然更省心,不用重复写相同的路由逻辑。
测试验证
现在访问fr/home,在HomeController@index里调用App::getLocale(),应该就能返回'fr'了;访问en/home则返回'en',完美解决问题!
另外提个小建议:最好把允许的语言列表放到配置文件里(比如config/app.php新增locales数组),这样后续添加语言时不用改中间件代码,更易维护。
内容的提问来源于stack exchange,提问作者waatz
相关产品推荐
相关产品推荐

