Nginx多语言缓存需归一化语言标识、结合GeoIP增强判定、构造结构化缓存键并协同Vary头:用map统一zh/en/ja/ko等语言码,fallback为en;优先取URL路径语言前缀;通过GeoIP2映射国家码到语言;缓存键含$scheme$request_method$host$request_uri|$lang|$geoip2_data_country_code;添加Vary头并透传X-Geo-Country给后端。

在 Nginx 中实现多语言缓存,核心不是简单地把语言参数塞进缓存键,而是让缓存键能准确反映“哪些请求应共享同一份语言内容”。直接用 $args 或原始 $http_accept_language 容易导致键碎片化——比如 zh-CN、zh-TW、ZH-hk 被当成不同键,实际却该命中同一套中文文案。
用 map 统一语言标识,避免 Accept-Language 泛滥
浏览器发来的语言头格式混乱,不能直接用于缓存键。应在 http 块中定义归一化映射:
- 匹配任意以
zh开头的语言头,统一为zh;en、ja、ko同理 - 支持 fallback:未匹配到时默认设为
en - 若 URL 路径含语言前缀(如
/zh/about),可优先提取路径段,比 header 更权威
示例配置:
~^zh "zh";
~^en "en";
~^ja "ja";
~^ko "ko";
default "en";
}
结合地理信息增强语言判定一致性
单靠语言头不够稳定,尤其当用户手动切换语言但 IP 仍在日本时,可能造成后端响应与缓存键不一致。推荐用 GeoIP2 模块推导默认语言:
- 加载
geoip2模块并指定数据库路径 - 提取国家代码:
$geoip2_data_country_code - 再用 map 将国家码映射为语言:
CN→zh、JP→ja、DE→de - 这样即使 Accept-Language 是英文,中国用户仍大概率命中中文缓存,更符合业务预期
构造结构化缓存键,剔除干扰维度
最终缓存键应只保留真正影响响应内容的变量。典型写法:
proxy_cache_key "$scheme$request_method$host$request_uri|$lang|$geoip2_data_country_code";-
$scheme$request_method$host$request_uri是基础骨架,保证协议、方法、域名、路径一致 -
|$lang引入归一化后的语言标识,确保中/英/日等版本隔离 -
|$geoip2_data_country_code补充地域维度,支撑“同语言不同地区”的细分缓存(如zh-CN和zh-TW可分别处理) - 务必剔除 UTM、随机数、时间戳等无关 query 参数,否则会大幅降低命中率
配合 Vary 响应头与后端协同
仅改缓存键不够,还需让客户端和中间层知道该响应是按语言/地域区分的:
- 在 location 中添加:
add_header Vary "Accept-Language, X-Geo-Country"; - 向后端透传地域信息:
proxy_set_header X-Geo-Country $geoip2_data_country_code; - 后端必须依据这些头返回对应语言内容,否则缓存键再准也无意义


















