Skip to content

懒加载

一次性加载所有的本地化文件是过度且不必要的。

在使用构建工具时,懒加载或异步加载本地化文件非常简单。

假设我们有一个类似下面的项目目录:

txt
├── dist
├── index.html
├── package.json
├── src
│   ├── App.vue
│   ├── components
│   ├── i18n.js
│   ├── index.css
│   ├── locales
│   │   ├── en.json
│   │   └── ja.json
│   ├── main.js
│   ├── pages
│   │   ├── About.vue
│   │   └── Home.vue
│   └── router.js

pages 文件夹是我们任意 Vue 组件文件如 About.vue、路由初始化、i18n 初始化和其他文件所在的位置。locales 文件夹是我们所有本地化文件所在的位置,而在 i18n.js 中,定义了 i18n 相关过程的函数如下:

js
import { nextTick } from 'vue'
import { createI18n } from 'vue-i18n'

export const SUPPORT_LOCALES = ['en', 'ja']

export function setupI18n(options = { locale: 'en' }) {
  const i18n = createI18n(options)
  setI18nLanguage(i18n, options.locale)
  return i18n
}

export function setI18nLanguage(i18n, locale) {
  if (i18n.mode === 'legacy') {
    i18n.global.locale = locale
  } else {
    i18n.global.locale.value = locale
  }
  /**
   * 注意:
   * 如果您需要为请求头指定语言设置,比如 `fetch` API,在这里设置。
   * 以下是对 axios 的示例。
   *
   * axios.defaults.headers.common['Accept-Language'] = locale
   */
  document.querySelector('html').setAttribute('lang', locale)
}

export async function loadLocaleMessages(i18n, locale) {
  // 使用动态导入加载本地化消息
  const messages = await import(
    /* webpackChunkName: "locale-[request]" */ `./locales/${locale}.json`
  )

  // 设置语言环境和本地化消息
  i18n.global.setLocaleMessage(locale, messages.default)

  return nextTick()
}

导出了以下三个函数:

  • setupI18n
  • setI18nLanguage
  • loadLocaleMessages

TIP

此代码示例还展示了如何在组件外部使用 i18n 实例的 global 属性来处理。 关于 i18n 实例,请参阅 API 参考

setupI18n 函数采用与 createI18n 相同的选项,使用这些选项创建 i18n 实例,执行 setI18nLanguage 函数,并返回 i18n 实例。

setI18nLanguage 函数通过将参数 i18n 的语言环境设置为参数 locale 的值来设置语言。此外,此函数还有将 HTML 文档的 lang 属性设置为参数 locale 值的实用功能。如注释中所述,就像 HTTP 客户端一样,您也可以设置语言。

loadLocaleMessages 函数是我们实际用来切换语言的。加载新文件是通过 webpack 提供的 import 函数完成的,它允许我们动态加载文件,由于它使用 Promise,我们可以轻松等待加载完成。

您可以在 webpack 文档中了解更多关于 import 函数的信息。

使用 loadLocaleMessages 函数很简单。常见的用例是在 vue-router 的 beforeEach 钩子中。

这里是 router.js 中 vue-router beforeEach 钩子部分的代码:

js
  // 导航守卫
  router.beforeEach(async (to, from, next) => {
    const paramsLocale = to.params.locale

    // 如果 paramsLocale 不在 SUPPORT_LOCALES 中,则使用默认语言
    if (!SUPPORT_LOCALES.includes(paramsLocale)) {
      return next(`/${locale}`)
    }

    // 加载本地化消息
    if (!i18n.global.availableLocales.includes(paramsLocale)) {
      await loadLocaleMessages(i18n, paramsLocale)
    }

    // 设置 i18n 语言
    setI18nLanguage(i18n, paramsLocale)

    return next()
  })