使用i18next-resources-to-backend懒加载时,i18next.init()回调未触发
i18next-resources-to-backend懒加载时init的ready回调不触发问题
问题描述
使用i18next-resources-to-backend实现懒加载时,i18next.init()的ready回调始终无法触发。语言文件路径正确,控制台日志显示语言/命名空间字典已成功加载,但回调就是不执行。改用i18next-http-backend插件时该配置能正常运行,所有语言/命名空间文件均存在且可正确解析为JSON。
代码示例
import i18next from 'i18next'; import i18nextBrowserLanguageDetector from 'i18next-browser-languagedetector'; import i18nextSprintfPostProcessor from 'i18next-sprintf-postprocessor'; import i18nextResourcesToBackend from 'i18next-resources-to-backend' i18next.use(i18nextBrowserLanguageDetector).use(i18nextResourcesToBackend((language, namespace)=>{ return new Promise(function(resolve, reject) { MyFsReadFile(`i18n/${language}/${namespace}.json`, (file)=>{ const reader = new FileReader(); reader.onload = (ev)=>{ resolve(JSON.parse(ev.target.result)) }; reader.readAsText(file); }), (error)=>{ if(process.env.NODE_ENV !== 'production') console.log('i18nextResourcesToBackend error', language, namespace, error); reject(error); } }); })).use(i18nextSprintfPostProcessor) .init({ fallbackLng: 'en', debug: process.env.NODE_ENV !== 'production', ns: ['app','test','core'], defaultNS: 'app', fallbackNS: 'core', overloadTranslationOptionHandler: i18nextSprintfPostProcessor.overloadTranslationOptionHandler }, (err, t)=> { // 此回调从未触发 });
解决方案
1. 强制预加载初始化所需资源
i18next-resources-to-backend是懒加载后端,默认不会在init阶段加载所有指定的命名空间。要触发init回调,需确保初始化时必要的资源已加载完成,可通过preload配置实现:
// 获取检测到的语言(依赖languageDetector) const detectedLng = i18next.language || i18next.options.fallbackLng; i18next.init({ fallbackLng: 'en', debug: process.env.NODE_ENV !== 'production', ns: ['app','test','core'], defaultNS: 'app', fallbackNS: 'core', overloadTranslationOptionHandler: i18nextSprintfPostProcessor.overloadTranslationOptionHandler, // 预加载检测到的语言,确保init阶段加载必要资源 preload: [detectedLng], // 关闭initImmediate,确保等待预加载完成再触发回调 initImmediate: false }, (err, t) => { // 现在回调应该能正常触发 });
2. 修复Promise的错误处理逻辑
原代码中MyFsReadFile的错误回调写法错误,导致错误发生时无法正确reject Promise,i18next会一直等待Promise完成,从而卡住init回调。修正后的资源加载逻辑:
i18nextResourcesToBackend((language, namespace)=>{ return new Promise(function(resolve, reject) { // 错误回调需作为MyFsReadFile的第二个参数传入 MyFsReadFile(`i18n/${language}/${namespace}.json`, (file)=>{ const reader = new FileReader(); reader.onload = (ev)=>{ try { resolve(JSON.parse(ev.target.result)); } catch (parseErr) { // 新增JSON解析错误的处理 reject(parseErr); } }; reader.onerror = (err) => reject(err); // 新增FileReader错误处理 reader.readAsText(file); }, (error)=>{ if(process.env.NODE_ENV !== 'production') console.log('i18nextResourcesToBackend error', language, namespace, error); reject(error); } ); }); })
3. 利用debug日志排查
保持debug: true,查看控制台中i18next的输出日志,确认:
- 是否有资源加载失败的提示
- 预加载的资源是否已完成加载
- 有没有未处理的Promise等待状态
核心原因
i18next-resources-to-backend的设计是按需加载,仅在实际使用翻译时才加载对应资源。而init的ready回调需要等待初始化阶段所有必要资源加载完成,因此必须通过preload强制加载初始化所需的语言和命名空间,同时确保所有异步操作的Promise能正确resolve/reject。
内容的提问来源于stack exchange,提问作者agei
相关产品推荐
相关产品推荐

