import i18n from 'i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import Backend, { HttpBackendOptions } from 'i18next-http-backend'; import { initReactI18next } from 'react-i18next'; import { trimTrailingSlash } from './utils/common'; i18n // i18next-http-backend // loads translations from your server // https://github.com/i18next/i18next-http-backend .use(Backend) // detect user language // learn more: https://github.com/i18next/i18next-browser-languageDetector .use(LanguageDetector) // pass the i18n instance to react-i18next. .use(initReactI18next) // init i18next // for all options read: https://www.i18next.com/overview/configuration-options .init({ debug: false, fallbackLng: 'en', // Explicit whitelist so the detector can't resolve to a language we // don't ship (e.g. `fr`) and then 404 silently. Matches the native // PushStrings / SW normalizeLang clamp — all three surfaces live in // the same `{en, ru}` set. supportedLngs: ['en', 'ru'], // Track the device/system language on every launch. The default // detector order checks localStorage before navigator.language, so // i18next "sticks" to whichever language was picked on first install // — when a user later changes their phone's system language, the // cached value wins and the app stays in the old language. Vojo has // no in-app language selector, so we have nothing to cache: read // `navigator.language` every time, fall through to `htmlTag` for // edge cases (extension iframes, very old WebViews), and write // nothing back to storage. detection: { order: ['navigator', 'htmlTag'], caches: [], }, interpolation: { escapeValue: false, // not needed for react as it escapes by default }, load: 'languageOnly', backend: { loadPath: `${trimTrailingSlash(import.meta.env.BASE_URL)}/public/locales/{{lng}}.json`, }, }); export default i18n;