Backend Fallback

Ensuring your application always has translations available — even if the network is down or the primary backend is unreachable — is crucial for a seamless user experience. Backend fallback lets you define a secondary source for translations, such as local or bundled resources, to guarantee reliability and offline support.

Why use backend fallback?

  • Provides resilience if the primary backend (e.g., Locize) is temporarily unavailable
  • Enables offline support for your app
  • Ensures users always see translations, even in poor network conditions

Browser fallback with local / bundled translations

With i18next, you can configure a fallback backend in the browser. The primary backend (e.g., your Locize backend) is used first. If it is not reachable or does not serve translations, a secondary backend (such as local or bundled translations) is used. This is made possible by the chained backend.

Example: Using bundled resources as a fallback

import i18next from "i18next";
import ChainedBackend from "i18next-chained-backend";
import LocizeBackend from "i18next-locize-backend";
import resourcesToBackend from "i18next-resources-to-backend";
const bundledResources = {
  en: {
    translation: {
      key: 'value'
    }
  }
};
i18next
  .use(ChainedBackend)
  .init({
    fallbackLng: "en",
    // ... your i18next config
    backend: {
      backends: [
        LocizeBackend,
        resourcesToBackend(bundledResources)
      ],
      backendOptions: [{
        projectId: "[PROJECTID]",
        apiKey: "[APIKEY]",
        version: "[VERSION]"
      }]
    }
  });

Lazy loading in-memory translations (e.g. with webpack)

You can also lazy load your in-memory translations, which is useful for large projects or when using bundlers like webpack.

Example: Lazy loading JSON files as a fallback

import i18next from "i18next";
import ChainedBackend from "i18next-chained-backend";
import LocizeBackend from "i18next-locize-backend";
import resourcesToBackend from "i18next-resources-to-backend";
i18next
  .use(ChainedBackend)
  .init({
    fallbackLng: "en",
    // ... your i18next config
    backend: {
      backends: [
        LocizeBackend,
        resourcesToBackend((lng, ns) => import(`./locales/${lng}/${ns}.json`))
      ],
      backendOptions: [{
        projectId: "[PROJECTID]",
        apiKey: "[APIKEY]",
        version: "[VERSION]"
      }]
    }
  });

More information can be found here:

Server side fallback with filesystem

On server side you can also use the i18next-fs-backend for example instead of the in memory fallback.

import i18next from "i18next";
import ChainedBackend from "i18next-chained-backend";
import LocizeBackend from "i18next-locize-backend";
import FsBackend from "i18next-fs-backend";
i18next
  .use(ChainedBackend)
  .init({
    fallbackLng: "en",
    // ... your i18next config
    backend: {
      backends: [
        LocizeBackend,
        FsBackend
      ],
      backendOptions: [{
        projectId: "[PROJECTID]",
        apiKey: "[APIKEY]",
        version: "[VERSION]"
      }, {
        loadPath: './locales_cache/{{lng}}/{{ns}}.json'
      }]
    }
  });

More information can be found here:

We suggest not to use multiple backends with the i18next-chained-backend in combination with saveMissing or updateMissing, because it may happen, that the trigger for this is based on stale data.