Lang::getLangSet()是唯一可信的语言标识获取方式,返回如'zh-cn'等最终生效值,综合URL参数、Cookie、Header等判断,需确保allow_lang_list配置正确且未被路由或伪静态丢失参数。

Language参数不是靠get()手动拿的
直接用request()->get('lang')或input('lang')取不到实际生效的语言标识——框架的语言检测是独立流程,不依赖你“读哪个变量”。它在请求生命周期极早期就运行,结果存在内部状态里,后续所有语言相关操作(比如模板翻译、验证器提示)都基于这个状态。硬去读$_GET['lang']可能拿到值,但那只是原始输入,未必被采纳。
Lang::getLangSet()才是唯一可信来源
必须用门面类Lang获取最终确定的语言标识:
use think\facade\Lang; $lang = Lang::getLangSet(); // 返回类似 'zh-cn' 或 'en-us'
这个值是综合判断的结果:可能来自 URL 参数、Cookie、Session、Accept-Language 请求头,甚至中间件里手动设置过。只要没被覆盖,它就是当前整个请求上下文里真正起效的语言。
- 如果返回空字符串,先检查
config/lang.php里的allow_lang_list是否包含你传的值(大小写、连字符必须完全一致) - 如果返回和 URL 里
?lang=ja-jp不一致,说明该参数被路由规则吃掉了,或者中间件提前终止了语言初始化流程 - 别在构造函数或静态方法里调用它——此时语言检测还没执行,一定为空
伪静态下lang参数容易丢失
像/zh-cn/article/123这种路径,Nginx/Apache 重写时若没把 query string 显式带上,lang参数就没了。典型错误配置:
立即学习“PHP免费学习笔记(深入)”;
rewrite ^/([a-z]{2}-[a-z]{2})/(.*)$ /index.php?s=/$2 last; // ❌ 丢掉了 $query_string
正确写法要保留$query_string:
try_files $uri $uri/ /index.php?$query_string; // ✅
或者改用路由变量方式传递语言,比如定义Route::rule(':lang/article/:id', 'article/read');,再在控制器里用$this->request->param('lang')手动设置:Lang::setLocale($lang)。
lang_detect_var配置决定参数名
框架默认只认?lang=xx,但这个行为由config/lang.php中的lang_detect_var控制:
- 设为
'lang'→ 只响应?lang=fr-fr - 设为
'l'→ 必须用?l=fr-fr - 该配置不区分大小写,但值必须在
allow_lang_list中才被接受
改完配置后记得清缓存,否则旧配置仍生效。真正容易被忽略的是:语言检测只跑一次,且不可逆;一旦Lang::setLocale()被调用,后续Lang::getLangSet()就返回这个值,和原始 URL 无关。



















