nginx 通过 map 指令解析 accept-language 请求头为标准语言码(如 zh、en),再结合 return 实现根路径自动跳转至对应语言首页,全程零后端、高性能;支持 cookie 优先策略与静态文件目录映射。

要用 Nginx 实现“访问 / 自动跳转到对应语言首页”,核心不是靠 guess 或 JS,而是用 map 提前把浏览器发来的 Accept-Language 头解析成确定的语言码(如 zh、en),再结合 return 或 rewrite 完成跳转。整个过程不依赖后端,纯由 Nginx 在请求初期完成,速度快、无额外开销。
在 http 块中定义 Accept-Language 到语言码的映射
map 必须写在 http 块顶层,不能放在 server 或 location 里。它根据请求头提取主语言,并统一小写处理,避免大小写干扰:
-
$http_accept_language是 Nginx 内置变量,直接获取请求中的Accept-Language值(如zh-CN,zh;q=0.9,en-US;q=0.8) - 用
~*表示大小写不敏感正则,匹配常见语言子标签组合 - 每条规则只取第一个匹配项,顺序很重要;未命中时走
default
示例配置:
http {
map $http_accept_language $lang {
~*zh-cn|zh-sg|zh-hans|zh-hans-cn zh;
~*zh-tw|zh-hant|zh-hk|zh-mo zh-hant;
~*en-us|en-gb|en-ca|en-au|en-nz en;
~*ja-jp|ja ja;
~*ko-kr|ko ko;
default en;
}
}
对根路径做 302 跳转并确保语言可回溯
在 server 块中,针对 location = / 进行跳转。推荐先用 return 302(调试友好),上线后可改 301(SEO 更优):
- 跳转目标为
/$lang/,例如访问根路径且浏览器报zh-CN,就跳到/zh/ - 跳转响应中需带上
Set-Cookie,让后续请求携带语言偏好,避免每次重判 - Cookie 设置建议含
Path=/、Max-Age=31536000(1年)、SameSite=Lax
配置片段:
server {
listen 80;
server_name example.com;
<pre class="brush:php;toolbar:false;">location = / {
add_header Set-Cookie "lang=$lang; Path=/; Max-Age=31536000; SameSite=Lax";
return 302 /$lang/;
}
location ~ ^/(zh|zh-hant|en|ja|ko)/$ {
alias /var/www/site/$1/;
index index.html;
}}
配合静态文件结构与 fallback 机制
每个语言目录需有独立入口,比如 /var/www/site/zh/index.html、/var/www/site/en/index.html。Nginx 不会自动创建这些文件,需提前部署好。
-
alias比root更适合这种路径映射,注意末尾斜杠和路径拼接逻辑 - 若用户手动访问不存在的语言路径(如
/fr/),Nginx 默认返回 404;可在location中加try_files或用error_page 404统一导向默认语言 - 也可在跳转前加一层判断:当
$lang为空或非法时,强制设为en并跳转,避免空路径错误
进阶:兼容 Cookie 优先策略
实际项目中,用户可能已通过前端操作设置了语言偏好(存于 lang=zh Cookie)。此时应让 Cookie 优先级高于 Accept-Language:
- 新增一个
map专门解析$cookie_lang,提取zh、en等主码 - 在
location = /中先检查$cookie_lang是否有效,有则用它;否则回落到$lang(来自Accept-Language) - 这样既尊重用户主动选择,又保留浏览器默认兜底能力
例如:
map $cookie_lang $cookie_lang_code {
~^zh.* zh;
~^en.* en;
~^ja.* ja;
~^ko.* ko;
default "";
}
<p>location = / {
if ($cookie_lang_code) {
set $final_lang $cookie_lang_code;
}
if ($cookie_lang_code = "") {
set $final_lang $lang;
}
add_header Set-Cookie "lang=$final_lang; Path=/; Max-Age=31536000; SameSite=Lax";
return 302 /$final_lang/;
}</p>











