Accept-Language 必须由前端在每个请求中显式设置为 zh-CN,后端无法单方面决定;Django 的 LANGUAGE_CODE 仅作兜底,实际语言由中间件解析 Accept-Language 头决定。
HTTP 请求里 Accept-Language 怎么设成 zh-CN
浏览器或客户端不主动发 accept-language: zh-cn,服务端就很难默认走中文逻辑——这不是后端能单方面决定的事,得靠请求头配合。
常见错误是只改后端配置(比如 django 的 language_code),但前端发起的 ajax 或 fetch 请求压根没带这个头,结果接口返回英文文案,还以为是后端没生效。
- 前端用
fetch时显式加头:headers: { 'Accept-Language': 'zh-CN' } - axios 可全局设置:
axios.defaults.headers.common['Accept-Language'] = 'zh-CN' - 表单提交(
GET/POST)本身不带该头,需配合 JS 拦截或改用fetch替代 - 注意:部分 CDN 或反向代理(如 Nginx)会清理或覆盖该头,要检查中间层是否透传
Django 中 LANGUAGE_CODE 和 LANGUAGES 的关系
LANGUAGE_CODE 是 fallback 语言,不是“用户看到的语言”;它只在没匹配到用户请求头、也没登录用户语言偏好时才生效。真正起作用的是中间件对 Accept-Language 的解析和缓存。
-
LANGUAGE_CODE = 'zh-hans'合法,但浏览器通常发zh-CN,Django 默认能映射,无需额外配置 - 若想支持简体/繁体自动区分,需在
LANGUAGES里明确列出:[('zh-hans', 'Simplified Chinese'), ('zh-hant', 'Traditional Chinese')] - 启用
LocaleMiddleware前,get_language()永远返回LANGUAGE_CODE,别误以为它已生效 - 模板中
{% get_current_language %}输出的是运行时检测结果,不是配置值
Vue/React 项目里怎么让 API 请求自动带上中文语言头
单页应用容易忽略:路由切换、组件重载、SWR/React Query 的自动 refetch 都可能发出不带语言头的请求,导致部分接口返回英文。
- 封装请求函数时统一注入:
headers: { ...defaultHeaders, 'Accept-Language': navigator.language || 'zh-CN' } -
navigator.language在 Chrome/Firefox 返回zh-CN,Safari 可能是zh,建议做简单 normalize:navigator.language.replace(/^[a-z]+$/, '$&-CN') - 避免在
useEffect或onMounted里动态读取并拼接 header——异步时机不可控,可能漏掉首屏请求 - 如果用了 i18n 库(如
vue-i18n),优先读取其locale.value而非navigator,更可靠
Set-Cookie 响应头里的 lang=zh 真的有用吗
有些老项目用 Cookie 记录语言偏好,再在后端读取它来覆盖 Accept-Language。这看似可控,实则问题一堆。
- Cookie 是 domain 级别的,跨子域或前后端分离部署时,前端 JS 可能读不到后端 set 的 cookie(
SameSite=Lax或Secure限制) - 服务端读取
lang=zh后,必须手动调用translation.activate('zh')(Django)或等效逻辑,否则只是白存 - 用户手动改浏览器语言后,cookie 不会自动更新,容易造成“界面是中文,接口返回英文”的撕裂感
- 现代做法是:用 cookie 存偏好,但所有接口仍以
Accept-Language为准,cookie 仅用于首次访问兜底

















