使用i18next中间件时i18next.language未返回实际翻译语言
问题:i18next.language未反映实际使用的翻译语言?
基于Node + EJS的应用,使用i18next-fs-backend和i18next-http-middleware组件,配置代码如下:
[...] const i18next = require('i18next'), i18next_backend = require('i18next-fs-backend'), i18next_middleware = require('i18next-http-middleware'); i18next .use(i18next_backend) .use(i18next_middleware.LanguageDetector) .init({ preload: ['en', 'fr'], fallbackLng: 'en', backend: { loadPath: path.join(__dirname, '/locales/{{ns}}-{{lng}}.json') }, debug: true }); app.use(i18next_middleware.handle(i18next)); app.use((req, res, next) => { console.log(req.headers['accept-language'], ':', req.language, i18next.language, i18next.resolvedLanguage, i18next.languages); next(); });
现象:
- 当请求头
accept-language为en时,日志输出en : en en en ['en'],页面显示英文; - 当
accept-language为fr时,日志输出fr : fr en en ['en'],但页面实际显示法语字符串。
疑问:为何i18next.language未反映实际使用的翻译语言?(预期日志应为fr : fr fr fr ['en', 'fr']?)
解答
核心原因是全局i18next实例与请求级别的i18n上下文是分离的:
i18next-http-middleware的设计是为每个请求创建独立的i18n上下文,确保不同请求的语言设置互不干扰;- 你日志里调用的
i18next.language、i18next.resolvedLanguage、i18next.languages是全局i18next实例的状态,它只会保持初始化时的默认值(这里是en),不会随请求的语言变化而更新; - 页面能正确显示法语,是因为渲染时使用的是请求上下文里的翻译方法(比如
req.t),中间件已经把请求级别的i18n实例挂载到req.i18n上,这个实例才对应当前请求的语言设置。
如果要在日志中获取当前请求实际使用的i18n状态,应该替换成请求上下文里的req.i18n对象,修改后的日志代码如下:
app.use((req, res, next) => { console.log( req.headers['accept-language'], ':', req.language, req.i18n.language, req.i18n.resolvedLanguage, req.i18n.languages ); next(); });
此时当accept-language为fr时,日志会输出符合预期的fr : fr fr fr ['fr', 'en'](注:languages数组顺序会按优先级排列,法语在前,fallback的英语在后)。
内容的提问来源于stack exchange,提问作者Joan
相关产品推荐
相关产品推荐

