thinkphp语言包路径固定为app_path.'lang/',必须按zh-cn/en-us等小写短横线格式建子目录并放common.php等php数组文件,否则lang::get()返回空或失效。

ThinkPHP 语言包路径不是靠配置项自由指定的,而是由框架硬编码约定的,改错位置或漏加后缀会导致 Lang::get() 返回空、think:lang 命令报错、多语言切换失效。
语言包目录必须放在 APP_PATH . 'lang/' 下
ThinkPHP(5.x 及以上)只认这个固定路径结构:语言文件必须放在 application/lang/ 目录下(即 APP_PATH . 'lang/'),不能挪到 public/、config/ 或自定义路径。框架内部通过 Lang::load() 自动扫描该目录下的子目录(如 zh-cn/、en-us/),每个子目录里放对应语言的 PHP 数组文件,例如:
application/
└── lang/
├── zh-cn/
│ └── common.php
└── en-us/
└── common.php
常见错误现象:
- 把语言包放到
application/common/lang/—— 框架根本不会扫描 - 用
define('LANG_PATH', ...)手动覆盖 —— 无效,框架不读这个常量 - 目录名写成
zh_CN或zhcn—— 必须是小写+短横线格式,否则Lang::detect()匹配失败
common.php 是默认加载文件,其他文件需显式调用
框架启动时自动加载 lang/{lang}/common.php,但像 user.php、admin.php 这类文件不会自动载入。必须在控制器或模型中手动执行:
Lang::load(APP_PATH . 'lang/zh-cn/user.php');
注意点:
- 路径必须用
APP_PATH拼接,不能用__DIR__或相对路径,否则 CLI 环境下会出错 - 文件名必须是
.php后缀,不能是.inc或无后缀 - 文件内必须返回关联数组,不能有 echo/print、不能 exit,否则
Lang::get()会中断 - 数组键名不要含空格或特殊符号,否则模板中
{:lang('user.name')}解析失败
多语言切换依赖 think\lang 中间件和 lang 参数传递
单纯放好文件还不够,语言切换需要两步配合:
- 确保
app/middleware.php中启用了think\middleware\Lang中间件(TP6 默认开启,TP5 需手动添加) - 语言标识必须通过 URL 参数(
?lang=zh-cn)、Cookie(think_lang)、Header(Accept-Language)或 Session 传入,不能仅靠修改配置 -
Lang::set('en-us')只对当前请求生效,不能写在配置文件里“永久设置”
容易被忽略的是:如果项目用了路由分组或子域名部署,Lang 中间件必须在路由解析之后运行,否则 lang 参数可能拿不到。
CLI 环境下语言包加载行为与 Web 不同
执行 php think hello 或队列任务时,Lang::get() 默认不加载任何语言包,除非显式调用 Lang::load() 或设置 Lang::set()。这是因为 CLI 没有 $_GET、$_COOKIE,中间件链也不触发。
实操建议:
- 在命令类的
handle()开头加Lang::set('zh-cn'); - 避免在
config/lang.php里写死语言,它只控制默认值,不替代实际加载逻辑 - 调试时用
dump(Lang::range());查看当前已加载的语言键值范围,比dump(Lang::get('xxx'))更能定位是否加载成功
最易踩的坑是:开发时在浏览器里切语言正常,一跑定时任务就全变成英文或空字符串——本质是 CLI 下语言上下文没初始化,而不是路径写错了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











