thinkphp多语言配置须放lang/目录下,按小写语言码(如zh-cn)建子目录,内含common.php等返回数组的php文件;动态切换需在中间件中用lang::setlang()提前设置,lang()函数支持{name}占位符和item|items复数语法。

多语言配置文件放哪、叫什么名
ThinkPHP 的多语言配置必须放在 lang/ 目录下,按语言代码命名子目录,比如 zh-cn、en-us;每个子目录里放 PHP 返回数组的文件,固定叫 common.php(或你指定的分组名,如 user.php),不能是 JSON 或 YAML。
常见错误:把语言包放在 config/lang.php 里,或者用 zh_CN.php 这种大写命名——ThinkPHP 会直接忽略,不报错但也不生效。
-
lang/zh-cn/common.php必须返回return ['hello' => '你好']; - 语言目录名区分大小写,
zh-CN≠zh-cn,Linux 服务器上尤其容易踩坑 - 如果用模块化项目,语言包路径优先级是:模块
lang/→ 应用lang/→ 框架默认
如何动态切换语言而不重启请求
ThinkPHP 不靠 Cookie 或 Session 自动识别语言,得手动设。核心是调用 Lang::setLang() 或在请求开始时用 Lang::detect() 主动探测。
典型场景:用户在个人设置里选了“English”,你得把选择存到 Session,然后在 app\common\middleware\Lang.php 中间件里读取并设置:
public function handle($request, \Closure $next)
{
$lang = $request->session('lang', 'zh-cn');
\think\Lang::setLang($lang);
return $next($request);
}
注意:Lang::setLang() 必须在任何语言翻译调用前执行,比如 lang('hello') 之前;否则该次请求还是用默认语言。
- 不要在控制器构造函数里调用
Lang::setLang(),因为中间件执行更早 -
Lang::detect()默认只看 URL 参数lang=和浏览器Accept-Language,不读 Session,得自己扩展 - 切换后不会自动重载语言包,已加载的翻译项不会刷新,所以务必在请求最开始就设好
lang() 函数怎么传参、支持哪些语法
lang() 是核心翻译函数,不是模板标签,它在控制器、模型、中间件里都能用。支持占位符和复数,但语法很精简,不兼容 gettext 那套。
示例:lang('welcome_to_site', ['name' => 'Tom']) 对应语言包里 'welcome_to_site' => '欢迎来到 {name} 的站点';复数用竖线分隔:'item|items',传入数字 1 就取左边,其他取右边。
- 占位符只认
{key}格式,不支持:key或%s - 如果 key 不存在,
lang()默认返回原 key 字符串(如lang('missing')返回'missing'),不是空或异常,容易误以为生效了 - 开启调试模式时,缺失 key 会在日志里记录,但线上默认静默,建议上线前跑一遍语言包完整性检查
多语言 + 路由绑定时 URL 怎么带语言标识
ThinkPHP 路由本身不感知语言,要实现 /zh-cn/user/login 这种路径,得靠路由变量 + 中间件配合,不能只靠 lang 参数。
在 route/route.php 里定义带语言前缀的路由组:
Route::group(['prefix' => '<lang>'], function () {
Route::rule('user/login', 'user/login');
})->ext('html');</lang>
然后中间件里从 $request->param('lang') 提取值,校验是否在白名单(如 ['zh-cn','en-us']),再调用 Lang::setLang()。关键点:这个 lang 变量必须参与路由匹配,否则无法反解析 URL。
- 别在路由规则里写死
zh-cn,否则生成 URL 时url('user/login')会丢掉语言前缀 -
url()函数默认不携带当前语言参数,需手动传:url('user/login', ['lang' => app('lang')->getLangSet()]) - 如果用了多应用模式,语言前缀可能和应用名冲突,建议统一用二级域名(如
en.example.com)更稳妥
语言切换本质是请求上下文的初始化时机问题,不是配几个文件就能跑通;最容易漏的是中间件执行顺序和 lang() 调用时机,这两处一错,整条链路就静默失效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










