Vue I18n

1. 什么是 Vue I18n?

Vue I18n 是 Vue.js 的官方国际化插件,它能够让你的应用轻松支持多种语言。无论是简单的文本替换,还是复杂的日期、数字格式化,Vue I18n 都能提供完善的解决方案。

2. 基础概念

2.1 安装与引入

npm install vue-i18n@9

2.2 最简单的 i18n 实例

import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'

// 1. 准备语言包
const messages = {
  en: {
    welcome: 'Welcome',
    button: { submit: 'Submit' }
  },
  zh: {
    welcome: '欢迎',
    button: { submit: '提交' }
  }
}

// 2. 创建 i18n 实例,这里是vue3的写法
const i18n = createI18n({
  legacy: false,  // 使用 Composition API 模式
  locale: 'en',   // 默认语言
  messages        // 上面的语言包
})

// 3. 挂载到 Vue 应用,同样是vue3
const app = createApp(App)
app.use(i18n)
app.mount('#app')

2.3 在组件中使用

Options API 方式:

<template>
  <div>
    <h1>{{ $t('welcome') }}</h1>
    <button>{{ $t('button.submit') }}</button>
  </div>
</template>

Composition API 方式:

<template>
  <div>
    <h1>{{ t('welcome') }}</h1>
    <button>{{ t('button.submit') }}</button>
  </div>
</template>

<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

3. 例子

3.1 项目目录结构

src/
  locales/           // 语言包目录
    zh-CN.ts
    en-US.ts
  plugins/
    i18n.ts         // i18n 实例配置
  composables/
    useLocale.ts   // 语言切换逻辑
  components/
    LangSwitch.vue  //语言切换组件

3.2 模块化语言包

src/locales/zh-CN.ts

export default {
  welcome: '欢迎使用',
  chart: { title: '月度收支' },
  btn: { lang: '切换语言' }
}

src/locales/en-US.ts

export default {
  welcome: 'Welcome',
  chart: { title: 'Monthly Report' },
  btn: { lang: 'Change Language' }
}

3.3 带懒加载的 i18n 实例!

src/plugins/i18n.ts

import { createI18n } from 'vue-i18n'

/** 异步加载语言包 - 实现懒加载 */
export function loadLocaleMessages(locale: string) {
  return import(/* @vite-ignore */`../locales/${locale}.ts`)
    .then((module) => module.default)  // 提取默认导出!!,import 返回的是一个promise对象
}

/** 从本地存储恢复语言设置 */
function getPersistedLocale(): string {
  const saved = localStorage.getItem('locale')
  if (saved) return saved
  
  // 获取系统语言
  const sysLang = navigator.language.slice(0, 2)
  return sysLang === 'zh' ? 'zh-CN' : 'en-US'
}

const i18n = createI18n({
  legacy: false,                 // 使用 Composition API
  locale: getPersistedLocale(),  // 智能初始语言
  fallbackLocale: 'zh-CN',       // 回退语言
  messages: {}                   // 初始为空,动态填充
})

export default i18n

3.4 懒加载原理

为什么需要 .then(module => module.default)?

// 语言包使用默认导出
export default { welcome: 'Welcome' }

// 动态导入返回的模块对象:
import('../locales/en-US.ts').then(module => {
  // module = { default: { welcome: 'Welcome' } }
  const messages = module.default  // 提取出真正的语言包
  // messages = { welcome: 'Welcome' }
})

懒加载的网络请求过程:

首次加载应用:
  GET /index.js                 # 主包(不含语言包)

用户切换到中文:
  GET /chunks/zh-CN.[hash].js   # 按需加载中文包

用户切换到英文:  
  GET /chunks/en-US.[hash].js   # 按需加载英文包

3.5 应用初始化

src/main.ts

import { createApp } from 'vue'
import App from './App.vue'
import i18n, { loadLocaleMessages } from './plugins/i18n'

const app = createApp(App)
app.use(i18n)

// 关键:先加载语言包再挂载,避免首屏闪烁
loadLocaleMessages(i18n.global.locale.value).then((messages) => {
  i18n.global.setLocaleMessage(i18n.global.locale.value, messages)
  app.mount('#app')  // 现在才挂载应用
})

3.6 语言切换逻辑

src/composables/useLocale.ts

import { ref } from 'vue'
import i18n, { loadLocaleMessages } from '@/plugins/i18n'

export function useLocale() {
  // 响应式当前语言
  const locale = ref(i18n.global.locale.value)

  async function setLocale(lang: string) {
    if (locale.value === lang) return  // 防重复点击
    
    // 1. 动态加载语言包
    const messages = await loadLocaleMessages(lang)
    
    // 2. 更新 i18n 实例
    i18n.global.setLocaleMessage(lang, messages)  // 添加语言包
    i18n.global.locale.value = lang               // 切换语言
    
    // 3. 更新本地状态
    locale.value = lang
    
    // 4. 持久化存储
    localStorage.setItem('locale', lang)
    document.cookie = `locale=${lang}; path=/; max-age=31536000`
  }

  return { locale, setLocale }
}

3.7 语言切换组件

src/components/LangSwitch.vue

<template>
  <select :value="locale" @change="setLocale($event.target.value)">
    <option value="zh-CN">简体中文</option>
    <option value="en-US">English</option>
  </select>
</template>

<script setup lang="ts">
import { useLocale } from '@/composables/useLocale'
const { locale, setLocale } = useLocale()
</script>

3.8 在应用中使用

<template>
  <div id="app">
    <h1>{{ $t('welcome') }}</h1>
    <p>{{ $t('chart.title') }}</p>
    <button>{{ $t('btn.lang') }}</button>
    
    <LangSwitch />
  </div>
</template>
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐