From 6276da42cfd392b8a3044960b4b4cfa19652cbe9 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sun, 14 Apr 2024 17:32:25 +0200 Subject: [PATCH] Feature/i18n load resources from backend (#746) * Load i18n resources from backend * Move locales to public folder --- package.json | 1 + {src/i18n/locale => public/locales}/ar.json | 0 {src/i18n/locale => public/locales}/de.json | 0 {src/i18n/locale => public/locales}/en.json | 0 {src/i18n/locale => public/locales}/es.json | 0 {src/i18n/locale => public/locales}/fr.json | 0 {src/i18n/locale => public/locales}/id.json | 0 {src/i18n/locale => public/locales}/it.json | 0 {src/i18n/locale => public/locales}/ja.json | 0 {src/i18n/locale => public/locales}/ko.json | 0 .../i18n/locale => public/locales}/nb-NO.json | 0 {src/i18n/locale => public/locales}/pt.json | 0 {src/i18n/locale => public/locales}/sv.json | 0 {src/i18n/locale => public/locales}/tr.json | 0 {src/i18n/locale => public/locales}/uk.json | 0 {src/i18n/locale => public/locales}/vi.json | 0 .../locale => public/locales}/zh_Hans.json | 0 .../locale => public/locales}/zh_Hant.json | 0 src/i18n/index.ts | 35 ++++++++++-- src/i18n/translations.ts | 53 ------------------- src/screens/Settings.tsx | 3 +- yarn.lock | 14 +++++ 22 files changed, 49 insertions(+), 57 deletions(-) rename {src/i18n/locale => public/locales}/ar.json (100%) rename {src/i18n/locale => public/locales}/de.json (100%) rename {src/i18n/locale => public/locales}/en.json (100%) rename {src/i18n/locale => public/locales}/es.json (100%) rename {src/i18n/locale => public/locales}/fr.json (100%) rename {src/i18n/locale => public/locales}/id.json (100%) rename {src/i18n/locale => public/locales}/it.json (100%) rename {src/i18n/locale => public/locales}/ja.json (100%) rename {src/i18n/locale => public/locales}/ko.json (100%) rename {src/i18n/locale => public/locales}/nb-NO.json (100%) rename {src/i18n/locale => public/locales}/pt.json (100%) rename {src/i18n/locale => public/locales}/sv.json (100%) rename {src/i18n/locale => public/locales}/tr.json (100%) rename {src/i18n/locale => public/locales}/uk.json (100%) rename {src/i18n/locale => public/locales}/vi.json (100%) rename {src/i18n/locale => public/locales}/zh_Hans.json (100%) rename {src/i18n/locale => public/locales}/zh_Hant.json (100%) delete mode 100644 src/i18n/translations.ts diff --git a/package.json b/package.json index 2381550567..4ba8d342ba 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "html-react-parser": "5.1.10", "i18next": "23.11.1", "i18next-browser-languagedetector": "7.2.1", + "i18next-http-backend": "^2.5.0", "material-ui-popup-state": "5.1.0", "p-limit": "5.0.0", "react": "18.2.0", diff --git a/src/i18n/locale/ar.json b/public/locales/ar.json similarity index 100% rename from src/i18n/locale/ar.json rename to public/locales/ar.json diff --git a/src/i18n/locale/de.json b/public/locales/de.json similarity index 100% rename from src/i18n/locale/de.json rename to public/locales/de.json diff --git a/src/i18n/locale/en.json b/public/locales/en.json similarity index 100% rename from src/i18n/locale/en.json rename to public/locales/en.json diff --git a/src/i18n/locale/es.json b/public/locales/es.json similarity index 100% rename from src/i18n/locale/es.json rename to public/locales/es.json diff --git a/src/i18n/locale/fr.json b/public/locales/fr.json similarity index 100% rename from src/i18n/locale/fr.json rename to public/locales/fr.json diff --git a/src/i18n/locale/id.json b/public/locales/id.json similarity index 100% rename from src/i18n/locale/id.json rename to public/locales/id.json diff --git a/src/i18n/locale/it.json b/public/locales/it.json similarity index 100% rename from src/i18n/locale/it.json rename to public/locales/it.json diff --git a/src/i18n/locale/ja.json b/public/locales/ja.json similarity index 100% rename from src/i18n/locale/ja.json rename to public/locales/ja.json diff --git a/src/i18n/locale/ko.json b/public/locales/ko.json similarity index 100% rename from src/i18n/locale/ko.json rename to public/locales/ko.json diff --git a/src/i18n/locale/nb-NO.json b/public/locales/nb-NO.json similarity index 100% rename from src/i18n/locale/nb-NO.json rename to public/locales/nb-NO.json diff --git a/src/i18n/locale/pt.json b/public/locales/pt.json similarity index 100% rename from src/i18n/locale/pt.json rename to public/locales/pt.json diff --git a/src/i18n/locale/sv.json b/public/locales/sv.json similarity index 100% rename from src/i18n/locale/sv.json rename to public/locales/sv.json diff --git a/src/i18n/locale/tr.json b/public/locales/tr.json similarity index 100% rename from src/i18n/locale/tr.json rename to public/locales/tr.json diff --git a/src/i18n/locale/uk.json b/public/locales/uk.json similarity index 100% rename from src/i18n/locale/uk.json rename to public/locales/uk.json diff --git a/src/i18n/locale/vi.json b/public/locales/vi.json similarity index 100% rename from src/i18n/locale/vi.json rename to public/locales/vi.json diff --git a/src/i18n/locale/zh_Hans.json b/public/locales/zh_Hans.json similarity index 100% rename from src/i18n/locale/zh_Hans.json rename to public/locales/zh_Hans.json diff --git a/src/i18n/locale/zh_Hant.json b/public/locales/zh_Hant.json similarity index 100% rename from src/i18n/locale/zh_Hant.json rename to public/locales/zh_Hant.json diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 55adac1465..4f038ace96 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -9,14 +9,42 @@ import { use } from 'i18next'; import { initReactI18next } from 'react-i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; -import { resources } from '@/i18n/translations'; +import HttpBackend from 'i18next-http-backend'; + +/** + * Keys have to match {@link ISOLanguages} codes, they're used for showing the language name in the dropdown in the {@link Settings}.
+ * In case there is no language code for the key in {@link ISOLanguages}, the corresponding language has to be added + */ +export const i18nResources = [ + 'ar', + 'de', + 'en', + 'es', + 'fr', + 'id', + 'it', + 'ja', + 'ko', + 'nb_NO', + 'pt', + 'sv', + 'uk', + 'vi', + 'zh_Hans', + 'zh_Hant', +]; export const i18n = use(initReactI18next) + .use(HttpBackend) .use(LanguageDetector) .init({ - resources, - fallbackLng: 'en', + + backend: { + loadPath: '/locales/{{lng}}.json', + allowMultiLoading: true, + }, + interpolation: { escapeValue: false, format: (value, format) => { @@ -28,6 +56,7 @@ export const i18n = use(initReactI18next) } }, }, + returnNull: false, debug: process.env.NODE_ENV !== 'production', }); diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts deleted file mode 100644 index 0904db5d64..0000000000 --- a/src/i18n/translations.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) Contributors to the Suwayomi project - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -import ar from '@/i18n/locale/ar.json'; -import de from '@/i18n/locale/de.json'; -import en from '@/i18n/locale/en.json'; // default language -import es from '@/i18n/locale/es.json'; -import fr from '@/i18n/locale/fr.json'; -import id from '@/i18n/locale/id.json'; -import it from '@/i18n/locale/it.json'; -import ja from '@/i18n/locale/ja.json'; -import ko from '@/i18n/locale/ko.json'; -import nb_NO from '@/i18n/locale/nb-NO.json'; -import pt from '@/i18n/locale/pt.json'; -import sv from '@/i18n/locale/sv.json'; -import tr from '@/i18n/locale/tr.json'; -import uk from '@/i18n/locale/uk.json'; -import vi from '@/i18n/locale/vi.json'; -import zh_Hans from '@/i18n/locale/zh_Hans.json'; -import zh_Hant from '@/i18n/locale/zh_Hant.json'; - -const translationHelper = (lng: T) => ({ - translation: lng, -}); - -/** - * Keys have to match {@link ISOLanguages} codes, they're used for showing the language name in the dropdown in the {@link Settings}.
- * In case there is no language code for the key in {@link ISOLanguages}, the corresponding language has to be added - */ -export const resources = { - ar: translationHelper(ar), - de: translationHelper(de), - en: translationHelper(en), // default language - es: translationHelper(es), - fr: translationHelper(fr), - id: translationHelper(id), - it: translationHelper(it), - ja: translationHelper(ja), - ko: translationHelper(ko), - 'nb-NO': translationHelper(nb_NO), - pt: translationHelper(pt), - sv: translationHelper(sv), - tr: translationHelper(tr), - uk: translationHelper(uk), - vi: translationHelper(vi), - 'zh-Hans': translationHelper(zh_Hans), - 'zh-Hant': translationHelper(zh_Hant), -} as const; diff --git a/src/screens/Settings.tsx b/src/screens/Settings.tsx index 65132716ee..7eed2f789a 100644 --- a/src/screens/Settings.tsx +++ b/src/screens/Settings.tsx @@ -40,6 +40,7 @@ import { NumberSetting } from '@/components/settings/NumberSetting.tsx'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { makeToast } from '@/components/util/Toast.tsx'; import { Select } from '@/components/atoms/Select.tsx'; +import { i18nResources } from '@/i18n'; export function Settings() { const { t, i18n } = useTranslation(); @@ -149,7 +150,7 @@ export function Settings() { value={i18n.language} onChange={({ target: { value: language } }) => i18n.changeLanguage(language)} > - {Object.keys(i18n.services.resourceStore.data).map((language) => ( + {i18nResources.map((language) => ( {langCodeToName(language)} diff --git a/yarn.lock b/yarn.lock index b27fcd6905..8dbfb0f14f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3386,6 +3386,13 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" + integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== + dependencies: + node-fetch "^2.6.12" + cross-fetch@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" @@ -4548,6 +4555,13 @@ i18next-browser-languagedetector@7.2.1: dependencies: "@babel/runtime" "^7.23.2" +i18next-http-backend@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-2.5.0.tgz#8396a7df30bfe722eff7a65f629df32a61720414" + integrity sha512-Z/aQsGZk1gSxt2/DztXk92DuDD20J+rNudT7ZCdTrNOiK8uQppfvdjq9+DFQfpAnFPn3VZS+KQIr1S/W1KxhpQ== + dependencies: + cross-fetch "4.0.0" + i18next@23.11.1: version "23.11.1" resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.11.1.tgz#8e384b6ad7d6ba70c40cb86e020438251a5ff8b1"