ThinkPHP语言中间件无内置优先级字段,其执行顺序取决于注册位置:必须置于SessionInit之后、路由调度之前,以确保能正确读取Cookie并生效;插件需单独注册LangSwitch中间件。

ThinkPHP 的语言中间件(think\middleware\Lang)本身没有内置的“优先级字段”可配置,它的执行时机和生效效果,完全取决于它在中间件注册数组中的位置顺序,以及是否满足前置依赖条件。
要让它正确工作,关键不是调高“优先级”,而是把它放在合适的位置——既不能太早(读不到 Cookie/Session),也不能太晚(业务逻辑已执行,语言切换失效)。
一、语言中间件必须放在 SessionInit 之后、路由调度之前
Lang 中间件需要读取 think_lang Cookie 或 Header 等信息,而 Cookie 解析依赖 Session 初始化。若放在 SessionInit::class 之前,$request->cookie() 可能为空或不完整。
✅ 正确顺序示例(app/middleware.php):
立即学习“PHP免费学习笔记(深入)”;
return [
\think\middleware\SessionInit::class, // 必须先初始化 Session/Cookie
\think\middleware\Lang::class, // 此时才能可靠读取 think_lang
\think\middleware\LoadLangPack::class, // (可选)按需加载语言包
// 后续是路由、控制器、日志等
];⚠️ 错误做法:
把 Lang::class 放在 SessionInit::class 前面 → Cookie 读不到,语言始终为默认值。
二、避免被其他中间件干扰语言上下文
某些中间件(如 AuthMiddleware、ParseJsonBody)会提前触发控制器逻辑或修改请求体,若 Lang 中间件排在其后,可能导致:
- 模板中
lang('submit')已按旧语言渲染完毕 - 验证失败提示语用的是默认语言,而非用户选择的语言
✅ 建议紧随 SessionInit 后立即执行,不插入无关中间件。
三、插件场景需单独注册专属 LangSwitch 中间件
主应用的 Lang::class 只加载 app/lang/ 下的语言包,不会自动识别插件目录下的 lang/zh-cn/common.php。
插件要独立多语言,必须:
- 在插件内建
middleware/LangSwitch.php -
handle()开头就读插件专属 Cookie(如plugin_wechat_lang) - 立即调用
Lang::set($lang) - 并确保该中间件在插件控制器执行前运行(注册到插件自己的
config.php的'middleware'数组中)
注意:这个插件中间件的顺序,由插件配置控制,与主应用
app/middleware.php无关。
四、验证是否生效的三个检查点
-
think_langCookie 是否存在且值合法(如zh-cn、en-us,全小写+短横线) - 对应语言包路径是否存在且命名规范:
app/lang/zh-cn/common.php(不能是ZH-CN或zh_CN) -
Lang::get('hello')在控制器中输出是否符合预期,而不是回退到默认语言
不复杂但容易忽略。



















