diff --git a/web/app/components/plugins/marketplace/hooks.ts b/web/app/components/plugins/marketplace/hooks.ts index 45a113030f..10aead17c4 100644 --- a/web/app/components/plugins/marketplace/hooks.ts +++ b/web/app/components/plugins/marketplace/hooks.ts @@ -106,10 +106,13 @@ export const useMarketplacePlugins = () => { } } +/** + * ! Support zh-Hans, pt-BR, ja-JP and en-US for Marketplace page + * ! For other languages, use en-US as fallback + */ export const useMixedTranslation = (localeFromOuter?: string) => { let t = useTranslation().t - // !localeFromOuter only support zh-Hans and en-US for now if (localeFromOuter) t = i18n.getFixedT(localeFromOuter) diff --git a/web/i18n-config/i18next-config.ts b/web/i18n-config/i18next-config.ts index 2055d29ba9..af04802e42 100644 --- a/web/i18n-config/i18next-config.ts +++ b/web/i18n-config/i18next-config.ts @@ -1,101 +1,91 @@ -"use client"; -import i18n from "i18next"; -import { camelCase } from "lodash-es"; -import { initReactI18next } from "react-i18next"; +'use client' +import i18n from 'i18next' +import { camelCase } from 'lodash-es' +import { initReactI18next } from 'react-i18next' const requireSilent = async (lang: string, namespace: string) => { - let res; + let res try { - res = (await import(`../i18n/${lang}/${namespace}`)).default; - } catch { - res = (await import(`../i18n/en-US/${namespace}`)).default; + res = (await import(`../i18n/${lang}/${namespace}`)).default + } + catch { + res = (await import(`../i18n/en-US/${namespace}`)).default } - return res; -}; + return res +} const NAMESPACES = [ - "app-annotation", - "app-api", - "app-debug", - "app-log", - "app-overview", - "app", - "billing", - "common", - "custom", - "dataset-creation", - "dataset-documents", - "dataset-hit-testing", - "dataset-pipeline", - "dataset-settings", - "dataset", - "education", - "explore", - "layout", - "login", - "oauth", - "pipeline", - "plugin-tags", - "plugin", - "register", - "run-log", - "share", - "time", - "tools", - "workflow", -]; + 'app-annotation', + 'app-api', + 'app-debug', + 'app-log', + 'app-overview', + 'app', + 'billing', + 'common', + 'custom', + 'dataset-creation', + 'dataset-documents', + 'dataset-hit-testing', + 'dataset-pipeline', + 'dataset-settings', + 'dataset', + 'education', + 'explore', + 'layout', + 'login', + 'oauth', + 'pipeline', + 'plugin-tags', + 'plugin', + 'register', + 'run-log', + 'share', + 'time', + 'tools', + 'workflow', +] export const loadLangResources = async (lang: string) => { const modules = await Promise.all( - NAMESPACES.map((ns) => requireSilent(lang, ns)) - ); + NAMESPACES.map(ns => requireSilent(lang, ns)), + ) const resources = modules.reduce((acc, mod, index) => { - acc[camelCase(NAMESPACES[index])] = mod; - return acc; - }, {} as Record); - return resources; -}; + acc[camelCase(NAMESPACES[index])] = mod + return acc + }, {} as Record) + return resources +} -/** - * !Need to load en-US and zh-Hans resources for initial rendering, which are used in both marketplace and dify - * !Other languages will be loaded on demand - * !This is to avoid loading all languages at once which can be slow - */ +// Load en-US resources first to make sure fallback works const getInitialTranslations = () => { const en_USResources = NAMESPACES.reduce((acc, ns, index) => { - acc[camelCase(NAMESPACES[index])] = require(`../i18n/en-US/${ns}`).default; - return acc; - }, {} as Record); - const zh_HansResources = NAMESPACES.reduce((acc, ns, index) => { - acc[camelCase(NAMESPACES[index])] = - require(`../i18n/zh-Hans/${ns}`).default; - return acc; - }, {} as Record); + acc[camelCase(NAMESPACES[index])] = require(`../i18n/en-US/${ns}`).default + return acc + }, {} as Record) return { - "en-US": { + 'en-US': { translation: en_USResources, }, - "zh-Hans": { - translation: zh_HansResources, - }, - }; -}; + } +} if (!i18n.isInitialized) { i18n.use(initReactI18next).init({ lng: undefined, - fallbackLng: "en-US", + fallbackLng: 'en-US', resources: getInitialTranslations(), - }); + }) } export const changeLanguage = async (lng?: string) => { - if (!lng) return; - const resource = await loadLangResources(lng); - if (!i18n.hasResourceBundle(lng, "translation")) - i18n.addResourceBundle(lng, "translation", resource, true, true); - await i18n.changeLanguage(lng); -}; + if (!lng) return + if (!i18n.hasResourceBundle(lng, 'translation')) { + const resource = await loadLangResources(lng) + i18n.addResourceBundle(lng, 'translation', resource, true, true) + } + await i18n.changeLanguage(lng) +} -export default i18n; +export default i18n