分组语言包读取失败的根本原因是路径错误、中间件未注册或Lang::setLocale()调用过晚;必须严格遵循app/lang/{lang}/common.php路径规范,启用think\middleware\Lang中间件,并确保在路由调度前完成locale解析与包加载。

分组语言包读取失败,基本就是路径没对上、中间件没注册、或 Lang::setLocale() 调得太晚——不是框架不支持,是它只认死规矩。
分组语言包路径必须是 app/lang/{lang}/common.php
ThinkPHP6 不会自动把 app/lang/zh-cn.php 拆成模块级结构;它只在启用了「分组」(即多应用或模块)时,才按 app/{group}/lang/{lang}/common.php 或 app/lang/{lang}/{group}.php 查找。但前提是:你得先让框架知道当前请求属于哪个 group。
- 单应用下,
app/lang/zh-cn/common.php是唯一有效路径;app/lang/zh-cn.php会被忽略 - 多应用模式(如
app/admin和app/api),必须确保app/admin/lang/zh-cn/common.php存在,且文件返回纯数组:return ['login' => '登录']; - 若用
lang_auto_load => true,框架会尝试加载app/lang/zh-cn/{controller}.php,但 controller 名必须小写、无命名空间前缀(如index.php,不是IndexController.php) - 任何大小写错误(
ZH-CN)、下划线(zh_CN)、多余目录层级(app/lang/zh-cn/lang/common.php)都会导致静默失败,Lang::get('login')直接返回键名
Lang 中间件必须注册且顺序靠前
分组语言包依赖 think\middleware\Lang 中间件在路由调度前完成 locale 解析和包加载。它不跟 LoadLangPack 冲突,但必须显式启用,且不能放在 SessionInit 之前。
- 检查
app/middleware.php是否包含think\middleware\Lang::class,不是注释掉,也不是拼错类名 - 多应用下,每个应用的
middleware.php都要单独加,不能只配全局中间件 - 如果用了自定义中间件链(比如路由级绑定),需确认
->middleware(Lang::class)在SessionInit之后、AllowCrossDomain之类之前 -
Lang::setLocale('zh-cn')放在控制器里无效——此时语言包早已加载完毕,后续调用Lang::get()仍走默认语言
Lang::get() 返回原 key?先查是否加载了对应分组包
返回键名不是 bug,是框架告诉你:“我根本没找到你要的语言包”。尤其在分组场景下,它不会 fallback 到 app/lang/zh-cn/common.php,而是严格按当前 group 查找。
立即学习“PHP免费学习笔记(深入)”;
- 用
Lang::load()手动触发一次加载,传入完整路径测试:Lang::load(app_path() . 'admin/lang/zh-cn/common.php');,成功则说明路径权限没问题 - 检查当前请求的 group 名是否被正确识别:dump($this->app->http->getName()),如果不是
admin却去加载admin/lang,自然失败 - 验证器里调
lang('user_not_found')前,确保Lang::setLocale()已执行,且app/admin/lang/zh-cn/validate.php存在并含对应键 - CLI 环境无自动 group 推断,必须手动
Lang::setLocale('zh-cn')+Lang::load(...),否则一律 fallback 到en-us
动态切换分组语言时,Cookie 键和路径必须匹配
前端点“切换语言”按钮后没生效,大概率是 Cookie 写错了位置,或者中间件压根没读到。
- ThinkPHP 只读
think_lang这个 Cookie 键,不是lang,也不是language - 写 Cookie 必须用
cookie('think_lang', 'zh-cn'),手写setcookie()容易漏path或domain,导致中间件读不到 - Cookie 的
path必须为/(或与应用部署路径一致),否则admin/下写的 Cookie,api/请求进不来 -
Lang::setLocale()只改本次请求上下文,不写 Cookie;想持久化,得自己cookie('think_lang', $lang),且确保中间件配置中use_cookie => true
分组语言包最脆弱的环节不在语法,而在路径和时机——一个斜杠大小写、一行中间件注册顺序、一次 Cookie 键名写错,都足以让整个翻译链静默崩塌。别猜,直接 dump 路径、check 中间件注册状态、抓包看 Cookie 是否送达。



















