国际化(Internationalization,简称 i18n)是现代 Web 应用的重要功能,特别是对于面向全球用户的官网。Vue.js 提供了多种实现国际化的方案,本文将详细介绍如何在 Vue 项目中实现多语言支持。
一、准备工作
1. 安装 vue-i18n
vue-i18n 是 Vue 生态中最流行的国际化插件:
csharp
npm install vue-i18n
# 或
yarn add vue-i18n
2. 项目结构规划
建议的多语言文件目录结构:
bash
src/
├── lang/
│ ├── index.js # 国际化入口文件
│ ├── locales/
│ │ ├── en-US.json # 英语翻译
│ │ ├── zh-CN.json # 简体中文翻译
│ │ └── ja-JP.json # 日语翻译
└── main.js # 主入口文件
二、基础实现
1. 创建语言文件
src/lang/locales/en-US.json
:
css
{
"header": {
"home": "Home",
"about": "About Us",
"products": "Products",
"contact": "Contact"
},
"homepage": {
"title": "Welcome to Our Official Website",
"subtitle": "Innovative Solutions for Your Business"
}
}
src/lang/locales/zh-CN.json
:
css
{
"header": {
"home": "首页",
"about": "关于我们",
"products": "产品中心",
"contact": "联系我们"
},
"homepage": {
"title": "欢迎访问我们的官网",
"subtitle": "为您提供创新的商业解决方案"
}
}
2. 配置 vue-i18n
src/lang/index.js
:
javascript
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import enUS from './locales/en-US.json'
import zhCN from './locales/zh-CN.json'
Vue.use(VueI18n)
const messages = {
'en-US': enUS,
'zh-CN': zhCN
}
// 获取浏览器语言设置
const navigatorLang = navigator.language || 'en-US'
const defaultLang = Object.keys(messages).includes(navigatorLang)
? navigatorLang
: 'en-US'
// 创建 i18n 实例
const i18n = new VueI18n({
locale: localStorage.getItem('lang') || defaultLang,
fallbackLocale: 'en-US',
messages
})
export default i18n
3. 在 Vue 中引入
src/main.js
:
javascript
import Vue from 'vue'
import App from './App.vue'
import i18n from './lang'
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')
三、在组件中使用
1. 基本使用
bash
<template>
<div>
<h1>{{ $t('homepage.title') }}</h1>
<p>{{ $t('homepage.subtitle') }}</p>
<nav>
<router-link to="/">{{ $t('header.home') }}</router-link>
<router-link to="/about">{{ $t('header.about') }}</router-link>
<router-link to="/products">{{ $t('header.products') }}</router-link>
<router-link to="/contact">{{ $t('header.contact') }}</router-link>
</nav>
</div>
</template>
2. 带参数的翻译
语言文件:
json
{
"welcome": "Hello {name}, welcome back!"
}
组件中使用:
bash
<p>{{ $t('welcome', { name: userName }) }}</p>
3. 复数形式
语言文件:
json
{
"cart": {
"items": "You have {count} item in your cart | You have {count} items in your cart"
}
}
组件中使用:
bash
<p>{{ $tc('cart.items', itemCount) }}</p>
四、语言切换功能
1. 创建语言切换组件
src/components/LanguageSwitcher.vue
:
xml
<template>
<div class="language-switcher">
<select v-model="currentLang" @change="changeLanguage">
<option
v-for="lang in availableLanguages"
:key="lang.code"
:value="lang.code"
>
{{ lang.name }}
</option>
</select>
</div>
</template>
<script>
export default {
name: 'LanguageSwitcher',
data() {
return {
availableLanguages: [
{ code: 'en-US', name: 'English' },
{ code: 'zh-CN', name: '简体中文' },
{ code: 'ja-JP', name: '日本語' }
],
currentLang: this.$i18n.locale
}
},
methods: {
changeLanguage() {
this.$i18n.locale = this.currentLang
localStorage.setItem('lang', this.currentLang)
// 根据需要可以触发页面刷新或重新获取数据
// window.location.reload()
}
}
}
</script>
<style scoped>
.language-switcher {
margin: 10px;
}
select {
padding: 5px 10px;
border-radius: 4px;
border: 1px solid #ddd;
}
</style>
2. 在布局中使用
xml
<template>
<div id="app">
<header>
<language-switcher />
<!-- 其他头部内容 -->
</header>
<main>
<router-view />
</main>
</div>
</template>
<script>
import LanguageSwitcher from '@/components/LanguageSwitcher'
export default {
components: {
LanguageSwitcher
}
}
</script>
五、高级功能实现
1. 动态加载语言包
对于大型项目,可以按需加载语言包:
javascript
// src/lang/index.js
export async function loadLocaleMessages(i18n, locale) {
if (Object.keys(i18n.getLocaleMessage(locale)).length > 0) {
return
}
const messages = await import(`@/lang/locales/${locale}.json`)
i18n.setLocaleMessage(locale, messages.default)
return nextTick()
}
// 在语言切换时调用
async function changeLanguage(locale) {
await loadLocaleMessages(this.$i18n, locale)
this.$i18n.locale = locale
localStorage.setItem('lang', locale)
}
2. 处理日期和数字格式化
sql
// src/lang/index.js
const i18n = new VueI18n({
// ...其他配置
numberFormats: {
'en-US': {
currency: {
style: 'currency',
currency: 'USD'
}
},
'zh-CN': {
currency: {
style: 'currency',
currency: 'CNY'
}
}
},
dateTimeFormats: {
'en-US': {
short: {
year: 'numeric',
month: 'short',
day: 'numeric'
},
long: {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long',
hour: 'numeric',
minute: 'numeric'
}
},
'zh-CN': {
short: {
year: 'numeric',
month: 'short',
day: 'numeric'
},
long: {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long',
hour: 'numeric',
minute: 'numeric'
}
}
}
})
组件中使用:
xml
<template>
<div>
<!-- 数字格式化 -->
<p>{{ $n(1000, 'currency') }}</p>
<!-- 日期格式化 -->
<p>{{ $d(new Date(), 'short') }}</p>
<p>{{ $d(new Date(), 'long') }}</p>
</div>
</template>
3. SEO 优化
对于官网,SEO 非常重要。多语言网站的 SEO 最佳实践:
- hreflang 标签:在 HTML head 中添加
ini
<template>
<head>
<link
v-for="lang in availableLanguages"
:key="lang.code"
rel="alternate"
:hreflang="lang.code"
:href="`https://yourdomain.com/${lang.code}${$route.path}`"
>
</head>
</template>
- URL 结构:建议使用以下格式之一
-
- 子域名:en.yourdomain.com
- 路径前缀:yourdomain.com/en/
- URL 参数:yourdomain.com?lang=en(不推荐)
- 语言元信息:在 HTML 标签中设置正确的 lang 属性
xml
<template>
<html :lang="$i18n.locale">
<!-- 页面内容 -->
</html>
</template>
六、最佳实践
- 翻译文件管理
-
- 按功能模块拆分翻译文件
- 使用 JSON 或 YAML 格式
- 为翻译键名制定命名规范(如:模块.组件.功能)
- 开发流程
-
- 提取所有需要翻译的文本到语言文件
- 避免在代码中硬编码文本
- 使用 CI/CD 流程自动同步翻译
缺失翻译处理
javascript
const i18n = new VueI18n({
// ...其他配置
missing: (locale, key) => {
console.warn(`Missing translation for ${key} in ${locale}`)
return key // 或者返回默认语言的翻译
}
})
- 测试
-
- 测试所有语言下的界面布局(不同语言文本长度不同)
- 验证所有翻译键都有对应的翻译
- 检查 RTL(从右到左)语言的布局
七、常见问题解决方案
1. 翻译文本中包含 HTML
使用 v-html
和 $t
:
bash
<p v-html="$t('message.withHtml')"></p>
语言文件:
json
{
"message": {
"withHtml": "Please read our <a href='/terms'>Terms of Service</a>"
}
}
2. 热重载语言文件
在开发环境中,可以添加 webpack 监听:
javascript
if (module.hot) {
module.hot.accept(['@/lang/locales/en-US.json'], () => {
i18n.setLocaleMessage('en-US', require('@/lang/locales/en-US.json'))
})
}
3. 处理语言回退
配置更灵活的回退策略:
arduino
const i18n = new VueI18n({
locale: 'zh-CN',
fallbackLocale: {
'zh-TW': ['zh-CN', 'en-US'],
'zh-HK': ['zh-CN', 'en-US'],
'default': ['en-US']
},
messages
})
八、替代方案
除了 vue-i18n,还有其他国际化方案:
i18next:功能更强大的国际化框架
npm install i18next vue-i18next
Vue 3 的组合式 API 方案:
javascript
import { useI18n } from 'vue-i18n'
export default {
setup() {
const { t, locale } = useI18n()
return { t, locale }
}
}
结语
实现 Vue 官网的多语言国际化需要综合考虑技术实现、用户体验和 SEO 优化。通过 vue-i18n 等工具,我们可以构建出功能完善的多语言网站。随着项目规模扩大,可以引入专业的翻译管理系统(TMS)和持续集成流程来管理翻译内容。国际化不仅仅是文本翻译,还包括日期、时间、货币、数字格式等本地化处理,以及考虑不同文化背景下的用户体验差异。