一、当我们需要说"世界语"时

几年前我接手过一个跨境电商项目,老板推门进来就说:"我们的用户下周会覆盖到25个国家"。那一瞬间,我仿佛看到无数个国旗在代码里飘扬。这就是国际化的现实需求——当你的用户遍及全球时,页面上的每个按钮都在说:"你值得拥有母语体验"。

国际化(i18n)不仅仅是文本翻译,它包含了日期格式、货币符号、复数规则等文化差异处理。在Vue生态中,Vue I18n库是我们的瑞士军刀。它支持Vue 2/3版本,截至2023年每周下载量超过200万次,已经成为Vue国际化的事实标准。

二、快速上手:基础配置四部曲

技术栈:Vue 3 + Vue I18n 9.x + Composition API

// main.js
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'

const messages = {
  en: {
    welcome: 'Welcome {name}!',
    cart: {
      title: 'Your Cart',
      items: '{count} item | {count} items'
    }
  },
  ja: {
    welcome: 'ようこそ、{name}さん!',
    cart: {
      title: 'ショッピングカート',
      items: '{count} 個の商品'
    }
  }
}

const i18n = createI18n({
  legacy: false, // 启用Composition API模式
  locale: 'en',
  fallbackLocale: 'en',
  messages
})

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

这段配置实现了:

  1. 声明式语言包结构(支持嵌套)
  2. 插值语法处理动态内容
  3. 配置回退语言机制
  4. 启用现代API模式

三、让页面开口说话:模板中的魔法时刻

<template>
  <div class="dashboard">
    <!-- 基础翻译 -->
    <h1>{{ $t('welcome', { name: user.name }) }}</h1>
    
    <!-- 复数处理 -->
    <p>{{ $tc('cart.items', itemCount) }}</p>
    
    <!-- 带HTML的翻译 -->
    <p v-html="$t('terms')"></p>
  </div>
</template>

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

const { t, tc } = useI18n()
const itemCount = ref(3)

// 代码中的翻译示例
const pageTitle = computed(() => t('cart.title'))
</script>

特别要注意的是:

  • 使用$tc处理复数规则(英语有单复数,中文没有)
  • v-html用于渲染带HTML标签的翻译,但要防范XSS攻击
  • 在组合式API中使用useI18n获取翻译函数

四、实时切换:语言选择的仪式感

<template>
  <div class="language-switcher">
    <button 
      v-for="lang in availableLocales"
      :key="lang"
      @click="changeLanguage(lang)"
      :class="{ active: locale === lang }"
    >
      {{ getNativeName(lang) }}
    </button>
  </div>
</template>

<script setup>
import { useI18n } from 'vue-i18n'
import { loadLocaleMessages } from '@/i18n'

const { locale, availableLocales } = useI18n()

const changeLanguage = async (newLocale) => {
  if (!localStorage.getItem(newLocale)) {
    const messages = await import(`@/locales/${newLocale}.json`)
    loadLocaleMessages(newLocale, messages.default)
  }
  locale.value = newLocale
  document.documentElement.lang = newLocale
}

const getNativeName = (code) => {
  return new Intl.DisplayNames([code], { type: 'language' }).of(code)
}
</script>

这里实现了:

  1. 按钮式语言切换
  2. 动态加载语言包(重要!)
  3. 本地缓存优化
  4. 语义化HTML属性更新

五、性能优化:让你的翻译包学会轻功

当语言包超过300KB时,就需要考虑拆分加载。这是通过Webpack的动态导入实现的:

// i18n.js
export async function loadLocaleMessages(i18n, locale) {
  if (!i18n.global.availableLocales.includes(locale)) {
    const messages = await import(
      /* webpackChunkName: "locale-[request]" */ 
      `@/locales/${locale}.json`
    )
    i18n.global.setLocaleMessage(locale, messages.default)
  }
}

配合路由守卫实现按需加载:

router.beforeEach(async (to) => {
  const lang = to.params.lang || 'en'
  await loadLocaleMessages(i18n, lang)
  i18n.global.locale.value = lang
})

六、高阶技巧:那些你没想到的细节

日期本地化:

<template>
  <p>{{ d(new Date(), 'long') }}</p>
</template>

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

货币格式化:

const price = computed(() => new Intl.NumberFormat(locale.value, {
  style: 'currency',
  currency: locale.value === 'en' ? 'USD' : 'JPY'
}).format(state.total))

RTL布局支持:

[dir="rtl"] .menu {
  direction: rtl;
  padding-right: 1rem;
}

七、何时需要国际化?

常见应用场景:

  1. 跨境电商平台(产品描述、支付流程)
  2. 企业级后台系统(多地区团队使用)
  3. 教育类应用(多语言课程内容)
  4. 新闻门户网站(多语种新闻报道)
  5. SAAS产品(全球化客户支持)

八、Vue I18n的优缺点对比

优点:

  • 深度集成Vue响应式系统
  • 完善的复数处理规则
  • 支持动态加载语言包
  • 活跃的社区支持
  • 类型安全(v9支持TypeScript)

缺点:

  • 初始配置略显繁琐
  • 大规模项目需要自行设计语言包结构
  • 实时切换时短暂的白屏问题
  • 缺乏内置的翻译管理系统整合

九、踩坑备忘录

  1. 键名管理:建议采用path.to.key的层级结构,建立严格的命名规范
  2. 翻译质量:专业翻译>机器翻译,特别是法律条款
  3. 缓存策略:对已加载语言包做本地存储,但要有版本控制
  4. 回退机制:当某语言翻译不全时,自动切换到备用语言
  5. 测试策略:使用伪翻译(如所有中文后加※)验证布局

十、从经验中得到的启示

经过多个国际化项目的实践,我总结出"三个统一"原则:

  1. 管理统一:使用专业的TMS(翻译管理系统)
  2. 流程统一:开发→翻译→校对→发布的标准化流程
  3. 样式统一:预留40%的文本扩展空间

十一、总结

国际化不是简单的文本替换,而是建立全球用户的情感连接。通过Vue I18n,我们可以优雅地实现多语言支持,但真正的挑战在于持续维护和用户体验优化。记住,好的国际化就像空气——用户感觉不到它的存在,却不可或缺。