Vue 国际化 (i18n) 主要通过 vue-i18n 库实现。以下是完整的实现步骤:
1. 安装 vue-i18n
npm install vue-i18n
# 或
yarn add vue-i18n
2. 基本配置
创建 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 i18n
5. 在路由中使用
// 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 国际化的完整实现方案。根据项目复杂度,可以选择简单或高级的配置方式。