diff --git a/package.json b/package.json index 4bc0e57..d84e9c1 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,6 @@ "bin": { "deriv-extract-translations": "./dist/deriv-extract-translations.cjs" }, - "exports": { - ".": { - "import": "./dist/index.js", - "types": "./dist/index.d.ts" - } - }, "private": false, "version": "1.2.4", "scripts": { diff --git a/src/index.ts b/src/index.ts index 0fba571..3dda466 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,8 @@ export { localize, getInitialLanguage, loadIncontextTranslation, - initializeI18n + getAllowedLanguages, + initializeI18n, } from "@utils/index"; export { Localize } from "@components/index"; export { useTranslations } from "@hooks/index"; diff --git a/src/provider/translation-provider.tsx b/src/provider/translation-provider.tsx index 1238ca6..f3f93b6 100644 --- a/src/provider/translation-provider.tsx +++ b/src/provider/translation-provider.tsx @@ -33,10 +33,7 @@ export default function TranslationProvider({ if (i18nInstance) { const initialLang = i18nInstance.language || defaultLang || ""; setCurrentLanguage(initialLang); - - i18nInstance.on("initialized", () => { - setIsTranslationsLoaded(true); - }); + setIsTranslationsLoaded(true); } }, [i18nInstance, defaultLang]); diff --git a/src/utils/__tests__/lang-utils.spec.ts b/src/utils/__tests__/lang-utils.spec.ts new file mode 100644 index 0000000..4fb3f4f --- /dev/null +++ b/src/utils/__tests__/lang-utils.spec.ts @@ -0,0 +1,19 @@ +import { ALL_LANGUAGES } from "../constants"; +import { getAllowedLanguages } from "../lang-utils"; + +describe("getAllowedLanguages", () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { ACH, ...languageList } = ALL_LANGUAGES; + + it("should return all languages if no excluded languages are provided", () => { + const allowedLanguages = getAllowedLanguages(); + expect(allowedLanguages).toEqual(languageList); + }); + + it("should return all languages except the excluded languages (ex: ID)", () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { ID, ...filteredLanguages } = languageList; + const allowedLanguages = getAllowedLanguages(["ID"]); + expect(allowedLanguages).toEqual(filteredLanguages); + }); +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index efdcae2..51c35cd 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,20 +1,24 @@ export const ALL_LANGUAGES = Object.freeze({ ACH: "Translations", EN: "English", - ES: "Español", + AR: "العربية", + BN: "বাংলা", DE: "Deutsch", + ES: "Español", FR: "Français", ID: "Indonesian", IT: "Italiano", + SW: "Kiswahili", KO: "한국어", PL: "Polish", PT: "Português", RU: "Русский", + SI: "සිංහල", + TH: "ไทย", TR: "Türkçe", VI: "Tiếng Việt", ZH_CN: "简体中文", ZH_TW: "繁體中文", - TH: "ไทย", }); export const LANGUAGE_KEY = "i18n_language"; diff --git a/src/utils/initialize-i18n.ts b/src/utils/initialize-i18n.ts index e8809dd..2b26991 100644 --- a/src/utils/initialize-i18n.ts +++ b/src/utils/initialize-i18n.ts @@ -1,29 +1,42 @@ -import i18next from "i18next"; +import i18next, { InitOptions } from "i18next"; import { str as crc32 } from "crc-32"; import { OtaSdk } from "@utils/index"; import { initReactI18next } from "react-i18next"; import { getInitialLanguage } from "@utils/index"; -const i18n_config = { +type TInstanceConfig = { + useSuspense?: Exclude["useSuspense"]; + enableDebug?: InitOptions["debug"]; +}; + +const setI18Config = ({ useSuspense, enableDebug }: TInstanceConfig) => ({ react: { hashTransKey(defaultValue: string) { return crc32(defaultValue); }, - useSuspense: true, + useSuspense, }, - debug: false, + debug: enableDebug, initImmediate: true, fallbackLng: "EN", interpolation: { escapeValue: false, }, -}; +}); -export default function initializeI18n({ cdnUrl }: { cdnUrl: string }) { +export default function initializeI18n({ + cdnUrl, + useSuspense = true, + enableDebug = false, +}: { + cdnUrl: string; +} & TInstanceConfig) { const module = new OtaSdk(cdnUrl); const initial_language = getInitialLanguage(); + const i18n_config = setI18Config({ useSuspense, enableDebug }); + i18next .use(module) .use(initReactI18next) diff --git a/src/utils/lang-utils.ts b/src/utils/lang-utils.ts index ea3067a..aa5f8a7 100644 --- a/src/utils/lang-utils.ts +++ b/src/utils/lang-utils.ts @@ -1,5 +1,7 @@ import { constants } from "@utils/index"; +type LanguageCode = keyof typeof constants.ALL_LANGUAGES; + export const getInitialLanguage = () => { const url_params = new URLSearchParams(window.location.search); const query_lang = url_params.get("lang"); @@ -18,9 +20,7 @@ export const getInitialLanguage = () => { return constants.DEFAULT_LANGUAGE; }; -export const loadIncontextTranslation = ( - lang: keyof typeof constants.ALL_LANGUAGES -) => { +export const loadIncontextTranslation = (lang: LanguageCode) => { const is_ach = lang.toUpperCase() === "ACH"; if (is_ach) { const jipt = document.createElement("script"); @@ -34,3 +34,22 @@ export const loadIncontextTranslation = ( document.head.appendChild(jipt); } }; + +/** + * Filter out unsupported languages and return an Object containing language code and language name + * @param excludedLanguages + * @returns Object containing language code and language name + */ +export const getAllowedLanguages = ( + excludedLanguages: Omit[] = [] +) => { + const unsupportedLanguages = ["ACH", ...excludedLanguages]; + const languageList = Object.keys(constants.ALL_LANGUAGES) + .filter((key) => !unsupportedLanguages.includes(key)) + .reduce((obj: { [key: string]: string }, key) => { + obj[key] = constants.ALL_LANGUAGES[key as LanguageCode]; + return obj; + }, {}); + + return languageList; +}; diff --git a/vite.config.ts b/vite.config.ts index 0fe3506..21bb682 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -15,7 +15,7 @@ export default defineConfig({ formats: ["es"], }, rollupOptions: { - external: ["react", "react-dom", "react/jsx-runtime", "react-dom/client"], + external: ["react", "react-dom", "react-dom/client"], output: { assetFileNames: "assets/[name]", entryFileNames: "[name].js",