i18next / i18next-http-backend

i18next-http-backend is a backend layer for i18next using in Node.js, in the browser and for Deno.
MIT License
452 stars 70 forks source link

reloadInterval not working for multiple translation files #127

Closed sernaferna closed 10 months ago

sernaferna commented 11 months ago

🐛 Bug Report

The reloadInterval setting doesn't seem to work for multiple translation files.

To Reproduce

The setting was working when I only had a single translation.json file. I'd build and deploy the app to production and new/updated translations would appear in the browser.

I've since broken my single JSON file into multiple for easier maintenance. Everything works fine in dev (when I Ctrl+R to reload the browser it gets all of the translations), but in production the translation files seem to be cached and never updated, even if I Ctrl+R the browser. I can only force new/updated translations to load by manually opening the JSON file in the browser directly (i.e. https://servername/locales/en/whatever.json).

Here are the i18n settings I'm using:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json',
      reloadInterval: 60 * 60 * 1000,
    },
  });

export default i18n;

Note: I added the loadPath setting in an effort to troubleshoot this issue. When I had a single translation.json file I hadn't specified that setting, just used the default.

Expected behavior

The reloadInterval setting should work for any and all translation files downloaded.

Your Environment

All of the translation files are coming from the /public/locales/{{lng}} directory of my React app.

adrai commented 11 months ago

I'm not able to reproduce it. Please provide a minimal reproducible example repository or codesandbox example. btw: your reloadInterval is set to 1 hour in your code snippet

sernaferna commented 11 months ago

I'm not able to reproduce it. Please provide a minimal reproducible example repository or codesandbox example. btw: your reloadInterval is set to 1 hour in your code snippet

It is set to 1 hour, correct. When I was using a single translation.json file it would get the latest file whenever the application was first loaded. (i.e. deploy a new version, then open the browser and go to the site; the updated translations appear.)

I'm not sure how a reproducible example can be created in this case; if you create an application in Code Sandbox it will definitely work. The only way it stops working is if you have a real, working application and then deploy a new version of it (with modified translation files) to the same environment. At that point the library clings to the old translation files.

adrai commented 11 months ago

Then you probably have some csche control configured? Hard to help without a reproducible example...

sernaferna commented 11 months ago

Then you probably have some csche control configured? Hard to help without a reproducible example...

If you have a suggestion as to how we could create a reproducible example, I'm all ears. How did you test having multiple translation files when you implemented the feature?

In the meantime, this library is responsible for caching (or not).

The same thing used to happen when I had a single translation file (i.e. updates to translations wouldn't load unless I manually downloaded the settings file), but then I discovered the reloadInterval setting and everything was fine; deploy new version of the app, new translations are loaded in the UI. This component would load the new version of the file (and presumably do so again every hour, if one used the app that long).

Then I started using multiple namespaces and translation files, and am getting the same issue I used to have. When translation JSON files get updated, the component never downloads them, just gets them from the cache. The reloadInterval setting used to force it to, for a single translations.json file, but doesn't for multiple namespaces.

adrai commented 11 months ago

No, i18next-http-backend does not have any caching functionality... for this you can use normal Cache-Control headers or something like: localstorage-backend: https://www.i18next.com/how-to/caching#browser-caching-with-local-storage

fyi: the reloadInterval just reloads all namespaces that have been loaded before: https://github.com/i18next/i18next-http-backend/blob/master/lib/index.js#L139C4-L139C4

so, I really can't help you more then that without a reproducible example, sorry

sernaferna commented 10 months ago

Gave up on reloadInterval, and am instead using the webpack hash to force new URLs for the translation files every time I build the app:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';

declare var __webpack_hash__: string;

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json?h=' + __webpack_hash__,
    },
  });

export default i18n;

__webpack_hash__ is a module variable created by webpack with the hash used for this build; appending it to the URL of the loadPath makes that URL unique for each build. (Given that it's just a static JSON file, the HTTP server ignores that query string param.)

I no longer care about reloadInterval -- the app can cache the translation file with that URL as long as it likes.