TP6中Accept-Language头失效需检查lang.php配置、注册Lang中间件、语言包路径命名严格匹配、启用accept_language映射及Cookie持久化。

Accept-Language头没被识别?检查lang.php配置和中间件注册
Accept-Language识别失效,八成不是浏览器没发头,而是框架压根没开这个通道。TP6默认不启用Header侦测,必须手动打开,且Lang中间件没注册就等于没装引擎。
常见错误现象:Lang::get('hello')始终返回hello;浏览器发Accept-Language: zh-TW,zh;q=0.9,但系统加载的还是zh-cn语言包。
- 确认
config/lang.php中'header_var' => 'think-lang'已设置(注意:这不是自动读Accept-Language,而是读自定义请求头) - 若想真正用
Accept-Language,必须设'accept_language' => ['zh-tw' => 'zh-tw', 'zh-cn' => 'zh-cn', 'en-us' => 'en-us'],否则框架只取第一个片段并小写转连字符,但不会匹配到你语言包目录 - 检查
app/middleware.php是否已注册think\middleware\Lang——漏掉这一步,所有侦测逻辑都不会触发 - 别在控制器里调
Lang::detect(),中间件已做这事,重复调可能覆盖结果
浏览器发的是zh-TW,但语言包加载失败?路径和命名必须严格匹配
TP6对语言包路径极其敏感,Accept-Language解析出zh-tw后,会直接拼路径去加载app/lang/zh-tw/common.php。任何大小写、分隔符或层级偏差都会导致静默失败。
常见错误现象:Language file not exists警告;lang('login')返回空或原key;繁体用户看到简体翻译。
立即学习“PHP免费学习笔记(深入)”;
- 语言包目录必须是
app/lang/zh-tw/,不能是app/lang/zh_TW/或app/lang/zh-TW/(系统强制转小写连字符,但目录名必须提前写对) - 文件名必须是
common.php或你在lang.php中声明的其他模块名(如validate.php),不能是zh-tw.php - 繁体包内容要返回纯数组:
return ['login' => '登入'];,不能套一层['zh-tw' => [...]] - 确保
config/lang.php中'allow_lang_list'包含'zh-tw',否则会被 fallback 到default_lang
Lang::get()返回原key?加载时机和作用域错位了
语言包不是全局常驻内存的,它按请求语言+当前模块路径动态加载。Lang中间件执行晚于路由解析,如果控制器里直接调Lang::get()而没等中间件完成,就会取到未初始化的状态。
性能与兼容性影响:每次Lang::get()都查一次已加载的语言数组,本身很快;但路径错配会导致warning并触发include失败,拖慢首字节响应时间。
- 验证器中的错误提示(如
require|email规则)默认查validate.php,不是common.php,字段级键名得写成'user_email.email' => '電子信箱格式錯誤' - 模块级语言包(如
app/lang/zh-tw/admin.php)需显式调用lang('key', '', 'admin'),否则只加载common.php - CLI命令下
Accept-Language不存在,必须手动Lang::setLang('zh-tw')并Lang::load(),否则一律fallback
切换语言后Cookie不持久?Header侦测和Cookie保存要配对启用
仅靠Accept-Language识别是被动的,用户切换语言后若不存状态,下次刷新又回退。TP6的Cookie机制和Header侦测是解耦的,开了侦测不一定存Cookie。
容易踩的坑:前端发think-lang: zh-tw,后端识别成功,但没设Cookie,用户点个链接就切回zh-cn。
- 启用Cookie保存需同时设
'use_cookie' => true和'cookie_var' => 'think_lang'(注意下划线,和header_var的短横线不同) -
Lang::setLocale('zh-tw')只对当次请求有效,要持久化得配合cookie('think_lang', 'zh-tw')或session('lang', 'zh-tw') - Cookie值必须在Lang中间件执行前写入,推荐在中间件里统一处理:先读session或cookie,再
Lang::setLang(),最后Lang::load() - 别依赖
$_GET['lang']自动切换——那是detect_var的事,和Accept-Language无关,混用容易冲突
最常被忽略的是:Accept-Language解析出zh-tw后,框架会尝试加载app/lang/zh-tw/下的所有已声明模块文件,但如果你只放了common.php,而验证器报错时查的是validate.php,那就必然 fallback。路径、命名、模块声明、白名单,四者缺一不可。



















