2026-04-24 02:31:42 +02:00
|
|
|
import en from './locales/en'
|
|
|
|
|
|
2026-05-14 12:39:36 +08:00
|
|
|
export type LocaleMessages = Record<string, any>
|
2026-04-24 02:31:42 +02:00
|
|
|
|
2026-05-14 12:39:36 +08:00
|
|
|
export const supportedLocales = ['en', 'zh', 'zh-TW', 'ja', 'ko', 'fr', 'es', 'de', 'pt'] as const
|
|
|
|
|
export type SupportedLocale = (typeof supportedLocales)[number]
|
2026-04-24 02:31:42 +02:00
|
|
|
|
|
|
|
|
function isPlainObject(value: unknown): value is LocaleMessages {
|
|
|
|
|
return !!value && typeof value === 'object' && !Array.isArray(value)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function mergeMessagesWithFallback(
|
|
|
|
|
fallback: LocaleMessages,
|
|
|
|
|
locale: LocaleMessages,
|
|
|
|
|
): LocaleMessages {
|
|
|
|
|
const merged: LocaleMessages = { ...fallback }
|
|
|
|
|
|
|
|
|
|
for (const [key, value] of Object.entries(locale)) {
|
|
|
|
|
const fallbackValue = fallback[key]
|
|
|
|
|
merged[key] = isPlainObject(fallbackValue) && isPlainObject(value)
|
|
|
|
|
? mergeMessagesWithFallback(fallbackValue, value)
|
|
|
|
|
: value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return merged
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-14 12:39:36 +08:00
|
|
|
const localeLoaders: Record<string, () => Promise<{ default: LocaleMessages }>> = {
|
|
|
|
|
'zh': () => import('./locales/zh'),
|
|
|
|
|
'zh-TW': () => import('./locales/zh-TW'),
|
|
|
|
|
'ja': () => import('./locales/ja'),
|
|
|
|
|
'ko': () => import('./locales/ko'),
|
|
|
|
|
'fr': () => import('./locales/fr'),
|
|
|
|
|
'es': () => import('./locales/es'),
|
|
|
|
|
'de': () => import('./locales/de'),
|
|
|
|
|
'pt': () => import('./locales/pt'),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export { en }
|
|
|
|
|
|
|
|
|
|
export async function loadLocale(locale: string): Promise<LocaleMessages | null> {
|
|
|
|
|
if (locale === 'en') return en
|
|
|
|
|
|
|
|
|
|
const loader = localeLoaders[locale]
|
|
|
|
|
if (!loader) return null
|
|
|
|
|
|
|
|
|
|
const mod = await loader()
|
|
|
|
|
return mergeMessagesWithFallback(en, mod.default)
|
|
|
|
|
}
|