ThinkPHP默认不自动识别用户语言偏好,必须同时开启lang_switch_on和lang_auto_detect配置,并正确注册Lang中间件且置于SessionInit之后、路由之前,否则Lang::get()始终返回默认语言内容。

ThinkPHP 默认不会自动识别用户语言偏好,必须显式开启检测机制并确保加载顺序正确,否则 Lang::get() 返回的永远是默认语言内容。
lang_switch_on 和 lang_auto_detect 都得开
只设 lang_switch_on => true 不够,lang_auto_detect 也必须为 true,否则系统压根不解析 $_SERVER['HTTP_ACCEPT_LANGUAGE']。这两个配置在 config/app.php 里要同时存在:
return [
'lang_switch_on' => true,
'lang_auto_detect' => true,
'default_lang' => 'zh-cn',
'allow_lang_list' => ['zh-cn', 'en-us'],
];
-
lang_auto_detect关闭时,即使浏览器请求头带Accept-Language: en-us,也不会触发切换 -
allow_lang_list必须包含目标语言代码,比如写成['zh_CN']就无效——ThinkPHP 只认短横线格式zh-cn - 如果用了多应用模式,每个应用的
config/app.php都得单独配,主配置不继承
Lang 中间件必须注册且位置不能错
ThinkPHP6 的语言检测逻辑封装在 think\middleware\Lang 中间件里,它不是默认启用的。没注册就等于没写,整个请求生命周期里语言包都不会加载。
- 检查
app/middleware.php,确认think\middleware\Lang::class在数组中且未被注释 - 中间件顺序很重要:必须排在
think\middleware\SessionInit::class之后、路由中间件之前,否则读不到 Cookie 或 Session - 中间件只在请求初始化阶段执行一次,后续手动改
$_COOKIE['think_lang']不会重新触发检测
浏览器语言识别实际只看 Accept-Language 第一项
ThinkPHP 解析 Accept-Language 时,只取第一个语言标签(如 zh-CN,zh;q=0.9,en;q=0.8 → zh-cn),不做权重计算或 fallback 匹配。
立即学习“PHP免费学习笔记(深入)”;
- 如果用户浏览器设的是
ja-JP,但你的allow_lang_list没写ja-jp,就会直接回退到default_lang,不会尝试ja或jp - 测试时别只靠 Chrome 设置语言,用 curl 手动构造头更可靠:
curl -H "Accept-Language: en-us" http://localhost - 某些代理或 CDN 会剥离或覆盖
Accept-Language头,此时检测必然失效,得靠 URL 参数或 Cookie 补充
Cookie 键名和路径必须严格匹配
Lang 中间件默认只读 $_COOKIE['think_lang'],不是 lang、language 或其他自定义名;而且写入时必须保证 Cookie 路径与当前域名一致。
- 前端 JS 切换语言时,用
document.cookie = "think_lang=en-us; path=/; domain=.example.com",漏掉path=/就可能读不到 - 后端写 Cookie 推荐统一用
cookie('think_lang', 'en-us'),避免手写setcookie()时编码或作用域出错 - Cookie 值必须在
allow_lang_list范围内,否则中间件会忽略并继续走浏览器检测逻辑
最容易被忽略的是中间件注册状态和 Cookie 键名——两者任一缺失,整个自动识别链就断了,而错误又完全静默,Lang::get() 看似正常返回,实则一直是默认语言。调试时优先用 Lang::getLangSet() 打印当前生效语言,比翻日志快得多。



















