90%原因是LoadLangPack中间件未启用或lang.php配置与路径不一致:需在app/middleware.php全局注册think\middleware\LoadLangPack并置于SessionInit后,default_lang和allow_lang_list须严格匹配app/lang/下文件名(如'zh-cn'),且GET参数名、cookie_var等须与配置一致。

改了 config/lang.php 但语言切换还是没反应,90% 是中间件没启用或配置与加载路径不一致。
LoadLangPack 中间件必须显式启用
ThinkPHP6 不会自动加载语言包,think\middleware\LoadLangPack 必须手动注册,否则所有 lang() 调用都返回原键名。
- 打开
app/middleware.php,在全局中间件数组中加入'think\middleware\LoadLangPack' - 确认该中间件排在
think\middleware\SessionInit之后(若依赖 session 存语言) - 别只在路由里加——全站多语言需全局生效,单加路由中间件会导致控制器里
Lang::get()提前执行而未加载
lang.php 配置项和实际路径必须严格对齐
框架按 config/lang.php 里的 default_lang 和 allow_lang_list 去找对应文件,错一个字符就加载失败。
-
default_lang必须是小写短横线格式,如'zh-cn',不能是'zh_CN'或'zh' -
allow_lang_list里的值必须和语言包文件名完全一致:app/lang/zh-cn.php对应'zh-cn',不是'zh_cn' - 检查
app/lang/下是否存在该文件,且文件以return [];开头,无 BOM、无空行、无echo - 多应用模式下,路径是
app/应用名/lang/zh-cn.php,不是app/lang/应用名/zh-cn.php
语言侦测参数名和优先级容易被忽略
框架默认按 GET → Cookie → Header → Accept-Language 顺序取语言,但各渠道的变量名要和配置匹配,否则参数传了也白传。
立即学习“PHP免费学习笔记(深入)”;
-
detect_var默认是'lang',所以?lang=en-us才有效;改成'l'就得用?l=en-us -
cookie_var默认是'think_lang',不是'lang'—— 写错就存不进 cookie,切完刷新又回退 -
header_var默认是'think-lang',前端发请求头必须是think-lang: zh-cn,不是Accept-Language: zh-CN - GET 参数优先级最高,哪怕 cookie 里存了
en-us,只要 URL 带?lang=zh-cn,就会强制切换
Lang::setLocale() 后没 reload 导致翻译失效
手动调用 Lang::setLocale('ja-jp') 不会自动重载语言包,必须显式触发加载,否则 lang('hello') 还是读旧语言。
- 调用
Lang::setLocale($lang)后,立即跟一句Lang::load() - 务必校验
$lang是否在allow_lang_list白名单内,避免传入非法值导致Lang::load()报错退出 - 如果用了模块化路由(如
app/api),Lang::load()默认只加载app/lang/,需手动指定路径:Lang::load(app_path() . 'api/lang/' . $lang . '.php'); - 别在控制器
__construct()里调Lang::setLocale()—— 此时中间件还没跑完,Lang状态可能被后续覆盖
最常漏掉的是中间件注册和 Lang::load() 的手动触发。框架不会报错,只会静默返回键名,导致你反复检查语言包内容却找不到问题根源。



















