From 1b5f07249df1217ebded1834ac9eeed9b6bc192a Mon Sep 17 00:00:00 2001 From: gnezim Date: Mon, 6 Apr 2026 10:10:23 +0300 Subject: [PATCH] fix: implement dynamic i18n translation loading with flattening --- apps/react/src/app/i18n/i18n.ts | 59 ++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/apps/react/src/app/i18n/i18n.ts b/apps/react/src/app/i18n/i18n.ts index 70d158bd8..a1eaeb7d3 100644 --- a/apps/react/src/app/i18n/i18n.ts +++ b/apps/react/src/app/i18n/i18n.ts @@ -1,7 +1,25 @@ import i18n from 'i18next' -import HttpBackend from 'i18next-http-backend' import { initReactI18next } from 'react-i18next' +// Flatten nested translation objects +const flattenTranslations = (obj: any, prefix = ''): Record => { + const result: Record = {} + + const flatten = (current: any, path: string) => { + if (typeof current === 'string') { + result[path] = current + } else if (typeof current === 'object' && current !== null && !Array.isArray(current)) { + for (const key in current) { + const newPath = path ? `${path}.${key}` : key + flatten(current[key], newPath) + } + } + } + + flatten(obj, prefix) + return result +} + // Language detection logic const getInitialLanguage = (): string => { const stored = localStorage.getItem('i18nextLng') @@ -31,17 +49,25 @@ const getInitialLanguage = (): string => { const lng = getInitialLanguage() +// Initialize with empty resources, will be loaded dynamically i18n - .use(HttpBackend) .use(initReactI18next) .init({ + resources: { + ru: { translation: {} }, + en: { translation: {} }, + es: { translation: {} }, + fr: { translation: {} }, + it: { translation: {} }, + ja: { translation: {} }, + ko: { translation: {} }, + de: { translation: {} }, + zh: { translation: {} }, + }, fallbackLng: 'ru', lng, defaultNS: 'translation', ns: ['translation'], - backend: { - loadPath: '/assets/i18n/{{lng}}.json', - }, interpolation: { escapeValue: false, }, @@ -50,4 +76,27 @@ i18n }, }) +// Load translations dynamically +const loadLanguage = async (language: string) => { + try { + const response = await fetch(`/assets/i18n/${language}.json`) + if (!response.ok) throw new Error(`Failed to load ${language} translations`) + + const data = await response.json() + const flattened = flattenTranslations(data) + + i18n.addResourceBundle(language, 'translation', flattened, true, true) + } catch (error) { + console.error(`Error loading ${language} translations:`, error) + } +} + +// Load current language +loadLanguage(lng).then(() => { + // Also preload fallback language + if (lng !== 'ru') { + loadLanguage('ru') + } +}) + export default i18n