nginx 无法精准基于客户端语言做域名重定向,仅能通过 $http_accept_language 头部粗略匹配(如 zh-cn、en-us),推荐用 cookie 或后端路由实现更可靠的语言识别。

在 Nginx 的 server 块中,无法直接“基于客户端语言”做域名重定向(比如把中文用户跳到 zh.example.com),因为 HTTP 协议本身不传递“用户语言偏好”作为强制字段,Nginx 仅能通过请求头中的 Accept-Language 字段间接获取——它是一个可选、由浏览器发送的提示性字段,且格式多变(如 zh-CN,zh;q=0.9,en-US;q=0.8),不能保证准确或存在。
提取并匹配 Accept-Language 头部
Nginx 可用内置变量 $http_accept_language 获取该头部值,再结合 if + 正则判断实现粗粒度分流。注意:if 在 server 级别可用,但需避免嵌套或复杂逻辑,且不能在 location 外使用 rewrite 指令(必须配合 return 或 rewrite ... redirect/permanent)。
- 匹配简体中文(含
zh-CN、zh-Hans、开头为zh的常见变体): if ($http_accept_language ~* "^zh|zh-CN|zh-Hans") { return 301 https://zh.example.com$request_uri; }- 匹配英文(优先匹配
en-US,再 fallback 到泛en): if ($http_accept_language ~* "^en-US|en-|^en") { return 301 https://en.example.com$request_uri; }- 默认跳转主站(兜底):
return 301 https://www.example.com$request_uri;
避免常见陷阱
Accept-Language 是客户端声明,易被伪造或缺失;Nginx 不支持解析权重(如 q=0.9),所以正则只能做前缀/子串匹配,无法真正按质量排序。更可靠的做法是:让前端 JS 检测 navigator.language 后跳转,或后端应用层根据该 header 做路由——Nginx 仅适合做简单、低精度的初始分流。
- 不要在
if中写多个rewrite,容易触发循环或冲突;统一用return 301更安全 -
$request_uri包含完整路径+查询参数,能保留原始访问上下文 - 确保目标域名已配置对应
server块并监听 443(HTTPS)或 80(HTTP),否则重定向会失败
替代方案:结合 Cookie 或 URL 参数更可控
若需稳定识别用户语言,建议首次访问时由后端设置语言 Cookie(如 lang=zh),后续 Nginx 可直接读取:
if ($cookie_lang = "zh") { return 301 https://zh.example.com$request_uri; }if ($cookie_lang = "en") { return 301 https://en.example.com$request_uri; }
这种方式绕过 Accept-Language 的不可靠性,也便于用户手动切换语言。
实际部署时建议加日志验证匹配效果,例如在 log_format 中加入 $http_accept_language 字段,观察真实请求分布后再调整正则精度。











