* refactor(channels): own setup and instance contracts * refactor(channels): isolate management contracts * refactor(channels): normalize activation contracts * fix(channels): enforce management contracts * refactor(channels): finish setup ownership migration * fix(channels): harden management contracts * fix(channels): enforce lazy loading and runtime ownership * fix(feishu): make multi-instance startup idempotent * fix(webui): render channel setup contracts cleanly * fix(feishu): stop websocket clients cleanly * fix(channels): enforce persistence and activation gates * fix(channels): preserve global feature action scope * fix(channels): apply defaults for single plugins * fix(channels): enforce management contract boundaries * refactor(feishu): remove identity helper indirection * fix(channels): preserve management setup contracts * refactor(channels): generalize instance settings UI * refactor(channels): package channel plugins with web UI metadata * refactor(channels): make built-ins self-contained packages * test(channels): colocate tests with channel packages * fix(dingtalk): use official brand icon * feat(channels): colocate webui translations * docs(channels): clarify plugin ownership * test(exec): remove output wait race * refactor(channels): unify plugin descriptors * fix(channels): enforce descriptor-owned contracts * refactor(channels): finish package-owned plugin setup * refactor(channels): use repository-owned packages only * fix(channels): self-describe dependencies and runtime state * fix(channels): warn about legacy entry points
80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import i18n from "i18next";
|
|
import { initReactI18next } from "react-i18next";
|
|
|
|
import {
|
|
channelLocaleNamespaces,
|
|
channelLocaleResources,
|
|
} from "@/channel-plugins/locale-registry";
|
|
|
|
import {
|
|
applyDocumentLocale,
|
|
defaultLocale,
|
|
fallbackLocale,
|
|
LOCALE_STORAGE_KEY,
|
|
normalizeLocale,
|
|
persistLocale,
|
|
resolveInitialLocale,
|
|
type SupportedLocale,
|
|
} from "./config";
|
|
|
|
import enCommon from "./locales/en/common.json";
|
|
import zhCNCommon from "./locales/zh-CN/common.json";
|
|
import zhTWCommon from "./locales/zh-TW/common.json";
|
|
import frCommon from "./locales/fr/common.json";
|
|
import jaCommon from "./locales/ja/common.json";
|
|
import koCommon from "./locales/ko/common.json";
|
|
import esCommon from "./locales/es/common.json";
|
|
import ptBRCommon from "./locales/pt-BR/common.json";
|
|
import viCommon from "./locales/vi/common.json";
|
|
import idCommon from "./locales/id/common.json";
|
|
|
|
export const resources = {
|
|
en: { common: enCommon, ...channelLocaleResources("en") },
|
|
"zh-CN": { common: zhCNCommon, ...channelLocaleResources("zh-CN") },
|
|
"zh-TW": { common: zhTWCommon, ...channelLocaleResources("zh-TW") },
|
|
fr: { common: frCommon, ...channelLocaleResources("fr") },
|
|
ja: { common: jaCommon, ...channelLocaleResources("ja") },
|
|
ko: { common: koCommon, ...channelLocaleResources("ko") },
|
|
es: { common: esCommon, ...channelLocaleResources("es") },
|
|
"pt-BR": { common: ptBRCommon, ...channelLocaleResources("pt-BR") },
|
|
vi: { common: viCommon, ...channelLocaleResources("vi") },
|
|
id: { common: idCommon, ...channelLocaleResources("id") },
|
|
} as const;
|
|
|
|
export function currentLocale(): SupportedLocale {
|
|
return normalizeLocale(i18n.resolvedLanguage ?? i18n.language ?? defaultLocale);
|
|
}
|
|
|
|
export async function setAppLanguage(locale: SupportedLocale): Promise<void> {
|
|
await i18n.changeLanguage(locale);
|
|
}
|
|
|
|
if (!i18n.isInitialized) {
|
|
void i18n
|
|
.use(initReactI18next)
|
|
.init({
|
|
resources,
|
|
lng: resolveInitialLocale(),
|
|
fallbackLng: fallbackLocale,
|
|
defaultNS: "common",
|
|
ns: ["common", ...channelLocaleNamespaces()],
|
|
interpolation: {
|
|
escapeValue: false,
|
|
},
|
|
returnNull: false,
|
|
supportedLngs: Object.keys(resources),
|
|
});
|
|
}
|
|
|
|
const syncLocaleSideEffects = (language: string) => {
|
|
const locale = normalizeLocale(language);
|
|
applyDocumentLocale(locale);
|
|
persistLocale(locale);
|
|
};
|
|
|
|
syncLocaleSideEffects(currentLocale());
|
|
i18n.on("languageChanged", syncLocaleSideEffects);
|
|
|
|
export { LOCALE_STORAGE_KEY };
|
|
export default i18n;
|