ThinkPHP6多语言失效主因是Nginx未正确传递PATH_INFO或拦截请求,导致LoadLangPack中间件未执行;需检查fastcgi_param配置、try_files参数、中间件注册及语言包路径命名规范。

ThinkPHP6 多语言切换在 Nginx 环境下失效,90% 的情况不是语言包写错了,而是请求根本没进到 LoadLangPack 中间件——PATH_INFO 为空、try_files 没传参、或 Nginx 抢先返回了 404/502,导致语言侦测逻辑压根没执行。
确认 PATH_INFO 是否被正确传递
TP6 的 LoadLangPack 依赖 $_SERVER['PATH_INFO'] 或 $_GET['s'] 解析当前路由,进而判断是否需要加载语言包。Nginx 默认不提取 PATH_INFO,若该值为空,语言包路径生成失败,lang() 调用直接回退到键名字符串。
- 在
public/index.php顶部加一行:var_dump($_SERVER['PATH_INFO'] ?? 'MISSING', $_GET['s'] ?? 'NO s'); die; - 访问
/index/index,输出应为string(12) "/index/index";若为空或NO s,说明 Nginx 没传参 - 检查 Nginx 配置中
location ~ \.php$块是否含fastcgi_param PATH_INFO $fastcgi_path_info;,且前面有匹配的fastcgi_split_path_info正则(如fastcgi_split_path_info ^(.+\.php)(/.+)$;) - 更推荐放弃
PATH_INFO模式:改用try_files $uri $uri/ /index.php?$query_string;,让 TP6 从QUERY_STRING解析,避免正则捕获失效
验证 LoadLangPack 中间件是否真正启用
中间件未注册或顺序错位,会导致语言包完全不加载——即使配置和路径都对,lang('welcome') 也只会原样输出 welcome。
- 打开
app/middleware.php,确认数组中存在'think\middleware\LoadLangPack',且不在注释内 - 检查该中间件是否被其他中间件提前终止(如某自定义中间件
return response(...)后没调用$next($request)) - 多应用模式下,中间件配置在
app/应用名/middleware.php,不是根目录的app/middleware.php - 临时在
think\middleware\LoadLangPack::handle()方法第一行加file_put_contents('/tmp/lang.log', "hit\n", FILE_APPEND);,访问后检查文件是否有内容
检查 Nginx 是否拦截或覆盖了语言参数
语言切换常通过 ?lang=zh-cn 或 Header think-lang: en-us 触发,但 Nginx 可能因缓存、重写或安全规则丢弃这些参数。
立即学习“PHP免费学习笔记(深入)”;
- 确认
try_filesfallback 行末尾带$query_string(如/index.php?$query_string),否则?lang=会被清空 - 检查是否有
if ($args ~* "lang=") { return 403; }类拦截规则——这是某些“安全加固脚本”误加的 - 禁用所有
error_page 404或error_page 500指令,它们会让 Nginx 在框架报错前直接返回静态页,跳过Lang::setLang()执行 - 用
curl -H "think-lang: zh-cn" https://yoursite.com/index/index测试 Header 方式,排除 GET 参数被重写干扰
语言包路径与命名必须严格小写短横线
TP6 的语言包自动加载器对路径和文件名大小写敏感,且只认 zh-cn.php 格式。任何偏差都会静默失败,无错误提示。
- 路径必须是
app/lang/zh-cn.php(单应用)或app/api/lang/en-us.php(多应用),不能是app/lang/zh_CN.php或lang/zh-cn/目录 - 文件内容必须以
return [ 'welcome' => '欢迎' ];开头,开头不能有 BOM、空格、<?php以外的字符 - 执行
php think route:list后看是否报Language file not found: zh-cn,若有,说明路径解析已触发但文件不存在 - 删除
runtime/lang/缓存目录,TP6 会重新扫描语言包——旧缓存可能锁定了错误路径
最易被忽略的是:LoadLangPack 只在路由匹配成功后才运行,如果伪静态规则导致请求连 index.php 都没进,或者 Nginx 返回了 502,那语言逻辑就彻底没机会执行。先确保 try_files 和 PATH_INFO 正确,再查中间件和路径,顺序错了排查效率直接归零。



















