跨域请求时语言标识丢失的根本原因是options预检未透传语言信息,需在cors中间件中为options响应添加access-control-allow-headers: think-lang、cookie,并确保loadlangpack中间件在cors之后执行。

多语言切换请求被跨域拦截后语言标识丢失
跨域请求(尤其是带 Cookie 或 Authorization 的 POST)触发浏览器预检(OPTIONS),而 ThinkPHP 默认不响应 OPTIONS 请求中的语言侦测逻辑,导致 lang 参数、think_lang Cookie 或 think-lang Header 全部失效,后续实际请求就 fallback 到 default_lang。
- 浏览器发带凭证的跨域请求时,先发 OPTIONS,此时
LoadLangPack中间件根本没执行——因为中间件栈在 OPTIONS 响应前就被终止了 -
detect_var => 'lang'在 GET 参数里的?lang=en-us对 OPTIONS 无效,且 OPTIONS 请求不携带 Cookie/Headers(除非显式配置Access-Control-Allow-Headers) - 即使你手动在控制器里调用
Lang::set('en-us'),也只对当前请求生效;OPTIONS 响应完后,真正的 POST 请求是全新上下文,语言包又得重加载
必须让 OPTIONS 响应携带语言协商头
不能只返回空 204,要让预检阶段就“透传”语言意图,否则业务请求进来时框架已错过语言侦测时机。
- 在自定义 CORS 中间件(如
app/middleware/Cors.php)的handle()方法中,对OPTIONS请求也设置关键响应头:Access-Control-Allow-Headers必须包含think-lang和Cookie(若启用了凭据) - 确保
config/lang.php中'use_cookie' => true且'cookie_var' => 'think_lang'已配置,否则 Cookie 语言无法被识别 - 如果前端通过 URL 传参(如
?lang=ja-jp),需在 OPTIONS 响应中加Access-Control-Allow-Headers: Origin(部分浏览器要求),并确认 Nginx/Apache 未过滤Origin头
跨域中间件与语言中间件的执行顺序冲突
LoadLangPack 必须在 CORS 中间件之后执行,但又要早于业务逻辑——这个顺序错一位,语言就永远加载不上。
- 打开
app/middleware.php,中间件数组顺序应为:\think\middleware\Cors::class→\think\middleware\LoadLangPack::class→ 其他(如SessionInit、AuthMiddleware) - 不能把
LoadLangPack放在Cors前面,否则Cors返回的响应体可能覆盖掉语言包已注入的 header - 若使用自定义
Cors类(非官方内置),务必在$response = $next($request)后再调用$response->header(),否则语言中间件写入的Content-Language等头会被冲掉
JSON 接口返回时语言键名未翻译
调用 return json(['msg' => lang('login_success')]) 时,lang() 返回的是键名(如 login_success)而非翻译文本,说明语言包压根没加载或加载时机太晚。
- 检查
lang()调用是否发生在LoadLangPack执行之后——它只在中间件链中运行一次,控制器里直接用是安全的;但若你在response()->json()封装前手动 new Response 对象,语言上下文会丢失 - 避免在 JSON 返回前用
echo、var_dump或任何输出,这会提前发送响应头,导致LoadLangPack的 header 设置失效 - 若接口返回
application/json,确认没漏掉\think\Response::mimeType('application/json', 'utf-8')这一步,否则框架可能用默认 MIME 覆盖语言包的字符集声明
最易被忽略的是:跨域场景下,语言切换依赖的三个通道(GET、Cookie、Header)中,只有 Header 是预检阶段可稳定传递的;所以前端必须用 think-lang: en-us 请求头,而后端 Cors 中间件必须显式放行它——少一个字符大小写不一致,整个链路就断了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











