语言分包与按需加载

默认情况下,ai-i18n 会把所有目标语言注册到同一个 Runtime。配置 loading 后,每个目标 locale 会生成独立的 Vite chunk;未提前加载的语言会在首次 setLang() 时按需加载。

配置分包策略

// vite.config.ts
import { aiI18n } from '@ai-i18n/vite';

aiI18n({
  sourceLang: 'zh-CN', // source locale 同步可用,不生成独立语言 chunk
  // value 是语言标识,label 是界面中的展示名称。
  locales: [
    { value: 'zh-CN', label: '中文' },
    { value: 'en-US', label: 'English' },
    { value: 'ja-JP', label: '日本語' },
    { value: 'fr-FR', label: 'Français' },
  ],
  loading: {
    // 启用按 locale 分包并声明资源加载提示
    preload: ['en-US'], // 通过 modulepreload 尽早准备
    prefetch: ['ja-JP'], // 通过 prefetch 低优先级缓存
  },
});
语言加载方式
zh-CNsource locale,不生成语言 chunk
en-US通过 modulepreload 尽早准备;非 source 的 defaultLang 也会自动 preload
ja-JP通过 prefetch 提示浏览器低优先级缓存
fr-FR首次调用 setLang('fr-FR') 时加载

modulepreloadprefetch 都是浏览器调度提示,不保证资源在某个时刻已经完成下载。

如果 defaultLang 保持 source,并希望所有目标语言都在切换时再加载,只需传入空对象:

aiI18n({
  sourceLang: 'zh-CN', // 默认语言保持 source
  locales, // 复用上方完整语言列表
  loading: {}, // 启用分包,其他目标语言首次 setLang() 时再加载
});

省略 loading 并不等于 loading: {}。前者保留默认的全语言注册模式,后者会启用分包, 并让未指定的目标语言完全按需加载。

显示切换中的加载状态

setLang() 返回 Promise。目标语言 chunk 尚未加载时,它会等待资源完成;成功后才切换语言 并通知订阅者更新。Runtime 同时维护共享状态。Vue adapter 统一维护响应式 revision; Composition 组件通过 useI18n() 读取共享 Ref,纯 Options 组件通过 i18nComputed() 读取已解包状态。React 组件通过 useI18n() 订阅,Vanilla JS 通过 subscribe() 订阅。

Vue
Vue Options
React
Vanilla JS
<script setup lang="ts">
import { t, useI18n } from 'virtual:ai-i18n';

const { isLangLoading, langLoadState, setLang } = useI18n();

async function switchToFrench() {
  try {
    await setLang('fr-FR');
  } catch {
    // 仅在这里添加业务级恢复动作;通用错误展示直接读取 langLoadState.status。
  }
}
</script>

<template>
  <button :disabled="isLangLoading" @click="switchToFrench">
    {{ isLangLoading ? t('正在加载语言包…') : t('切换到法语') }}
  </button>
  <p v-if="langLoadState.status === 'error'">
    {{ t('语言包加载失败,请重试') }}
  </p>
  <small v-if="langLoadState.status === 'loading'">
    {{ t('目标语言:') }} {{ langLoadState.targetLang }}
  </small>
</template>

加载失败时,Runtime 会保留当前语言并让 Promise reject。应用可以像上例一样捕获错误, 执行日志、重试计数等业务动作;只需要通用 UI 时可以直接使用内置状态。

普通 JavaScript / TypeScript 模块如果只需要当前值,可以读取一次快照:

import { getLangLoadState } from 'virtual:ai-i18n';

const state = getLangLoadState();

需要持续响应变化时,应像 Vanilla 示例一样配合 subscribe() 重新读取。状态的完整类型与 并发语义见 getLangLoadState()

配置规则

  • preloadprefetch 只能填写 locales 中的目标 locale,不能填写 sourceLang
  • 同一 locale 不能同时出现在两个列表中;同一列表内的重复值会自动去重。
  • 非 source 的 defaultLang 会自动按 preload 处理。不要再把它填入 prefetch,否则配置会在启动时 报错。资源就绪前先渲染 source fallback,加载完成后再通知订阅者更新。
  • 相同 locale 的并发调用会复用同一次底层语言包加载请求,不保证各次 setLang() 返回的 Promise 引用相等。不同 locale 的并发切换以最后一次调用为准。
  • 缺失或值为 null 的译文始终回退到 source 文案。

完整字段类型与边界见 AiI18nLocaleLoadingOptions