ThinkPHP多语言不支持降级,仅单层匹配;lang()查无键时返回原字符串而非报错,便于开发兜底但易掩盖漏译;必须用lang/zh-cn/common.php格式,大小写敏感且路径严格;切换语言须在中间件早期调用Lang::setLang(),并显式注册Lang中间件。

ThinkPHP 多语言配置本身不支持“降级”概念——它没有 fallback 语言链(比如 en-us → en → default),只有单层匹配:请求语言存在对应 lang/{lang}/common.php 就加载,否则直接回退到 default_lang,不尝试找近似语言包。
lang() 查不到 key 时为什么没报错,还返回原字符串?
这是 ThinkPHP 的默认行为设计:当 lang('missing_key') 在当前语言包里找不到该键时,函数直接返回 'missing_key' 字符串本身,而不是抛异常或返回空。这方便开发期快速兜底,但上线后极易掩盖漏翻译问题。
- 调试模式下会记录日志(
runtime/log/),但线上环境静默处理 - 检查遗漏最有效的方式是写个脚本遍历所有控制器/模板中出现的
lang()或__('...')调用,再比对各语言包数组的 key 集合 - 不要依赖“看起来显示正常”来判断多语言生效——可能只是 key 没配,却返回了英文 key 当文本
lang/ 目录下放 zh-CN.php 还是 lang/zh-cn/common.php?
必须是 lang/zh-cn/common.php(小写路径 + common.php 文件名)。任何偏差都会导致静默失败:
-
zh-CN.php、ZH-CN/common.php、lang/zh_cn/common.php全部无效 - Linux 服务器对大小写敏感,
lang/zh-cn/和lang/zh-CN/是两个不同目录 - 语言包不能放在
config/lang.php或根目录下,框架只扫描lang/子目录 - 模块级语言包优先级高于应用级,即
app/module/lang/zh-cn/common.php会覆盖app/lang/zh-cn/common.php
切换语言后部分文字还是旧的,是不是缓存没清?
不是缓存问题,是语言包加载时机不对。ThinkPHP 的语言包在请求生命周期早期一次性加载,之后调用 Lang::setLang('en-us') 只会改上下文,不会重新读取文件内容。
立即学习“PHP免费学习笔记(深入)”;
- 必须在中间件(如
app\common\middleware\Lang.php)中、且在$next($request)前调用Lang::setLang() - 切勿在控制器构造函数或
initialize()中设置——此时语言包已加载完毕 - 如果手动调用了
Lang::setLang()却发现没生效,先确认lang/en-us/common.php确实存在且可读 - Cookie 必须用
cookie('think_lang', 'en-us')写入,$_COOKIE['lang']不会被识别
最容易被忽略的是:Lang 中间件必须显式注册在 app/middleware.php 里,且顺序要在 SessionInit 之后、路由之前;否则整个语言机制形同虚设,连 Lang::detect() 都拿不到请求上下文。



















