diff --git a/frontend/package.json b/frontend/package.json index 8ab5e46..82341c0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,6 +22,7 @@ "chart.js": "^4.3.0", "crypto-js": "^4.1.1", "i18next": "^22.4.13", + "i18next-http-backend": "^2.4.1", "react": "^18.2.0", "react-bootstrap": "^2.7.2", "react-dom": "^18.2.0", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2c032c5..7c5ce97 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,23 +1,35 @@ import { initReactI18next } from 'react-i18next'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; import i18n from 'i18next'; +import Backend from "i18next-http-backend"; +import { HttpBackendOptions } from 'i18next-http-backend'; +import { ResourcesApi } from '@/api/ResourcesApi'; import { ExecutionPage } from './pages/execution/ExecutionPage'; import { IndexPage } from './pages/index/IndexPage'; import './App.css'; -export const locale = 'en-US'; // Initialize i18next with default options i18n .use(initReactI18next) - .init({ - fallbackLng: locale, + .use(Backend) + .init({ + fallbackLng: 'en-US', debug: true, interpolation: { escapeValue: false, }, + load: 'currentOnly', + backend: { + loadPath: '{{lng}}', // hack: get only localeId but not whole url in the request method + request: (_options, localeId, _payload, callback) => { + ResourcesApi.getAll(localeId) + .then(data => callback(null, { status: 200, data })) + .catch(error => callback(error, { status: 400, data: {} })); + } + } }); const router = createBrowserRouter([ diff --git a/frontend/src/hooks/useResources.ts b/frontend/src/hooks/useResources.ts index 536b2ab..2cd11ec 100644 --- a/frontend/src/hooks/useResources.ts +++ b/frontend/src/hooks/useResources.ts @@ -1,6 +1,3 @@ -import i18n from 'i18next'; - -import { ResourcesApi } from '@/api'; import { useTranslation } from 'react-i18next'; import { useEffect, useState } from 'react'; import { LocalStorageService } from '@/services'; @@ -8,7 +5,6 @@ import { LocalesApi } from '@/api/LocalesApi'; type TLanguages = { [key: string]: string; }; -const DEFAULT_LANGUAGE = 'US'; const LS_LANGUAGE_KEY = 'locale'; async function loadLocales() { @@ -25,52 +21,22 @@ async function loadLocales() { }) }; -export async function loadResources(newLng: string) { - return await ResourcesApi - .getAll(newLng) - .then(r => { - if (r) { - i18n.addResourceBundle(newLng, 'translation', r); - } else { - console.error('No such resource!'); - } - return r; - }); -}; - export function useResources() { + const lastOrDefaultLang = LocalStorageService.get(LS_LANGUAGE_KEY) ?? 'en-US'; const { i18n } = useTranslation(); - const [language, setLanguage] = useState(DEFAULT_LANGUAGE); - const [alreadyLoaded, setAlreadyLoaded] = useState([]); + const [language, setLanguage] = useState(lastOrDefaultLang); const [locales, setLocales] = useState(); - const languages: string[] = locales ? Object.keys(locales) : []; - const changeLanguage = async (lngName: string, initLocales?: TLanguages) => { const newLngCode = initLocales?.[lngName] || locales?.[lngName]; - if (!newLngCode || lngName === language) { + if (!newLngCode) { return; }; - const newLngName = lngName; - - const saveNewLanguage = () => { - LocalStorageService.set(LS_LANGUAGE_KEY, lngName); - setLanguage(newLngName); - }; - - if (alreadyLoaded.includes(newLngName)) { - i18n.changeLanguage(newLngCode); - saveNewLanguage(); - } else { - const res = await loadResources(newLngCode); - if (res) { - i18n.changeLanguage(newLngCode); - setAlreadyLoaded(prev => ([...prev, newLngName])); - saveNewLanguage(); - } - }; + await i18n.changeLanguage(newLngCode); + LocalStorageService.set(LS_LANGUAGE_KEY, lngName); + setLanguage(lngName); }; useEffect(() => { @@ -79,14 +45,19 @@ export function useResources() { const localesRes = await loadLocales(); setLocales(localesRes); - if (lsLng && localesRes[lsLng] && lsLng !== DEFAULT_LANGUAGE) { + if (lsLng && localesRes[lsLng]) { changeLanguage(lsLng, localesRes); - } else { - loadResources(localesRes[DEFAULT_LANGUAGE]); - setAlreadyLoaded([DEFAULT_LANGUAGE]) - }; + } })(); }, []); - return { languages, language, changeLanguage }; + return { + get languages() { + if (locales) + return Object.keys(locales); + + return []; + }, + language, + changeLanguage }; }