import { createI18n } from 'vue-i18n' import type { I18n, I18nOptions } from 'vue-i18n' import en from '../../../lang/en.json' /** * Locale-to-filename mapping for language files whose filename does * not match the locale code exactly. */ const LOCALE_FILE_MAP: Record = { zh_CN: 'zh-cn', pt_BR: 'pt-br', } /** Tracks which languages have already been loaded. */ const loadedLanguages = new Set(['en']) /** In-memory cache of loaded message objects keyed by locale. */ const languageCache = new Map>() /** * Dynamically import a language JSON file for a given locale. */ async function loadLanguageMessages( locale: string ): Promise> { if (languageCache.has(locale)) { return languageCache.get(locale)! } // English is already statically imported — no dynamic import needed if (locale === 'en') { const messages = en as unknown as Record languageCache.set('en', messages) return messages } const fileName = LOCALE_FILE_MAP[locale] ?? locale try { const mod: { default: Record } = await import( `../../../lang/${fileName}.json` ) const messages = mod.default ?? mod languageCache.set(locale, messages) loadedLanguages.add(locale) return messages } catch (error: unknown) { console.warn(`Failed to load language: ${locale}`, error) // Fall back to English if (locale !== 'en' && !languageCache.has('en')) { try { const fallback: { default: Record } = await import( '../../../lang/en.json' ) const fallbackMessages = fallback.default ?? fallback languageCache.set('en', fallbackMessages) return fallbackMessages } catch (fallbackError: unknown) { console.error('Failed to load fallback language (en)', fallbackError) return {} } } return languageCache.get('en') ?? {} } } /** * Load a language and activate it on the given i18n instance. */ export async function setI18nLanguage( i18n: I18n, Record, Record, string, false>, locale: string ): Promise { if (!loadedLanguages.has(locale)) { const messages = await loadLanguageMessages(locale) i18n.global.setLocaleMessage(locale, messages) } i18n.global.locale.value = locale } /** * Check whether a language has already been loaded. */ export function isLanguageLoaded(locale: string): boolean { return loadedLanguages.has(locale) } /** Type alias for the i18n instance created by this module. */ export type AppI18n = I18n< Record, Record, Record, string, false > /** * Create and return the vue-i18n plugin instance. * * Only the English bundle is included synchronously; all other * languages are loaded on demand via `setI18nLanguage`. */ export function createAppI18n( extraMessages?: Record> ): AppI18n { const messages: Record> = { en: en as unknown as Record, ...extraMessages, } const options: I18nOptions = { legacy: false, locale: 'en', fallbackLocale: 'en', globalInjection: true, messages, } return createI18n(options) as AppI18n }