Laravel 8 使用JSON语言包实现本地化功能不生效如何解决
问题核心原因
你的代码不生效是三个低级错误导致的:
App::setLocale()仅对当前单次请求生效,你在切换方法里设置完直接重定向,新请求不会保留之前设置的语言值,等于白设- 自定义中间件写法完全错误:既没有从持久化存储里读取用户选择的语言,还错误给handle方法加了无法自动注入的
$lang参数 - 每次请求都执行
config:clear/config:cache/cache:clear是完全错误的用法,这些运维类命令只应该在部署时手动执行,请求里调用会严重拖垮性能,也不会帮你持久化语言设置
分步解决方法
第一步:先校验基础配置正确性
- 确认语言文件路径匹配你的Laravel版本:Laravel 9+默认语言目录是和
app同级的lang/文件夹,Laravel 6-8默认是resources/lang/,你放的en.json、ar.json要在对应目录根路径下 - 确认JSON文件格式合法:不能有多余的尾逗号(最后一个键值对后面不能加逗号),文件编码为UTF-8无BOM格式,示例内容:
// en.json 示例 { "Welcome": "Welcome", "Login": "Login" }
- 提前在
config/app.php里定义好支持的语言列表,避免传入非法值:
'available_locales' => ['en', 'ar'],
第二步:修正语言切换路由与控制器逻辑
首先修改路由,增加语言参数合法性校验,web.php代码调整为:
Route::get('lang/{lang}', [HomeController::class,'switchLang'])->name('lang')->whereIn('lang', config('app.available_locales'));
然后修改控制器里的切换方法,删掉所有请求内调用artisan缓存命令的代码,把用户选择的语言存入session(session是跨请求持久化存储的载体):
public function switchLang($lang) { if (!in_array($lang, config('app.available_locales'))) { abort(400); } session(['app_locale' => $lang]); return redirect()->back(); }
第三步:编写正确的全局语言中间件
删掉你之前中间件里多余的参数、多余的artisan命令,中间件的作用是每次请求启动时,从session里读取用户之前选好的语言,设置到当前请求中。修改Language.php代码:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\App; class Language { public function handle(Request $request, Closure $next) { $locale = session('app_locale', config('app.locale')); if (in_array($locale, config('app.available_locales'))) { App::setLocale($locale); } return $next($request); } }
然后打开app/Http/Kernel.php,把中间件注册到web中间件组,确保所有走web路由的请求都会经过这个中间件:
protected $middlewareGroups = [ 'web' => [ // 框架自带的其他中间件保持不动 \App\Http\Middleware\Language::class, ], ];
第四步:常见不生效问题排查
- 如果你之前跑过路由缓存,在命令行手动执行一次
php artisan route:clear清除旧路由缓存即可 - 翻译调用要符合JSON文件规则:在模板里用
{{ __('Welcome') }}直接取JSON中对应键的翻译值,不需要加文件前缀 - 确认你的业务路由都在
web.php里,或者都加载了web中间件组——只有web中间件组会启用session,放在api.php里的路由无法读取session存储的语言值 - 阿拉伯语这类RTL语言要手动给html标签加
dir="rtl"属性,不要因为页面排版问题误以为翻译没生效
内容的提问来源于stack exchange,提问作者HAMZA HUMMAM
相关产品推荐
相关产品推荐

