ThinkPHP语言包扩展不依赖“extend_list”配置项,该键名在官方源码和文档中不存在;语言包加载由lang/目录结构和命名约定决定,需手动调用Lang::load()加载多分组,且文件格式必须严格规范。

ThinkPHP 语言包扩展不是靠“extend_list”配置项实现的,这个键名根本不存在于框架任何版本的文档或源码中——你看到的很可能是拼写错误、过时资料,或者把其他框架(如 Laravel 的 trans 扩展机制)混淆进来了。
lang/ 目录结构决定语言包加载范围
ThinkPHP(6.x 及主流 5.x 版本)通过目录层级和命名约定识别语言包,不依赖额外的“扩展列表”配置:
- 语言包必须放在
lang/目录下,子目录名即语言代码,如lang/zh-cn/、lang/en-us/ - 每个子目录内默认加载
common.php;若需分组,可另建user.php、admin.php等,调用时显式传入分组名:lang('login', [], 'user') - 模块化项目中,优先加载
app/module/lang/zh-cn/common.php,再 fallback 到应用级app/lang/zh-cn/common.php - 路径名严格区分大小写:
zh-CN≠zh-cn,Linux 服务器上放错就完全不生效,且无报错提示
lang() 函数支持多分组但不支持“自动 extend”
lang() 本身不扫描或合并多个文件,它只从当前已加载的语言包数组中取值。所谓“扩展”,实际是手动加载多个分组:
- 先调用
Lang::load('user', 'zh-cn')加载lang/zh-cn/user.php - 再调用
Lang::load('admin', 'zh-cn')加载lang/zh-cn/admin.php - 之后
lang('login')会按顺序在已加载的分组中查找,找到第一个匹配 key 即返回 - 注意:重复 key 会被后加载的覆盖,不是合并;且
Lang::load()必须在首次lang()调用前执行,否则无效
别信“LANG_EXTEND_LIST”这类伪配置
翻遍 ThinkPHP 6.3 官方源码(think\facade\Lang、think\Lang 类)和全部 config 文件模板,没有 lang_extend_list、extend_list 或类似字段。常见误传来源:
立即学习“PHP免费学习笔记(深入)”;
- 把
lang_list(允许切换的语言白名单)错记为扩展配置 - 把第三方插件(如某些未维护的 GitHub 包)的自定义配置当成框架原生功能
- 混淆了
config/app.php中的'lang_switch_on' => true和实际加载逻辑
真正影响语言包可用性的只有三件事:目录结构是否合规、Lang::setLang() 是否提前调用、分组是否显式 load() —— 其他任何“扩展配置”都是干扰项。
最易被忽略的点:语言包文件必须以 return [...] 结尾,不能有输出(包括 BOM、空行、echo)、不能用 include 嵌套加载、不能依赖未声明的变量。一个空格就能让整个语言包静默失效。



















