Reputation: 93
I am using react and react-i18next for the localization of my app. The issue is that after updating localization files. Sometimes an old version of my json files are cached in the browser. It could be solved if the user clean the cache but I can't rely on users to know how to clear the cache. JSON files are under public\locales.
I just figured out how to disable the cache in i18next translation.json files
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: "en",
debug: true,
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
requestOptions: {
cache: 'no-store',
},
},
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
});
It is not an ideal solution. The better solution - translations files need to be retrieved fresh after each build. But now this does not happen, such a feeling that hash is not added to translation files How to prevent cache after a new build?
Upvotes: 7
Views: 5290
Reputation: 11
You can use the version from package.json in the file request parameters. It is not a fact that translations will be changed in each release, but it is definitely better than disabling the cache or not updating it
backend: {
loadPath: `/locales/{{lng}}/{{ns}}.json?version=${version}`
}
Upvotes: 1
Reputation: 1
I got the same issue using i18next-localstorage-backend
which is meant to use localStorage
in browser.
I simply added a defaultVersion
in the init options, But in order to get a new version every build, I had to generate a random version number.
Here is my i18n.ts
file:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import resourcesToBackend from 'i18next-resources-to-backend';
import Backend from "i18next-chained-backend";
import LocalStorageBackend from "i18next-localstorage-backend";
function genRandonNumber(length : number) {
const chars = '0123456789';
const charLength = chars.length;
let result = '';
for ( var i = 0; i < length; i++ ) {
result += chars.charAt(Math.floor(Math.random() * charLength));
}
return result;
}
const LOCAL_DOMAINS = ["localhost", "127.0.0.1"];
const HASH = genRandonNumber(10);
i18n
.use(Backend)
// detect user language
.use(LanguageDetector)
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next
.init({
// default fallback will be french
fallbackLng: 'fr',
// default namespace to load
ns: 'header',
// load languages ressources with lazy loading and caching client side
backend: {
backends: [
LocalStorageBackend, // primary ressources (cache = window.localStorage)
resourcesToBackend((language, namespace, callback) => {
import(`/public/locales/${language}/${namespace}.json`)
.then((resources) => {
callback(null, resources)
})
.catch((error) => {
callback(error, null)
})
}) // fallback ressources (json)
],
backendOptions: [{
expirationTime: 24 * 60 * 60 * 1000 * 7, // 7 days
defaultVersion: "v" + HASH // generate a new version every build to refresh
}]
},
// debug only in dev
debug: LOCAL_DOMAINS.includes(window.location.hostname),
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
});
i18n.on('languageChanged', () => {
document.documentElement.lang = i18n.language;
});
export default i18n;
My i18n
instance is a bit more complicated, but in the end it will:
localStorage
to reduce networking and enable faster translation.JSON
files for a given page thanks to namespaces.localStorage
every new build.If you are using multiple backends (JSON
files and localStorage
), you have to use i18next-chained-backend
.
Upvotes: 0