通过AJAX POST调用/i18n/setlang/切换语言在Firefox中无效
我之前处理过类似的跨浏览器语言切换问题,结合你的描述,Chrome正常但Firefox完全无效,大概率是Cookie、CSRF令牌或者请求处理时机的问题,你可以按以下步骤逐一排查:
1. 确认CSRF令牌是否正确携带
Django的/i18n/setlang/视图强制要求CSRF验证,Chrome在同域请求中可能会自动携带Cookie里的CSRF令牌,但Firefox在某些场景下(比如AJAX请求的Content-Type设置不对)可能不会自动处理。
你需要手动在AJAX请求中添加X-CSRFToken头,从Cookie中获取令牌值:
// 辅助函数:获取指定名称的Cookie function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } // 发起语言切换请求 const csrftoken = getCookie('csrftoken'); const language_code = 'fr'; // 替换为用户选择的语言码 fetch('/i18n/setlang/', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRFToken': csrftoken }, body: `language=${language_code}` }) .then(response => { // 必须等待请求成功后再刷新页面 if (response.ok) { window.location.reload(); } else { console.error('语言切换请求失败'); } });
2. 检查Session Cookie的SameSite属性
Django默认的Session Cookie SameSite属性是Lax,在Firefox的AJAX请求中,这个设置可能导致Cookie无法被正确携带,进而LocaleMiddleware无法读取用户的语言偏好。
你可以在settings.py中修改Session配置:
# 注意:SameSite=None 需要配合HTTPS使用,所以必须开启SESSION_COOKIE_SECURE SESSION_COOKIE_SAMESITE = 'None' SESSION_COOKIE_SECURE = True
如果你的站点还没有HTTPS,这个设置可能不生效(Firefox会拒绝SameSite=None的Cookie),这种情况下可以暂时把SESSION_COOKIE_SAMESITE改成'Lax',同时确保AJAX请求完全符合同域规则。
3. 确保AJAX请求完成后再刷新页面
如果你的代码是发送AJAX请求后立即刷新页面,Firefox可能还没完成Session的更新就重新加载了页面,导致语言设置没生效。一定要把页面刷新操作放在请求成功的回调函数里,就像上面代码中那样,用then等待响应状态正常后再执行window.location.reload()。
4. 验证请求参数格式是否正确
你提到携带的数据是{language: [language_code]},但Django的/i18n/setlang/视图期望的是单个语言码的表单数据,而不是数组格式。如果你的AJAX请求用了JSON格式发送数据,Django无法正确解析,必须用application/x-www-form-urlencoded格式(就像上面代码里的body那样),或者multipart/form-data格式。
5. 检查Firefox的Cookie存储
打开Firefox的开发者工具(F12),切换到「存储」标签,查看Cookie列表里有没有django_language和sessionid这两个Cookie:
django_language的值应该是你设置的语言码(比如fr、pl等)sessionid应该存在且有效
如果这两个Cookie不存在,说明AJAX请求没有成功设置Session或语言Cookie,需要回到「网络」标签查看请求的状态码和响应内容,排查具体错误。
关于HTTP_ACCEPT_LANGUAGE的差异
你提到Firefox的HTTP_ACCEPT_LANGUAGE只有en相关的语言,不过因为你是通过/i18n/setlang/设置Session语言,LocaleMiddleware会优先使用Session里的语言设置,而不是浏览器的Accept-Language头,所以这个差异本身不会导致失效,主要还是前面几个Cookie和请求的问题。
内容的提问来源于stack exchange,提问作者Ryan Pergent

