Vue 国际化 (i18n) 主要通过vue-i18n 库实现。以下是完整的实现步骤:
1. 安装 vue-i18n
npm install vue-i18n # 或 yarn add vue-i18n2. 基本配置
创建 i18n 实例
// src/i18n/index.js import Vue from 'vue' import VueI18n from 'vue-i18n' Vue.use(VueI18n) // 语言包 const messages = { en: { message: { hello: 'Hello World', welcome: 'Welcome!', user: { name: 'Name', age: 'Age' } }, button: { submit: 'Submit', cancel: 'Cancel' } }, zh: { message: { hello: '你好,世界', welcome: '欢迎!', user: { name: '姓名', age: '年龄' } }, button: { submit: '提交', cancel: '取消' } }, ja: { message: { hello: 'こんにちは、世界', welcome: 'ようこそ!' } } } // 创建实例 const i18n = new VueI18n({ locale: 'zh', // 默认语言 fallbackLocale: 'en', // 回退语言 messages, // 语言包 silentTranslationWarn: true // 禁止警告 }) export default i18n在 main.js 中引入
// src/main.js import Vue from 'vue' import App from './App.vue' import i18n from './i18n' new Vue({ i18n, render: h => h(App) }).$mount('#app')3. 在组件中使用
模板中使用
<template> <div> <!-- 基本用法 --> <p>{{ $t('message.hello') }}</p> <!-- 带参数 --> <p>{{ $t('message.welcome', { name: 'John' }) }}</p> <!-- 复数形式 --> <p>{{ $tc('cart.item', 3, { count: 3 }) }}</p> <!-- 指令方式 --> <p v-t="'message.hello'"></p> <!-- 属性绑定 --> <input :placeholder="$t('message.user.name')"> <!-- 切换语言按钮 --> <button @click="changeLang('en')">English</button> <button @click="changeLang('zh')">中文</button> </div> </template> <script> export default { methods: { changeLang(lang) { this.$i18n.locale = lang localStorage.setItem('lang', lang) // 保存语言偏好 } }, mounted() { // 读取保存的语言设置 const savedLang = localStorage.getItem('lang') if (savedLang) { this.$i18n.locale = savedLang } } } </script>JavaScript 中使用
// 在方法或计算属性中 export default { methods: { showMessage() { alert(this.$t('message.welcome')) }, getTranslatedText() { return this.$t('button.submit') } } }4. 语言包按需加载(推荐)
创建语言文件
src/ locales/ en.json zh.json ja.json// src/locales/en.json { "common": { "save": "Save", "cancel": "Cancel" }, "login": { "title": "Login", "username": "Username" } }配置懒加载
// src/i18n/index.js import Vue from 'vue' import VueI18n from 'vue-i18n' Vue.use(VueI18n) // 创建实例 const i18n = new VueI18n({ locale: localStorage.getItem('lang') || 'zh', fallbackLocale: 'en', messages: {} // 初始为空 }) // 已加载的语言 const loadedLanguages = [] // 异步加载语言包 function setI18nLanguage(lang) { i18n.locale = lang document.querySelector('html').setAttribute('lang', lang) return lang } export function loadLanguageAsync(lang) { if (i18n.locale === lang) { return Promise.resolve(setI18nLanguage(lang)) } if (loadedLanguages.includes(lang)) { return Promise.resolve(setI18nLanguage(lang)) } return import(`@/locales/${lang}.json`).then(messages => { i18n.setLocaleMessage(lang, messages.default || messages) loadedLanguages.push(lang) return setI18nLanguage(lang) }) } export default i18n5. 在路由中使用
// router/index.js import Vue from 'vue' import VueRouter from 'vue-router' import { loadLanguageAsync } from '@/i18n' Vue.use(VueRouter) const router = new VueRouter({ routes: [ { path: '/:lang', component: () => import('@/views/Home.vue'), beforeEnter: async (to, from, next) => { const lang = to.params.lang await loadLanguageAsync(lang) next() } } ] })6. 组件内单独定义
<template> <div>{{ $t('myComponent.title') }}</div> </template> <script> export default { i18n: { messages: { en: { title: 'My Component' }, zh: { title: '我的组件' } } } } </script>7. 数字和日期格式化
// 数字格式化 $n(1000, 'currency') // $1,000.00 // 日期格式化 $d(new Date(), 'short')8. 最佳实践
项目结构
src/ i18n/ index.js # 主配置文件 languages/ # 语言包目录 en/ common.json login.json zh/ common.json login.json utils.js # 工具函数语言包模块化
// 自动导入所有语言文件 const modules = {} const requireModule = require.context( './languages', true, /\.json$/ ) requireModule.keys().forEach(fileName => { const path = fileName.replace(/(\.\/|\.json$)/g, '').split('/') const lang = path[0] const moduleName = path[1] if (!modules[lang]) modules[lang] = {} modules[lang][moduleName] = requireModule(fileName) })TypeScript 支持
// src/i18n.d.ts declare module 'vue/types/vue' { interface Vue { $t: (key: string, values?: any) => string } }9. 完整的切换组件示例
<template> <div class="language-switcher"> <select v-model="$i18n.locale" @change="changeLanguage"> <option value="en">English</option> <option value="zh">中文</option> <option value="ja">日本語</option> </select> </div> </template> <script> export default { name: 'LanguageSwitcher', methods: { changeLanguage() { localStorage.setItem('lang', this.$i18n.locale) location.reload() // 或重新加载语言包 } } } </script>10. 注意事项
命名约定:使用点分隔的键名,保持层次清晰
提取文本:使用工具提取模板中的文本,如
vue-i18n-extract动态内容:动态键名使用
$t函数,而不是在模板中拼接回退策略:设置合适的 fallback locale
SEO优化:为不同语言设置不同的URL,使用
<link rel="alternate">
这是 Vue 国际化的完整实现方案。根据项目复杂度,可以选择简单或高级的配置方式。