refactor(i18n): clean up code structure and improve readability

This commit is contained in:
WTW0313 2025-09-11 10:53:40 +08:00
parent bb6b663ef4
commit b146f5d3fa
2 changed files with 69 additions and 76 deletions

View File

@ -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) => { export const useMixedTranslation = (localeFromOuter?: string) => {
let t = useTranslation().t let t = useTranslation().t
// !localeFromOuter only support zh-Hans and en-US for now
if (localeFromOuter) if (localeFromOuter)
t = i18n.getFixedT(localeFromOuter) t = i18n.getFixedT(localeFromOuter)

View File

@ -1,101 +1,91 @@
"use client"; 'use client'
import i18n from "i18next"; import i18n from 'i18next'
import { camelCase } from "lodash-es"; import { camelCase } from 'lodash-es'
import { initReactI18next } from "react-i18next"; import { initReactI18next } from 'react-i18next'
const requireSilent = async (lang: string, namespace: string) => { const requireSilent = async (lang: string, namespace: string) => {
let res; let res
try { try {
res = (await import(`../i18n/${lang}/${namespace}`)).default; res = (await import(`../i18n/${lang}/${namespace}`)).default
} catch { }
res = (await import(`../i18n/en-US/${namespace}`)).default; catch {
res = (await import(`../i18n/en-US/${namespace}`)).default
} }
return res; return res
}; }
const NAMESPACES = [ const NAMESPACES = [
"app-annotation", 'app-annotation',
"app-api", 'app-api',
"app-debug", 'app-debug',
"app-log", 'app-log',
"app-overview", 'app-overview',
"app", 'app',
"billing", 'billing',
"common", 'common',
"custom", 'custom',
"dataset-creation", 'dataset-creation',
"dataset-documents", 'dataset-documents',
"dataset-hit-testing", 'dataset-hit-testing',
"dataset-pipeline", 'dataset-pipeline',
"dataset-settings", 'dataset-settings',
"dataset", 'dataset',
"education", 'education',
"explore", 'explore',
"layout", 'layout',
"login", 'login',
"oauth", 'oauth',
"pipeline", 'pipeline',
"plugin-tags", 'plugin-tags',
"plugin", 'plugin',
"register", 'register',
"run-log", 'run-log',
"share", 'share',
"time", 'time',
"tools", 'tools',
"workflow", 'workflow',
]; ]
export const loadLangResources = async (lang: string) => { export const loadLangResources = async (lang: string) => {
const modules = await Promise.all( const modules = await Promise.all(
NAMESPACES.map((ns) => requireSilent(lang, ns)) NAMESPACES.map(ns => requireSilent(lang, ns)),
); )
const resources = modules.reduce((acc, mod, index) => { const resources = modules.reduce((acc, mod, index) => {
acc[camelCase(NAMESPACES[index])] = mod; acc[camelCase(NAMESPACES[index])] = mod
return acc; return acc
}, {} as Record<string, any>); }, {} as Record<string, any>)
return resources; return resources
}; }
/** // Load en-US resources first to make sure fallback works
* !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
*/
const getInitialTranslations = () => { const getInitialTranslations = () => {
const en_USResources = NAMESPACES.reduce((acc, ns, index) => { const en_USResources = NAMESPACES.reduce((acc, ns, index) => {
acc[camelCase(NAMESPACES[index])] = require(`../i18n/en-US/${ns}`).default; acc[camelCase(NAMESPACES[index])] = require(`../i18n/en-US/${ns}`).default
return acc; return acc
}, {} as Record<string, any>); }, {} as Record<string, any>)
const zh_HansResources = NAMESPACES.reduce((acc, ns, index) => {
acc[camelCase(NAMESPACES[index])] =
require(`../i18n/zh-Hans/${ns}`).default;
return acc;
}, {} as Record<string, any>);
return { return {
"en-US": { 'en-US': {
translation: en_USResources, translation: en_USResources,
}, },
"zh-Hans": { }
translation: zh_HansResources, }
},
};
};
if (!i18n.isInitialized) { if (!i18n.isInitialized) {
i18n.use(initReactI18next).init({ i18n.use(initReactI18next).init({
lng: undefined, lng: undefined,
fallbackLng: "en-US", fallbackLng: 'en-US',
resources: getInitialTranslations(), resources: getInitialTranslations(),
}); })
} }
export const changeLanguage = async (lng?: string) => { export const changeLanguage = async (lng?: string) => {
if (!lng) return; if (!lng) return
const resource = await loadLangResources(lng); if (!i18n.hasResourceBundle(lng, 'translation')) {
if (!i18n.hasResourceBundle(lng, "translation")) const resource = await loadLangResources(lng)
i18n.addResourceBundle(lng, "translation", resource, true, true); i18n.addResourceBundle(lng, 'translation', resource, true, true)
await i18n.changeLanguage(lng); }
}; await i18n.changeLanguage(lng)
}
export default i18n; export default i18n