lang()传参后仍显示原key,主因是Lang组件未激活:未启用LoadLangPack中间件、Lang::setLang('zh-cn')未在首次lang()调用前执行、语言码格式错误(如zh_CN)、语言包路径不匹配(应为app/lang/zh-cn.php而非common.php)、占位符非{name}格式或传参非关联数组。

lang() 传参后仍显示原 key,不是语法写错而是环境没设好
lang('welcome', ['name' => 'Tom']) 返回 'welcome' 而非 '欢迎 Tom',大概率不是函数调用问题,而是 Lang 组件根本没进入工作状态。TP6+ 的 lang() 不自动探测语言,必须提前执行 Lang::setLang('zh-cn'),且该调用必须在任何 lang() 之前完成。
常见失效路径:
- 中间件未启用
think\middleware\LoadLangPack,语言包压根没加载 -
Lang::setLang()写在控制器方法里,但模板渲染或模型逻辑中已提前调用了lang() - 语言码写成
zh_CN或zh,而 TP6 只认小写短横格式(zh-cn),Linux 服务器上大小写敏感,错一个字符就静默失败 - 语言包文件放在
app/lang/zh-cn/common.php,但实际路径是app/lang/zh-cn.php—— TP6 默认加载的是zh-cn.php,不是子目录下的common.php
占位符 {name} 不生效?检查语言包返回值和传参结构
lang() 只识别 {key} 形式的大括号占位符,不支持 :name、%s 或 {0}。语言包里必须写成 'welcome' => '欢迎 {name}',且调用时必须传关联数组:lang('welcome', ['name' => 'Tom'])。
若传参是索引数组(如 ['Tom'])或字符串(如 'Tom'),占位符不会被替换,直接原样输出。
另外注意:语言包文件必须以 return [...]; 结尾,开头不能有 BOM、空格、echo 或 var_dump —— 任何前置输出都会导致解析失败,lang() 静默回退为原 key。
复数语法 item|items 总是取右边?确认传入的是整数 1
lang('item|items', 1) 输出左边,lang('item|items', 2) 或 lang('item|items', 0) 输出右边。这不是 bug,是 TP6 的明确设计:只有严格等于 1 的整数才走单数分支,其余全部归为复数。
容易踩坑的点:
- 数据库查出的
count是字符串'1',不是整数1,结果走复数分支 - 前端传参如
?num=1,input('num')默认返回字符串,需显式转整:(int)input('num') - 使用
lang('item|items', $count ?? 0)时,$count为空则传0,也走复数
多应用下 lang() 失效?每个应用要独立配语言包路径
TP6 多应用模式(如 app/admin/ 和 app/api/)下,语言包路径不是共享的。每个应用必须有自己的 lang/ 目录:app/admin/lang/zh-cn.php、app/api/lang/en-us.php。
如果只在 app/lang/ 下放了语言包,admin 应用里的 lang() 会找不到文件,直接返回 key。
验证方式:在对应应用的中间件中加一行 dump(Lang::getLangSet());,看返回值是否为你期望的语言码;再检查 Lang::loadLangPack() 是否成功加载了对应路径下的文件。
最常被忽略的一点:Lang 组件不报错也不提示加载失败——它只是安静地返回原 key 字符串。线上环境看不到 warning,调试时得靠 dump(Lang::getLangSet()) 和 dump(Lang::getLoadedList()) 主动确认状态,不能凭感觉判断“应该生效了”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











