nginx可通过map提取accept-language头并结合location实现根路径自动跳转至语言子路径。具体为:http块中用map映射语言码,server中location=/用return 302跳转,再以alias按语言路径服务静态资源。

Nginx 本身不解析 Accept-Language 头做自动语言识别,但可以通过 map 提取语言标识、再用 location 做路径分发,实现“访问根路径 → 自动跳转到对应语言子路径”的效果。关键不是 location 自己识别,而是它配合 map 变量完成路由。
核心逻辑:
先在 http 块中用 map 把请求头 $http_accept_language 映射为标准语言码(如 zh、en),然后在 server 块中用 location = / 捕获根请求,通过 return 302 /$lang/ 跳转;后续 /zh/、/en/ 等路径再由独立的 location 块处理静态资源。
✅ 正确配置步骤
1. 在 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;
}
注意:
map必须写在http { ... }内,不能嵌套在server或location中;正则前加~*表示忽略大小写。
2. 在 server 块中处理根路径跳转
location = / {
return 302 /$lang/;
}
使用
302是为了方便后期灰度或调试;稳定后可改为301。该跳转会把/→/zh/或/en/,确保后续所有请求都带语言上下文。
3. 为各语言路径设置静态服务(推荐用 alias)
location ~ ^/(zh|zh-hant|en|ja|ko)/$ {
alias /var/www/site/$1/;
index index.html;
try_files $uri $uri/ =404;
}
alias比root更适合这种结构:访问/zh/就直接指向/var/www/site/zh/目录,且index.html会从该目录下查找。
4. 静态资源路径兼容(可选但建议)
如果前端使用相对路径(如 <script src="/js/app.js"></script>),需额外支持无语言前缀的公共资源:
location ~ ^/(css|js|images|fonts)/ {
root /var/www/site/common;
}
这样
/js/app.js和/zh/js/app.js可共存,避免重复存放。
❌ 常见误区提醒
- 不要用
if ($http_accept_language ~ ...)在 location 里做判断 —— 性能差、易出错、Nginx 官方不推荐; - 不要依赖
index index.zh.html index.en.html;——index指令不读请求头,无法动态选择; - 不要把语言跳转逻辑写在
location /里(不加=),否则会误匹配/zh/css/style.css等资源路径; -
location ^~ /zh/和location ~ ^/zh/功能不同:前者是前缀匹配(高效),后者是正则(灵活但稍慢),按需选用。
? 补充:支持 Cookie 优先策略(增强体验)
如果用户手动切换过语言并存了 lang=zh Cookie,可优先读 Cookie,再 fallback 到 Accept-Language:
map $cookie_lang $lang_from_cookie {
~^zh zh;
~^en en;
~^ja ja;
default "";
}
map $http_accept_language $lang_from_header {
~*zh-cn|zh-sg zh;
~*en-us|en-gb en;
~*ja-jp|ja ja;
default en;
}
map $lang_from_cookie $lang {
"" $lang_from_header;
default $lang_from_cookie;
}
然后仍用 location = / { return 302 /$lang/; } 即可。这样既尊重用户选择,又保底可用浏览器偏好。
不复杂但容易忽略细节。











