子应用语言包必须独立配置路径、中间件和作用域:路径需为小写短横线命名且位于子应用目录下,中间件须显式启用,lang() 调用仅限本应用语言包。

子应用语言包路径必须独立且小写短横线命名
多应用下,app/admin/lang/zh-cn.php 和 app/api/lang/en-us.php 是合法路径;但若复用全局 app/lang/ 下的语言包,子应用的 LoadLangPack 中间件会跳过加载——因为中间件默认只查当前应用目录下的 lang/ 子目录。
常见错误现象:访问 /admin 时语言始终是默认值,或 lang('welcome') 返回键名而非翻译内容。
- 每个子应用必须有自己的
lang/目录,不能靠 config/lang.php 的extend_list“补救”路径缺失 - 文件名严格小写+短横线:
zh-cn.php✅,zh_CN.php❌,zh.php❌ - 子应用内若需扩展语言包(如加载
common.php),必须在该应用自己的config/lang.php中配置extend_list,而非全局 config/lang.php
子应用的 LoadLangPack 中间件不会自动启用
ThinkPHP6 的 LoadLangPack 中间件默认只在主应用(index)中注册。多应用模式下,admin 或 api 应用若没显式启用该中间件,语言包根本不会加载。
错误配置示例:app/middleware.php 里只写了全局中间件,但 app/admin/middleware.php 是空的或没继承父级配置。
- 必须为每个子应用单独配置中间件文件:
app/admin/middleware.php内容需包含return [ \think\middleware\LoadLangPack::class ]; - 不要依赖“继承”或“自动合并”——TP6 多应用中间件不共享、不穿透
- 确认
app/admin/config/app.php中'middleware' => true已开启,否则中间件数组会被忽略
lang() 调用作用域绑定到当前应用,跨应用调用会失效
lang('welcome') 在 admin 应用中执行时,只会查找 app/admin/lang/ 下对应语言包;它不会向上回溯到 app/lang/,也不会去读 api 应用的语言文件。
典型误用:在 admin 控制器里调用 lang('user.delete'),但该键只定义在 app/api/lang/zh-cn.php 中 → 返回原字符串。
- 语言键名不是全局唯一命名空间,而是按应用隔离的
- 若多个应用共用一套文案,应把公共语言包复制到每个应用的
lang/目录下,或统一用extend_list显式引入(路径必须指向本应用可读位置) - 避免在子应用中通过
Lang::setLang('en-us')手动切换——它只影响当前请求生命周期内的语言上下文,且不触发中间件重载语言包逻辑
异常处理类中获取语言失败,本质是 Request 对象未绑定应用上下文
在自定义 ExceptionHandle 的 render() 方法里调用 lang('error.network') 返回键名,往往不是语言包没加载,而是此时 Request 尚未完成应用识别,Lang 组件查不到当前应用路径。
原因:异常可能发生在路由解析前(如中间件抛出),$request->app_name() 返回空或 index,导致语言包加载路径错误。
- 不要在
render()开头就调用lang();先判断$request->isApp() === true,再安全调用 - 更稳妥的做法是:在
render()中直接返回硬编码的 fallback 提示(如'Network error'),或改用Lang::get('error.network', [], $lang)显式传入语言标识 - 若需动态语言,建议在
report()阶段记录原始异常,render()仅做响应包装,避免依赖运行时语言上下文
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











