多语言站点缓存键设计核心是归一化语言维度:用map提取主语言代码(如zh、en),优先取url路径或cookie中的显式标识,静态资源不加语言字段,ssr页面才纳入稳定$final_lang,并通过响应头和日志验证缓存收敛。

多语言站点的缓存键设计,核心是让同一语言内容只生成一个缓存项,避免因语言标识格式不一导致缓存分裂。不能简单把所有语言相关字段拼进去,而要提取稳定、归一化的语言维度,并按内容类型区别对待。
只取主语言代码,忽略区域子标签和大小写
浏览器发送的 Accept-Language 差异很大:zh-CN、zh-TW、ZH-hk、zh;q=0.9……这些都该命中同一套中文文案。直接用 $http_accept_language 会生成多个 key,造成严重缓存浪费。
推荐用 map 提取主语言:
map $http_accept_language $lang {
~^zh "zh";
~^en "en";
~^ja "ja";
~^ko "ko";
~^fr "fr";
default "en";
}这样无论原始值如何变化,最终都统一为 "zh" 或 "en" 等标准码,确保语言内容收敛。
优先采用 URL 路径或 Cookie 中的显式语言标识
路径(如 /en/about)或 Cookie(如 lang=ja)比 Accept-Language 更权威、更可控,应作为首选信号。
可分别定义:
- 从路径提取:
map $uri $route_lang { ~^/en/ "en"; ~^/zh/ "zh"; default ""; } - 从 Cookie 提取:
map $http_cookie $cookie_lang { ~lang=([^;]+) $1; default ""; }
在 location 块中组合使用:
set $final_lang $route_lang;
if ($final_lang = "") {
set $final_lang $cookie_lang;
}
if ($final_lang = "") {
set $final_lang $lang;
}静态资源与 SSR 页面分开处理
不是所有内容都需要语言维度:
-
JS/CSS/图片等静态资源:语言不影响内容,
proxy_cache_key中完全不需要$final_lang,用$scheme$host$uri即可 -
SSR 渲染的 HTML 页面(如 Next.js、Nuxt):语言决定文案、日期、货币等,必须纳入
$final_lang,但仅限稳定值,例如:"$scheme$request_method$host$uri$lang"
验证缓存是否真正收敛
配置完成后,务必通过响应头和日志确认效果:
- 加响应头:
add_header X-Language-Used $final_lang;,方便前端或调试时查看实际使用的语言标识 - 记录日志:
log_format cache_log '$remote_addr - $upstream_cache_status "$request" $final_lang';,观察不同请求是否命中相同$final_lang下的 HIT - 检查缓存目录结构,确认同语言路径下 key 数量合理,无大量相似但不一致的缓存文件











