thinkphp6多应用下语言包必须按应用隔离存放于app/应用名/lang/语言标识.php,开启app_multi,注册loadlangpack中间件并置于sessioninit后,语言标识统一小写短横线,切换语言需调用lang::setlocale()并校验白名单。

语言包路径必须匹配多应用结构
ThinkPHP6在多应用模式下,语言包不会自动从app/lang/加载,而是按应用名隔离。如果你有app/admin/和app/api/两个应用,却只把zh-cn.php放在app/lang/,那admin和api都读不到——框架根本不会去那里找。
实操建议:
- 每个应用的语言包必须放在
app/应用名/lang/语言标识.php,例如app/admin/lang/zh-cn.php - 确认
config/app.php中'app_multi' => true已开启,否则框架仍走单应用逻辑 - 不要复用
app/lang/下的文件,哪怕内容完全一样——它对多应用无效 - 若需共用部分翻译,用
extend_list在config/lang.php里显式引入,例如:'extend_list' => ['zh-cn' => [app()->getBasePath() . 'lang/zh-cn/common.php']]
LoadLangPack中间件未注册或顺序错误
即使路径全对,Lang::get('xxx')返回原key,大概率是think\middleware\LoadLangPack没生效。这个中间件不是默认启用的,且必须在SessionInit之后执行,否则无法读取cookie_var或正确解析detect_var。
实操建议:
- 检查
app/middleware.php,确保'think\middleware\LoadLangPack'在数组中,且位置在'think\middleware\SessionInit'之后 - 如果用了自定义中间件(如权限校验),别把它插在
LoadLangPack前面——语言环境必须在控制器执行前就确定好 - 临时加一行
var_dump(Lang::getLangSet()); die();在控制器开头,看输出是不是预期语言标识;如果是zh-cn但翻译仍不生效,说明语言包没加载,不是语言没切对
语言标识大小写与分隔符不一致
ThinkPHP6只认小写字母+短横线格式的标识,比如zh-cn、en-us。任何偏差都会导致静默失败:写成ZH-CN、zh_CN、zh或zh_CN.php,框架连文件都不尝试包含。
实操建议:
- 所有地方统一使用小写短横线:
config/lang.php里的default_lang、allow_lang_list,URL参数?lang=en-us,Cookie值think_lang=zh-cn,文件名app/admin/lang/zh-cn.php - Linux服务器上
zh-cn.php和zh-CN.php是两个不同文件,Windows开发时可能不报错,一部署就失效 - 用
ls -l app/admin/lang/确认文件名确实是小写,没有隐藏字符;编辑器保存时关掉BOM
Lang::setLocale()调用过晚或未触发加载
手动切换语言时,很多人直接改$_GET['lang']或Cookie,但LoadLangPack中间件不会因此重载语言包。必须显式调用Lang::setLocale(),并确保后续有Lang::load()触发(通常自动,但手动设后建议补一手)。
实操建议:
- 在中间件或控制器
initialize()里做切换,例如:Lang::setLocale(input('lang', '', 'trim'));,然后立刻Lang::load(); - 务必校验输入值是否在
allow_lang_list白名单内,避免传入../../etc/passwd类恶意字符串导致路径遍历(虽然TP6本身做了防护,但白名单仍是必须) -
Lang::setLocale()不修改session或cookie,如需持久化,得自己存,比如:Cookie::set(config('lang.cookie_var'), $lang);
最常被忽略的是:多应用下每个应用的语言配置相互独立,app/admin/config/lang.php和app/api/config/lang.php都得单独配,不能只改根目录的config/lang.php。路径、标识、中间件、时机,四者缺一不可,错一个就静默退回到键名显示。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











