From dd280b2c0c9a4f47b6954c460b3c39b3fbfbdd99 Mon Sep 17 00:00:00 2001 From: Khavin Shankar Date: Sat, 25 Jan 2025 16:38:50 +0530 Subject: [PATCH] added i18n support for plugins --- care.config.ts | 1 + package-lock.json | 18 +++++++++++++---- package.json | 3 ++- src/i18n.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/care.config.ts b/care.config.ts index 0721552b888..6c2e4249fc5 100644 --- a/care.config.ts +++ b/care.config.ts @@ -121,6 +121,7 @@ const careConfig = { careApps: env.REACT_ENABLED_APPS ? env.REACT_ENABLED_APPS.split(",").map((app) => ({ branch: app.split("@")[1], + name: app.split("@")[0].split("/")[1], package: app.split("@")[0], })) : [], diff --git a/package-lock.json b/package-lock.json index 477129c9df9..94da428724a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,6 +62,7 @@ "i18next": "^24.2.1", "i18next-browser-languagedetector": "^8.0.2", "i18next-http-backend": "^3.0.1", + "i18next-resources-to-backend": "^1.2.1", "input-otp": "^1.4.2", "lodash-es": "^4.17.21", "lucide-react": "^0.473.0", @@ -100,7 +101,7 @@ "@types/google.maps": "^3.58.1", "@types/jsdom": "^21.1.7", "@types/markdown-it": "^14.1.2", - "@types/node": "^22.9.0", + "@types/node": "^22.10.10", "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-csv": "^1.1.10", @@ -6738,9 +6739,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "22.10.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz", + "integrity": "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==", "devOptional": true, "license": "MIT", "dependencies": { @@ -11824,6 +11825,15 @@ "cross-fetch": "4.0.0" } }, + "node_modules/i18next-resources-to-backend": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/i18next-resources-to-backend/-/i18next-resources-to-backend-1.2.1.tgz", + "integrity": "sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", diff --git a/package.json b/package.json index 03bdd34ae2c..7dd42f153de 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "i18next": "^24.2.1", "i18next-browser-languagedetector": "^8.0.2", "i18next-http-backend": "^3.0.1", + "i18next-resources-to-backend": "^1.2.1", "input-otp": "^1.4.2", "lodash-es": "^4.17.21", "lucide-react": "^0.473.0", @@ -138,7 +139,7 @@ "@types/google.maps": "^3.58.1", "@types/jsdom": "^21.1.7", "@types/markdown-it": "^14.1.2", - "@types/node": "^22.9.0", + "@types/node": "^22.10.10", "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-csv": "^1.1.10", diff --git a/src/i18n.ts b/src/i18n.ts index 0b3cf7ab7b7..9093a4858c1 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -1,6 +1,8 @@ +import careConfig from "@careConfig"; import i18n from "i18next"; import LanguageDetector from "i18next-browser-languagedetector"; import HttpApi from "i18next-http-backend"; +import resourcesToBackend from "i18next-resources-to-backend"; import { initReactI18next } from "react-i18next"; export const LANGUAGES = { @@ -12,21 +14,63 @@ export const LANGUAGES = { hi: "हिन्दी", } as const; +function toURL(input: string) { + input = input.trim(); + if (!input.startsWith("http://") && !input.startsWith("https://")) { + if (input.startsWith("localhost")) { + return `http://${input}`; + } else { + return `https://${input}`; + } + } + return input; +} + +const namespaceToUrl = (namespace: string) => { + const careApp = careConfig.careApps.find((app) => app.name === namespace); + + if (!careApp) { + return ""; + } + + return toURL(careApp.branch); +}; + i18n .use(HttpApi) .use(initReactI18next) .use(LanguageDetector) + .use( + resourcesToBackend((language, namespace, callback) => { + fetch(`${namespaceToUrl(namespace)}/locale/${language}.json`) + .then((response) => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then((resources) => { + callback(null, resources); + }) + .catch((error) => { + console.error( + `Failed to load translations for ${language}/${namespace}:`, + error, + ); + callback(error, null); + }); + }), + ) .init({ - backend: { - loadPath: "/locale/{{lng}}.json", - }, fallbackLng: "en", + ns: ["care_fe", ...careConfig.careApps.map((app) => app.name)], load: "currentOnly", supportedLngs: Object.keys(LANGUAGES), interpolation: { escapeValue: false, skipOnVariables: false, }, + defaultNS: "care_fe", }); export default i18n;