如何在 Vue 中实现一个通用的国际化(i18n)解决方案,支持多语言切换和文本动态加载?

各位观众老爷们,大家好!今天咱们来聊聊 Vue 项目里的国际化(i18n)这个磨人的小妖精。别怕,今天咱们就把这妖精给收了,让你的项目也能说一口流利的“各国语言”。

国际化:不只是翻译

首先,咱们得明白,国际化不仅仅是把文字翻译成不同的语言。它涉及到日期、时间、货币格式等等,甚至包括从右到左的阅读习惯。不过,在前端,我们通常关注的是文本内容的翻译和一些简单的格式化。

Vue + i18n:天生一对

Vue 和 i18n 简直是天生一对!有很多 i18n 库可以和 Vue 完美结合,咱们今天就用 vue-i18n 这个官方推荐的库来做演示。

安装 vue-i18n

首先,打开你的终端,输入:

npm install vue-i18n@9
# 或者
yarn add vue-i18n@9

注意,这里指定了版本号 @9。因为vue-i18n 版本 9 是兼容vue3 的.

初始化 i18n 实例

接下来,我们需要创建一个 i18n 实例。在你的 src 目录下,创建一个 i18n 文件夹,然后在里面创建一个 index.js 文件:

// src/i18n/index.js
import { createI18n } from 'vue-i18n'

const i18n = createI18n({
  locale: 'zh-CN', // 默认语言
  fallbackLocale: 'en-US', // 备用语言,当没有对应翻译时使用
  messages: {
    'zh-CN': {
      message: {
        hello: '你好,世界!',
        welcome: '欢迎来到我的网站!',
        dynamic: '这是一个动态文本:{value}'
      }
    },
    'en-US': {
      message: {
        hello: 'Hello, world!',
        welcome: 'Welcome to my website!',
        dynamic: 'This is a dynamic text: {value}'
      }
    }
  }
})

export default i18n

这段代码做了什么?

  1. 导入 createI18n: 这是 Vue I18n 的核心函数,用于创建 i18n 实例。
  2. 创建 i18n 实例: 使用 createI18n 创建一个 i18n 实例,并配置以下选项:
    • locale: 设置默认语言为 zh-CN (简体中文)。
    • fallbackLocale: 设置备用语言为 en-US (美国英语)。如果当前语言没有对应的翻译,则使用备用语言。
    • messages: 定义不同语言的翻译文本。这里定义了 zh-CNen-US 两种语言的翻译,每个语言都包含一个 message 对象,其中包含一些键值对,键是翻译的标识符,值是翻译后的文本。 动态文本示例dynamic使用了占位符 {value},稍后我们会看到如何替换它。
  3. 导出 i18n 实例: 将创建的 i18n 实例导出,以便在 Vue 应用中使用。

在 Vue 应用中使用 i18n

在你的 main.js 文件中,导入 i18n 实例并将其安装到 Vue 应用中:

// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n'

const app = createApp(App)
app.use(i18n)
app.mount('#app')

在组件中使用翻译

现在,你可以在 Vue 组件中使用 $t 方法来获取翻译后的文本了。 $t 是 vue-i18n 提供的全局方法,用于翻译文本。

// src/App.vue
<template>
  <div>
    <h1>{{ $t('message.hello') }}</h1>
    <p>{{ $t('message.welcome') }}</p>
    <p>{{ $t('message.dynamic', { value: 'Vue.js' }) }}</p>
    <button @click="changeLocale('en-US')">切换到英文</button>
    <button @click="changeLocale('zh-CN')">切换到中文</button>
  </div>
</template>

<script>
import { useI18n } from 'vue-i18n'

export default {
  setup() {
    const { t, locale } = useI18n()

    const changeLocale = (newLocale) => {
      locale.value = newLocale
    }

    return {
      t,
      changeLocale
    }
  }
}
</script>

这段代码做了什么?

  1. 引入 useI18n: 这是一个 Vue I18n 提供的 hook,用于在 setup 函数中使用 i18n 功能。
  2. 使用 useI18n: 调用 useI18n hook,获取 t (翻译函数) 和 locale (当前语言) 对象。
  3. 使用 $t 在模板中翻译: 在模板中使用 $t('message.hello') 获取 message.hello 对应的翻译文本。
  4. 动态文本: 使用 $t('message.dynamic', { value: 'Vue.js' }) 获取 message.dynamic 对应的翻译文本,并使用 { value: 'Vue.js' } 替换文本中的占位符 {value}
  5. 切换语言: 创建一个 changeLocale 方法,用于切换语言。该方法将 locale.value 设置为新的语言代码。
  6. 返回 tchangeLocale:tchangeLocale 方法返回,以便在模板中使用。

现在运行你的 Vue 项目,你应该能看到页面上的文本被翻译成中文或英文。点击按钮可以切换语言。

动态加载语言文件

上面的例子把所有的翻译都写在了一个文件里。如果你的项目很大,这显然不是一个好主意。更好的做法是把不同语言的翻译放在不同的文件中,然后动态加载它们。

首先,在 i18n 目录下创建 locales 文件夹,然后在里面创建 zh-CN.jsonen-US.json 文件:

// src/i18n/locales/zh-CN.json
{
  "message": {
    "hello": "你好,世界!",
    "welcome": "欢迎来到我的网站!",
    "dynamic": "这是一个动态文本:{value}"
  }
}
// src/i18n/locales/en-US.json
{
  "message": {
    "hello": "Hello, world!",
    "welcome": "Welcome to my website!",
    "dynamic": "This is a dynamic text: {value}"
  }
}

然后,修改 i18n/index.js 文件,使用 createI18nmessages 选项,但不再直接定义翻译文本,而是定义一个函数来加载翻译文件:

// src/i18n/index.js
import { createI18n } from 'vue-i18n'

async function loadLocaleMessages(locale) {
  const messages = await import(`./locales/${locale}.json`)
  return messages.default
}

const i18n = createI18n({
  locale: 'zh-CN',
  fallbackLocale: 'en-US',
  messages: {} // 初始化为空对象,后续动态加载
})

export async function setI18nLanguage(locale) {
  i18n.global.locale.value = locale // 直接修改 i18n 实例的 locale

  // 如果已经加载过该语言,则直接返回
  if (i18n.global.availableLocales.includes(locale)) {
    return
  }

  // 加载语言文件
  const messages = await loadLocaleMessages(locale)

  // 将加载的语言文件添加到 i18n 实例中
  i18n.global.setLocaleMessage(locale, messages)
  i18n.global.availableLocales.push(locale) // 记录已加载的语言
}

export default i18n

这段代码做了什么?

  1. loadLocaleMessages 函数: 这是一个异步函数,用于动态加载语言文件。它使用 import() 函数加载指定语言的 JSON 文件,并返回其默认导出 (也就是 JSON 对象)。
  2. setI18nLanguage 函数: 这是一个异步函数,用于设置 i18n 的语言。它接收一个语言代码作为参数。
    • 首先,它设置 i18n 实例的 locale 属性为新的语言代码。
    • 然后,它检查是否已经加载过该语言。如果已经加载过,则直接返回。
    • 如果还没有加载过该语言,则调用 loadLocaleMessages 函数加载语言文件。
    • 最后,它使用 i18n.global.setLocaleMessage 函数将加载的语言文件添加到 i18n 实例中,并使用 i18n.global.availableLocales.push(locale) 记录已加载的语言。
  3. i18n 实例初始化: 使用 createI18n 创建一个 i18n 实例,并将 messages 选项初始化为空对象。这是因为我们将在运行时动态加载语言文件。

现在,我们需要修改 App.vue 组件,使用 setI18nLanguage 函数来切换语言:

// src/App.vue
<template>
  <div>
    <h1>{{ $t('message.hello') }}</h1>
    <p>{{ $t('message.welcome') }}</p>
    <p>{{ $t('message.dynamic', { value: 'Vue.js' }) }}</p>
    <button @click="changeLocale('en-US')">切换到英文</button>
    <button @click="changeLocale('zh-CN')">切换到中文</button>
  </div>
</template>

<script>
import { useI18n } from 'vue-i18n'
import { setI18nLanguage } from './i18n'

export default {
  setup() {
    const { t, locale } = useI18n()

    const changeLocale = async (newLocale) => {
      await setI18nLanguage(newLocale)
      locale.value = newLocale // 确保 locale 同步更新
    }

    return {
      t,
      changeLocale
    }
  }
}
</script>

这段代码修改了 changeLocale 函数,使其调用 setI18nLanguage 函数来加载和设置语言。 setI18nLanguage 是一个异步操作,所以我们在 changeLocale 中使用了 await 关键字,以确保语言文件加载完成后再更新 locale.value

更好的体验:自动根据浏览器语言设置默认语言

为了提供更好的用户体验,我们可以根据用户的浏览器语言自动设置默认语言。

i18n/index.js 中,添加一个函数来获取浏览器语言:

// src/i18n/index.js
function getBrowserLocale() {
  const navigatorLocale = navigator.language || navigator.userLanguage
  const lang = navigatorLocale.substr(0, 2) // 获取语言的前两个字母
  // 根据实际情况返回支持的语言代码
  if (lang === 'zh') {
    return 'zh-CN'
  } else if (lang === 'en') {
    return 'en-US'
  } else {
    return 'en-US' // 默认使用英语
  }
}

// ... 其他代码 ...

const i18n = createI18n({
  locale: getBrowserLocale(), // 根据浏览器语言设置默认语言
  fallbackLocale: 'en-US',
  messages: {}
})

这段代码做了什么?

  1. getBrowserLocale 函数: 这是一个函数,用于获取浏览器的语言。
    • 它首先尝试获取 navigator.languagenavigator.userLanguage 属性,这些属性包含了浏览器的语言信息。
    • 然后,它使用 substr(0, 2) 获取语言代码的前两个字母。
    • 最后,它根据语言代码返回支持的语言代码。如果不支持该语言,则返回默认语言 en-US
  2. i18n 实例初始化: 在创建 i18n 实例时,将 locale 选项设置为 getBrowserLocale() 函数的返回值。

更进一步:使用 i18n 组件

vue-i18n 还提供了一些组件,可以更方便地在模板中使用翻译。

  • <i18n> 组件: 可以格式化数字、日期和时间。
  • <i18n-t> 组件: 用于翻译文本,功能和 $t 方法类似。

例如,我们可以使用 <i18n-t> 组件来翻译 App.vue 中的文本:

// src/App.vue
<template>
  <div>
    <h1><i18n-t keypath="message.hello" /></h1>
    <p><i18n-t keypath="message.welcome" /></p>
    <p><i18n-t keypath="message.dynamic" :values="{ value: 'Vue.js' }" /></p>
    <button @click="changeLocale('en-US')">切换到英文</button>
    <button @click="changeLocale('zh-CN')">切换到中文</button>
  </div>
</template>

这段代码使用了 <i18n-t> 组件来翻译文本。 keypath 属性指定了翻译的标识符, :values 属性指定了动态文本的占位符替换值。

i18n 的高级用法:复数形式、日期格式化等等

vue-i18n 还支持很多高级用法,例如:

  • 复数形式: 根据数量选择不同的翻译文本。
  • 日期格式化: 根据语言习惯格式化日期和时间。
  • 货币格式化: 根据语言习惯格式化货币。

这些高级用法可以参考 vue-i18n 的官方文档。

总结

今天我们学习了如何在 Vue 项目中使用 vue-i18n 实现国际化。我们从最简单的文本翻译开始,然后学习了如何动态加载语言文件,以及如何根据浏览器语言设置默认语言。最后,我们还介绍了 vue-i18n 提供的一些组件和高级用法。

希望今天的讲座能帮助你更好地理解和使用 vue-i18n。 记住,国际化不仅仅是翻译,更是一种对用户的尊重。 好了,今天的讲座就到这里,下次再见!

表格总结:

功能 实现方式 代码示例
安装 vue-i18n npm install vue-i18n@9yarn add vue-i18n@9 (终端命令)
初始化 i18n 使用 createI18n 创建 i18n 实例,配置 locale, fallbackLocale, messages javascript import { createI18n } from 'vue-i18n' const i18n = createI18n({ locale: 'zh-CN', fallbackLocale: 'en-US', messages: { ... } }) export default i18n
应用 i18n main.jsapp.use(i18n) javascript import { createApp } from 'vue' import App from './App.vue' import i18n from './i18n' const app = createApp(App) app.use(i18n) app.mount('#app')
使用翻译 使用 $t 方法或 <i18n-t> 组件。 vue <template> <p>{{ $t('message.hello') }}</p> <i18n-t keypath="message.welcome" /> </template>
动态加载语言文件 创建 loadLocaleMessages 函数加载 JSON 文件,使用 setI18nLanguage 函数设置语言和加载语言文件。 javascript async function loadLocaleMessages(locale) { ... } export async function setI18nLanguage(locale) { ... }
自动检测浏览器语言 使用 getBrowserLocale 函数获取浏览器语言,作为 locale 的默认值。 javascript function getBrowserLocale() { ... } const i18n = createI18n({ locale: getBrowserLocale(), ... })
i18n 组件 <i18n> (格式化数字、日期、时间), <i18n-t> (翻译文本)。 vue <template> <i18n tag="div" :path="'number'" :locale="currentLocale" :number="1234567.89" format="currency"/> <i18n-t keypath="message.dynamic" :values="{ value: 'Vue.js' }" /> </template>

希望这个表格能够帮助你更好地理解 Vue i18n 的使用方法。 记住,多实践才能真正掌握!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注