ThinkPHP 多语言功能原生内置,无需额外插件;核心是 Lang 类和 lang() 函数,需严格遵循路径(如 lang/zh-cn/common.php)、大小写规范及执行时机(中间件中提前调用 Lang::setLang)。
ThinkPHP 官方
多语言
支持是内置的,不需要额外“集成扩展包”——所谓“多语言插件”基本是误解或旧版第三方行为;直接用框架原生
类和
函数即可实现完整功能,加包反而容易冲突。
lang() 和 Lang::setLang() 是核心,不是可选插件
ThinkPHP 5/6 的多语言能力由
类提供,
是全局助手函数,底层调用它。你不需要 composer require 任何“多语言插件”,也不该在
里硬编码翻译项(那是配置文件,不是语言包)。
在控制器、模型、中间件里都能直接用,返回对应语言的字符串
必须在请求最开始调用,比如中间件里;晚于第一次
调用就无效
不支持自动重载:切换语言后,已加载的语言包不会刷新,所以必须在路由分发前完成设置
语言包路径和命名必须严格符合约定
框架只认
这种结构,大小写、目录名、文件名错一个就静默失效——线上环境尤其难排查。
语言目录名必须全小写,
≠
,Linux 服务器上
直接被忽略
语言包文件必须返回数组,不能是 JSON/YAML,也不能用
或其他输出
常见错误:把
放到
下,或命名为
—— 框架根本不会扫描
模块级语言包优先级高于应用级:例如
会覆盖
动态切换语言必须靠中间件,不能依赖 Cookie 自动识别
默认只看
和
,不读 Session;想按用户偏好切换,得自己写中间件读取并提前设置。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
在
中写:
切忌在控制器构造函数里调用
:中间件执行时机更早,此时语言已锁定
URL 切换如
能生效,前提是
且
包含该值
缺失 key 时
默认返回
字符串,不是报错,容易误判——开启调试模式才记日志
lang() 占位符和复数语法有硬性限制
它不兼容 gettext 风格,只支持极简语法,写错格式就当普通字符串处理。
立即学习
“
PHP免费学习笔记(深入)
”;
占位符只认
格式,
、
、
全部无效
复数用竖线分隔:
,传入数字 1 取左边,其它值取右边;不支持区间或复杂规则
数组参数必须是关联数组:
,索引数组会被忽略
语言包中键名必须完全一致,
,大小写敏感
真正麻烦的不是配置,而是路径大小写、执行顺序、key 名一致性这三处——本地 Windows 开发没问题,一上 Linux 就挂;中间件漏写一行,整个请求还是默认语言;语言包里多一个空格,
就回退成原始 key。这些点不盯死,再多“插件”也白搭。
Langlang()think\Langlang()config/lang.phplang('welcome')Lang::setLang('en-us')lang()lang/zh-cn/common.phpzh-CNzh-cnzh_CNechocommon.phpconfig/lang/zh-cn.phpapp\home\lang\zh-cn\common.phpapp\lang\zh-cn\common.phpLang::detect()$_GET['lang']Accept-Languageapp\common\middleware\Lang.php$lang = $request->session('lang', 'zh-cn'); Lang::setLang($lang);Lang::setLang()?lang=en-us'lang_switch_on' => true'lang_list'lang('missing')'missing'{name}:name%s{0}'item|items'lang('hello', ['name' => 'Tom'])'Hello' !== 'hello'lang()