Lang中间件未注册导致语言切换不生效,必须在app/middleware.php中注册think\middleware\Lang或路由级绑定;语言包路径须为app/lang/{lang}/common.php({lang}小写连字符格式);语言设置须在中间件中完成且早于翻译调用。

Lang中间件没注册,语言切换根本不会触发
ThinkPHP6的Lang中间件默认不启用,不是配了lang.php就自动工作。如果只改配置、不注册中间件,整个语言侦测流程压根不会执行,Lang::get()永远返回默认语言或键名本身。
- 全局生效:把
think\middleware\Lang加到app/middleware.php的返回数组里,不是注释掉、也不是写错命名空间 - 路由级生效:在路由定义里显式绑定,例如
Route::get('home', 'Index/index')->middleware(\think\middleware\Lang::class) - 别在控制器构造函数里调
Lang::detect()——中间件还没跑,你手动调可能被后续中间件覆盖
语言包路径或文件名不符合规范,系统静默忽略
ThinkPHP6对语言包路径和命名极其敏感,错一个字符(比如大小写、下划线、连字符)就会跳过加载,且不报错。常见现象是lang('hello')始终返回hello,而不是翻译值。
- 目录结构必须是
app/lang/{lang}/common.php,其中{lang}为小写连字符格式,如zh-cn、en-us,不能是zh_CN或ZH-CN -
common.php必须返回纯关联数组,例如return ['hello' => '你好'];,不能嵌套在return ['zh-cn' => [...]]里 - 若用模块化项目,优先检查模块下的
lang/目录是否存在,它会覆盖应用级语言包
语言切换逻辑写在错误位置,导致本次请求无效
语言切换不是“设了就立刻全局生效”,它只影响后续的lang()或Lang::get()调用。如果在控制器方法里才调Lang::setLang($lang),那之前已执行的模板渲染、验证器初始化、甚至中间件里的Lang::get()都还是旧语言。
- 切换动作应放在中间件中完成,例如在
app/middleware.php里加一个自定义中间件,读取input('lang')或session('lang')后立即调Lang::setLang() - 务必校验输入值是否在
allow_lang_list白名单内,避免传入../../etc/passwd类恶意字符串造成路径遍历 - 设完
Lang::setLang()后,建议紧跟Lang::load()(尤其手动切换时),防止语言包未加载导致翻译为空
GET参数lang=没被识别,因为detect_var配置或优先级被覆盖
很多人以为加个?lang=en-us就能切语言,结果没反应——问题常出在config/lang.php里detect_var没配,或虽配了但其他渠道(如Cookie、Header)干扰了优先级。
立即学习“PHP免费学习笔记(深入)”;
- 确认
config/lang.php中'detect_var' => 'lang'已设置,且'use_cookie' => true、'cookie_var' => 'think_lang'也开启 - 系统默认按“GET参数 → Cookie → Header → Accept-Language”顺序侦测,如果Cookie里已有旧值,GET参数会被忽略;可临时清Cookie验证是否为此原因
- 若用
Lang::setLocale()手动设语言,请注意它不操作Cookie或Session,持久化需额外写setcookie()或$request->session()



















