Lang::get() 返回空主因是语言包未加载,常见于缓存未清除、OPcache未刷新、键名重复覆盖或加载顺序不当,需逐层排查缓存、中间件顺序及键名规范。

Lang::get() 返回空,八成不是键名写错,而是语言包根本没加载进来——尤其在开启缓存后,改了语言文件却没清 runtime/lang/,旧缓存还在撑场面。
为什么 lang/zh-cn.php 改了但页面不更新
ThinkPHP V6.0+ 默认把解析后的语言包缓存到 runtime/lang/zh-cn.php(不是源文件),下次请求直接读缓存,跳过原始文件。改完 lang/zh-cn.php 不清缓存,等于白改。
- 清缓存命令:
php think clear:lang(推荐)或手动删runtime/lang/目录 - 开发期可临时关掉语言缓存:在
config/lang.php加'cache_time' => 0 - 注意 OPcache:如果启用了 PHP 的 OPcache,
lang/zh-cn.php文件本身也可能被缓存,需重启 PHP-FPM 或调用opcache_invalidate()
语言键名重复导致覆盖或丢失
多个语言包里定义了相同键名(比如 user.name),ThinkPHP 按加载顺序合并,后加载的会覆盖先加载的。这不是 bug,是设计行为——但容易误以为“翻译没生效”。
- 用
Lang::range()查看当前已加载的全部键值,确认有没有被意外覆盖 - 避免在不同模块语言包中重复定义同一键;统一收口到
lang/common.php,其他模块只定义特有文案 - 如果必须分包加载,控制
extend_list数组顺序,把基础包放前面、业务包放后面
数据库字段多语言 vs 语言包键名冲突
别把 title_zh 这类数据库字段名,当成语言包键名去调 Lang::get('title_zh')——这是两类事:前者是数据层字段,后者是静态文案标识。
立即学习“PHP免费学习笔记(深入)”;
- 语言包键名建议全小写 + 下划线,如
article.title、form.submit_button,和数据库字段命名逻辑区分开 - 模型里用 accessor 处理多语言字段时,不要返回
Lang::get(),而应直接取值:return $this->getData('title_' . Lang::getLangSet()); - 若用 JSON 字段存多语言内容,键名也建议用标准语言码:
{"zh-cn": "标题", "en-us": "Title"},别用zh或cn这种模糊缩写
切换语言后部分页面仍显示默认语言
常见于使用路由分组(如 lang/:lang)但没透传参数,或中间件执行顺序不对——LoadLangPack 必须在 session/cookie 中间件之后运行,否则读不到用户偏好。
- 检查中间件注册顺序:
app/middleware.php中\think\middleware\SessionInit::class和\think\middleware\LoadLangPack::class要前后连贯 - 路由分组里拿到
:lang后,必须显式调用Lang::setLocale($lang),不能只存 session - Cookie 方式下,确认
cookie_var配置和实际写入一致,比如配置了'cookie_var' => 'think_lang',就不能用Cookie::set('lang', 'en-us')
真正难调的不是语法,是加载时机和缓存层级——Lang 类初始化、中间件顺序、OPcache、runtime 缓存,四层叠在一起,漏查一层就卡住。



















