如何设置ThinkPHP语言中间件实现自动加载多语言?

2026-05-08 02:473阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1010个文字,预计阅读时间需要5分钟。

如何设置ThinkPHP语言中间件实现自动加载多语言?

在Lang中,中间件不会自动生效,必须手动注册到全局中间件列表中。否则,语言包根目录不会加载,也不会返回原始键名。

Lang中间件必须显式注册到 app/middleware.php

ThinkPHP 不会默认启用多语言中间件,哪怕你把语言包放对了位置、配置也写全了,只要没注册,整个流程就卡在第一步。

常见错误现象:lang('hello') 始终返回 'hello',日志无报错,调试时 Lang::range() 返回空数组。

  • 打开 app/middleware.php,确认数组中包含 \think\middleware\Lang::class(不是注释状态)
  • 多应用模式下,需在对应应用目录下的 middleware.php 单独注册,不能只改根目录
  • 别和 \think\middleware\LoadLangPack 混用——V6.0+ 已弃用该类,Lang 中间件已内置自动加载逻辑

语言包路径和命名必须严格符合 lang/{lang}/common.php 格式

ThinkPHP 只按固定路径规则加载语言包:小写字母 + 连字符格式的 locale 目录名,内含返回数组的 PHP 文件。任何偏差都会静默失败。

立即学习“PHP免费学习笔记(深入)”;

常见错误现象:Language file not exists 报错,或切换语言后翻译不更新。

  • 路径必须是 app/lang/zh-cn/common.php,不是 app/lang/zh_CN.php、也不是 config/lang.php
  • zh-cnZH-CN 在 Linux 服务器上完全不等价,大小写错误会导致文件找不到
  • common.php 必须以 return ['hello' => '你好']; 结尾,不能是 JSON、YAML 或嵌套结构如 return ['zh-cn' => [...]]

动态切换语言必须在中间件中调用 Lang::setLocale(),且早于任何 lang() 调用

URL 参数 ?lang=en-us 或 Cookie 并不会自动触发语言切换,Lang 中间件默认只读取 Accept-Language 头或配置项,不解析 GET 参数。

常见错误现象:用户点了“English”按钮,但页面文字没变;或者控制器里 Lang::setLocale('en-us') 没效果。

  • 在自定义中间件(如 app/middleware/LangSwitch.php)中读取输入:$lang = input('lang', cookie('think_lang', 'zh-cn'))
  • 务必校验白名单:in_array($lang, config('lang.allow_lang_list', ['zh-cn', 'en-us'])),防止非法值引发路径问题
  • 调用 Lang::setLocale($lang) 后,建议显式 Lang::load() 确保语言包重载(尤其手动设 locale 时)
  • 切勿在控制器构造函数中调用——中间件执行时机更早,此时 Lang 上下文尚未建立

Lang::get() 返回原键名?先查 Lang::range(),再看中间件执行顺序

返回键名不是配置错了,而是语言包压根没加载成功,或者 lang() 被调用时当前语言上下文还没就位。

最容易被忽略的是中间件顺序:如果 Lang 中间件排在 SessionInit 之后,它就读不到 cookie('think_lang');如果排在路由调度之后,控制器里第一行 lang() 就已执行完毕。

  • Lang::range() 直接查看当前已加载的全部翻译项,比翻日志更快定位是否加载
  • 确保 Lang 中间件在 SessionInit 之后、但仍在路由匹配之前执行(即注册顺序应靠前)
  • 若用了模块化结构,检查模块级语言包路径:app/module_name/lang/zh-cn/common.php 优先级高于应用级

本文共计1010个文字,预计阅读时间需要5分钟。

如何设置ThinkPHP语言中间件实现自动加载多语言?

在Lang中,中间件不会自动生效,必须手动注册到全局中间件列表中。否则,语言包根目录不会加载,也不会返回原始键名。

Lang中间件必须显式注册到 app/middleware.php

ThinkPHP 不会默认启用多语言中间件,哪怕你把语言包放对了位置、配置也写全了,只要没注册,整个流程就卡在第一步。

常见错误现象:lang('hello') 始终返回 'hello',日志无报错,调试时 Lang::range() 返回空数组。

  • 打开 app/middleware.php,确认数组中包含 \think\middleware\Lang::class(不是注释状态)
  • 多应用模式下,需在对应应用目录下的 middleware.php 单独注册,不能只改根目录
  • 别和 \think\middleware\LoadLangPack 混用——V6.0+ 已弃用该类,Lang 中间件已内置自动加载逻辑

语言包路径和命名必须严格符合 lang/{lang}/common.php 格式

ThinkPHP 只按固定路径规则加载语言包:小写字母 + 连字符格式的 locale 目录名,内含返回数组的 PHP 文件。任何偏差都会静默失败。

立即学习“PHP免费学习笔记(深入)”;

常见错误现象:Language file not exists 报错,或切换语言后翻译不更新。

  • 路径必须是 app/lang/zh-cn/common.php,不是 app/lang/zh_CN.php、也不是 config/lang.php
  • zh-cnZH-CN 在 Linux 服务器上完全不等价,大小写错误会导致文件找不到
  • common.php 必须以 return ['hello' => '你好']; 结尾,不能是 JSON、YAML 或嵌套结构如 return ['zh-cn' => [...]]

动态切换语言必须在中间件中调用 Lang::setLocale(),且早于任何 lang() 调用

URL 参数 ?lang=en-us 或 Cookie 并不会自动触发语言切换,Lang 中间件默认只读取 Accept-Language 头或配置项,不解析 GET 参数。

常见错误现象:用户点了“English”按钮,但页面文字没变;或者控制器里 Lang::setLocale('en-us') 没效果。

  • 在自定义中间件(如 app/middleware/LangSwitch.php)中读取输入:$lang = input('lang', cookie('think_lang', 'zh-cn'))
  • 务必校验白名单:in_array($lang, config('lang.allow_lang_list', ['zh-cn', 'en-us'])),防止非法值引发路径问题
  • 调用 Lang::setLocale($lang) 后,建议显式 Lang::load() 确保语言包重载(尤其手动设 locale 时)
  • 切勿在控制器构造函数中调用——中间件执行时机更早,此时 Lang 上下文尚未建立

Lang::get() 返回原键名?先查 Lang::range(),再看中间件执行顺序

返回键名不是配置错了,而是语言包压根没加载成功,或者 lang() 被调用时当前语言上下文还没就位。

最容易被忽略的是中间件顺序:如果 Lang 中间件排在 SessionInit 之后,它就读不到 cookie('think_lang');如果排在路由调度之后,控制器里第一行 lang() 就已执行完毕。

  • Lang::range() 直接查看当前已加载的全部翻译项,比翻日志更快定位是否加载
  • 确保 Lang 中间件在 SessionInit 之后、但仍在路由匹配之前执行(即注册顺序应靠前)
  • 若用了模块化结构,检查模块级语言包路径:app/module_name/lang/zh-cn/common.php 优先级高于应用级