thinkphp 6+ 多语言必须配置在 config/app.php 中,config/lang.php 不被框架加载;需设置 lang_switch_on、default_lang、lang_list 等项,并将语言包置于 app/lang/zh-cn/ 下且命名 common.php。

ThinkPHP 多语言不能靠“放个配置文件就自动生效”,config/lang.php 在 TP6+ 中**根本不是标准配置入口**,强行创建它不会被框架加载,也不会起作用。
为什么 config/lang.php 不生效?
ThinkPHP 6 及以后版本中,多语言核心配置项(如 lang_switch_on、default_lang)必须写在 config/app.php 里。框架启动时只读取 app.php 中的这些键,config/lang.php 是用户自定义配置文件,框架不识别、不解析、不合并——它会被完全忽略。
- 常见错误现象:
config/lang.php里写了'lang_switch_on' => true,但lang('hello')仍返回键名、不翻译 - 真实加载路径:框架只从
config/app.php读取语言开关和默认语言,其他语言相关行为(如检测变量名、支持列表)也都在这里配 - 历史混淆来源:TP3.2 曾用
tags.php+CheckLangBehavior,TP5 早期有config.php全局数组,但 TP6 统一收口到app.php
正确开启方式:只改 config/app.php
打开 config/app.php,确保包含以下几项(缺一不可):
-
'lang_switch_on' => true:这是总开关,不设为true,整个多语言机制不启动 -
'default_lang' => 'zh-cn':必须是小写连字符格式,不能是zh_CN或zh -
'lang_list' => ['zh-cn', 'en-us']:显式声明允许的语言白名单,未列在此处的 locale 会被拒绝 -
'lang_detect_var' => 'lang'(可选):指定 URL 中用于切换的语言参数名,默认就是lang,即支持?lang=en-us
示例片段:
return [
'lang_switch_on' => true,
'default_lang' => 'zh-cn',
'lang_list' => ['zh-cn', 'en-us', 'ja-jp'],
'lang_detect_var'=> 'lang',
];
语言包路径和命名必须严格匹配
配置开对了,语言包放错位置或命名不规范,照样不翻译。框架只认固定路径和格式:
- 语言包根目录必须是
app/lang/(TP6 默认),不是config/lang/、也不是lang/根目录 - 子目录名必须是小写连字符格式:如
app/lang/zh-cn/、app/lang/en-us/,zh_CN或ZH-CN均无效 - 语言文件必须叫
common.php(默认分组)或你代码中指定的分组名,如user.php;不能叫zh-cn.php或lang.php -
common.php必须返回纯数组:return ['hello' => '你好'];,不能加任何输出、BOM、注释或包裹结构
Lang::setLang() 必须在请求最开始执行
即使配置全对、路径全对,如果在控制器里才调 Lang::setLang('en-us'),那之前已执行的 lang('hello') 还是按默认语言渲染——因为语言环境是请求级的,且不可回滚。
- 正确做法:写一个中间件(如
app/middleware/Lang.php),在handle()开头就读取 session 或 input,然后立即调\think\Lang::setLang($lang) - 必须注册:把该中间件加入
app/middleware.php的全局中间件数组,或绑定到对应路由组 - 别依赖自动检测:
Lang::detect()默认只看Accept-Language头,不读 session,也不解析$_GET['lang'],得自己手动取值并校验白名单
容易被忽略的一点:Lang::setLang() 不会重载已加载的语言包,所以它必须在任何 lang() 调用前执行,晚了就来不及了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











