I'm using i18next with React and Vite for loading the translation for my app. In the app, I have a child component that allows users to set a banner message in some languages, and it uses a key from the translation to display a prefill message. The child component also has a language selector but just to preview the message in other languages, not changing the app languauge. In other words, the child component uses the same translation but a different laguage state. Before applying the lazy loading translation, the child component works just fine as the translations of all the supported languages are loaded. But after implementing the lazy load, it only loads the current language, which causes the other language prefill message to display just a key.
I tried to add the trannslation under resoures for i18next init options but it won't lazy load at all. Then I've tried to add the missing bundle after the init, but it will prevent the page from loading new translation on language changes. Below is how I setup i18n and my resourcesToBackend function.
const resourcesToBackend: (res: any) => BackendModule = (res) => ({
type: 'backend',
init: function (services, backendOptions, i18nextOptions) {
// no init needed
},
read: function (language, namespace, callback) {
if (typeof res === 'function') {
// in case someone wants to customize the loading...
if (res.length < 3) {
// no callback
try {
const r = res(language, namespace);
if (r && typeof r.then === 'function') {
// promise
r.then((data) => {
callback(null, (data && data.default) || data);
}).catch(callback);
} else {
// sync
callback(null, r);
}
} catch (err) {
callback(err, null);
}
return;
}
// normal with callback
res(language, namespace, callback);
return;
}
callback(null, res && res[language] && res[language][namespace]);
},
});
i18next
.use(initReactI18next)
.use(languageDetector)
.use(
resourcesToBackend(
(language: string, namespace: string) => import(`./${namespace}-${language}.json`),
),
)
.init({
partialBundledLanguages: true,
supportedLngs: SUPPORTED_LANGUAGES,
resources: {},
defaultNS: DEFAULT_NAMESPACE,
interpolation: {
escapeValue: false,
},
})
.then(() => {
BANNER_SUPPORTED_LANGUAGES.forEach((lang) => {
i18next.addResourceBundle(
lang.toLowerCase(),
DEFAULT_NAMESPACE,
BANNER_PREFILL_MESSAGES[lang.toLowerCase()],
true, // to extend the loaded resources
true, // to update the translation if the key is available in the resources
);
});
})
.catch((e) => {
console.log(e);
});
Is there a way to make my case works? I want to keep the translation and anything related in the i18n only. So far I've tried the above methods, but none of them worked so maybe my last resort is to move all the translations used by the child component to the child folder.