/** * runtime.js —— 只装配 vue-i18n(设 fallback='en')+ setLocale/getLocale。 * 不读 env、不发网络;locale 初值由调用方注入。 */ import { createI18n as createVueI18n } from 'vue-i18n' import { messages } from './messages/index.js' import { SUPPORTED_LOCALES, DEFAULT_LOCALE, LOCALE_META, isSupportedLocale } from './locales.js' /** * @typedef {import('./locales.js').LocaleCode} LocaleCode * @typedef {import('./locales.js').LocaleMeta} LocaleMeta */ /** * @typedef {object} CreateI18nOptions * @property {LocaleCode} [locale] 初值(注入);缺省 `'en'`。非法值回落 `'en'`。 * @property {LocaleCode} [fallbackLocale] 缺省 `'en'`(英语第一公民)。 */ /** * @typedef {object} I18nRuntime * @property {import('vue-i18n').I18n} i18n vue-i18n 实例,`app.use(i18n)`。 * @property {(code: LocaleCode) => void} setLocale 切换当前 locale(非法值回落 fallback)。 * @property {() => LocaleCode} getLocale 读当前 locale(供 api-sdk 取 `x-locale`)。 * @property {LocaleMeta[]} locales 语言元数据数组(供渲染切换器)。 */ /** * 唯一入口工厂:装配 vue-i18n 运行时。 * @param {CreateI18nOptions} [opts] * @returns {I18nRuntime} */ export function createI18n(opts = {}) { const fallbackLocale = isSupportedLocale(opts.fallbackLocale) ? opts.fallbackLocale : DEFAULT_LOCALE const initialLocale = isSupportedLocale(opts.locale) ? opts.locale : fallbackLocale const i18n = createVueI18n( /** @type {any} */ ({ legacy: false, // Composition API 模式 locale: initialLocale, fallbackLocale, // 缺失 key 自动回落 en,不显示原始 key、不抛错 fallbackWarn: false, missingWarn: false, messages, availableLocales: SUPPORTED_LOCALES, }), ) // legacy:false 下 `i18n.global.locale` 是一个 ref;vue-i18n 重载类型在 // checkJs 下无法精确推断该分支,故对 global 取一次窄化引用集中处理。 const composer = /** @type {{ locale: { value: LocaleCode } }} */ ( /** @type {unknown} */ (i18n.global) ) /** @param {LocaleCode} code */ function setLocale(code) { const next = isSupportedLocale(code) ? code : fallbackLocale composer.locale.value = next } /** @returns {LocaleCode} */ function getLocale() { return composer.locale.value } return { i18n, setLocale, getLocale, locales: LOCALE_META } }