uni-app 国际化
章节介绍
在全球化背景下,开发支持多语言的应用变得越来越重要。uni-app 提供了多种方式来实现国际化,使应用能够轻松适应不同语言和地区的用户需求。本章节将详细介绍 uni-app 中的国际化实现方法,包括语言包的创建、多语言切换、动态语言更新等功能。
核心知识点
1. 国际化基础概念
- 国际化(i18n):使应用能够适应不同语言和地区的需求
- 本地化(l10n):将应用适配到特定语言和地区
- 语言包:存储不同语言翻译的文件
- 语言标签:标识语言和地区的代码,如 zh-CN、en-US 等
2. uni-app 国际化方案
uni-app 支持多种国际化实现方案:
- 使用 uni-app 官方推荐的
vue-i18n插件 - 使用自定义国际化工具
- 利用条件编译实现多语言
3. vue-i18n 插件使用
- 安装和配置 vue-i18n
- 创建语言包文件
- 在组件中使用国际化
- 动态切换语言
4. 语言包管理
- 语言包的组织方式
- 翻译键的命名规范
- 语言包的加载和缓存
- 动态更新语言包
5. 国际化最佳实践
- 日期、时间的国际化
- 数字、货币的国际化
- 文本方向的处理(从右到左的语言)
- 占位符和复数形式的处理
实用案例分析
案例一:基本国际化实现
场景:创建一个支持中英文切换的应用。
实现步骤:
- 安装 vue-i18n 插件
- 创建语言包文件
- 配置国际化实例
- 在组件中使用国际化
- 实现语言切换功能
代码示例:
1. 安装 vue-i18n 插件
# 使用 npm 安装
npm install vue-i18n@8
# 或使用 yarn 安装
yarn add vue-i18n@82. 创建语言包文件
创建 src/lang/zh-CN.js:
export default {
common: {
confirm: '确认',
cancel: '取消',
submit: '提交',
reset: '重置'
},
login: {
title: '用户登录',
username: '用户名',
password: '密码',
login: '登录',
forgetPassword: '忘记密码',
register: '注册账号'
},
home: {
welcome: '欢迎使用 uni-app',
features: '核心功能',
crossPlatform: '跨平台开发',
performance: '高性能',
ecosystem: '丰富的生态'
}
}创建 src/lang/en-US.js:
export default {
common: {
confirm: 'Confirm',
cancel: 'Cancel',
submit: 'Submit',
reset: 'Reset'
},
login: {
title: 'User Login',
username: 'Username',
password: 'Password',
login: 'Login',
forgetPassword: 'Forgot Password',
register: 'Register Account'
},
home: {
welcome: 'Welcome to uni-app',
features: 'Core Features',
crossPlatform: 'Cross-platform Development',
performance: 'High Performance',
ecosystem: 'Rich Ecosystem'
}
}3. 配置国际化实例
创建 src/lang/index.js:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import zhCN from './zh-CN'
import enUS from './en-US'
Vue.use(VueI18n)
// 从本地存储获取语言设置,默认使用中文
const lang = uni.getStorageSync('lang') || 'zh-CN'
const i18n = new VueI18n({
locale: lang,
messages: {
'zh-CN': zhCN,
'en-US': enUS
}
})
export default i18n在 main.js 中引入:
import Vue from 'vue'
import App from './App.vue'
import i18n from './lang'
Vue.config.productionTip = false
new Vue({
i18n,
render: h => h(App)
}).$mount('#app')4. 在组件中使用国际化
在页面或组件中使用 $t() 方法:
<template>
<view class="container">
<view class="header">
<text class="title">{{ $t('home.welcome') }}</text>
</view>
<view class="content">
<text class="subtitle">{{ $t('home.features') }}</text>
<view class="feature-list">
<view class="feature-item">
<text>{{ $t('home.crossPlatform') }}</text>
</view>
<view class="feature-item">
<text>{{ $t('home.performance') }}</text>
</view>
<view class="feature-item">
<text>{{ $t('home.ecosystem') }}</text>
</view>
</view>
</view>
<view class="footer">
<button @click="switchLanguage('zh-CN')">中文</button>
<button @click="switchLanguage('en-US')">English</button>
</view>
</view>
</template>
<script>
export default {
methods: {
switchLanguage(lang) {
this.$i18n.locale = lang
uni.setStorageSync('lang', lang)
uni.showToast({
title: this.$t('common.confirm'),
icon: 'success'
})
}
}
}
</script>
<style>
.container {
padding: 20rpx;
}
.header {
margin-bottom: 40rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.content {
margin-bottom: 40rpx;
}
.subtitle {
font-size: 28rpx;
font-weight: bold;
color: #666;
margin-bottom: 20rpx;
}
.feature-list {
margin-top: 20rpx;
}
.feature-item {
padding: 20rpx;
background-color: #f5f5f5;
margin-bottom: 10rpx;
border-radius: 8rpx;
}
.footer {
display: flex;
justify-content: space-around;
margin-top: 40rpx;
}
button {
padding: 20rpx 40rpx;
border-radius: 8rpx;
}
</style>案例二:动态加载语言包
场景:从服务器获取语言包,实现动态更新。
实现步骤:
- 创建语言包加载函数
- 从服务器获取语言包
- 动态更新 i18n 实例
- 处理加载状态和错误
代码示例:
// src/lang/index.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import zhCN from './zh-CN'
import enUS from './en-US'
Vue.use(VueI18n)
const lang = uni.getStorageSync('lang') || 'zh-CN'
const i18n = new VueI18n({
locale: lang,
messages: {
'zh-CN': zhCN,
'en-US': enUS
}
})
// 动态加载语言包
export function loadLanguagePack(lang) {
return new Promise((resolve, reject) => {
// 先检查本地是否已有该语言包
if (i18n.messages[lang]) {
i18n.locale = lang
uni.setStorageSync('lang', lang)
resolve()
return
}
// 从服务器获取语言包
uni.request({
url: `https://api.example.com/lang/${lang}`,
method: 'GET',
success: (res) => {
if (res.statusCode === 200 && res.data) {
// 更新语言包
i18n.setLocaleMessage(lang, res.data)
i18n.locale = lang
uni.setStorageSync('lang', lang)
resolve()
} else {
reject(new Error('Failed to load language pack'))
}
},
fail: (err) => {
reject(err)
}
})
})
}
export default i18n在组件中使用:
<template>
<view class="container">
<view v-if="loading">加载语言包中...</view>
<view v-else>
<text>{{ $t('home.welcome') }}</text>
<button @click="loadLanguage('zh-CN')">加载中文语言包</button>
<button @click="loadLanguage('en-US')">加载英文语言包</button>
</view>
</view>
</template>
<script>
import { loadLanguagePack } from '@/lang'
export default {
data() {
return {
loading: false
}
},
methods: {
async loadLanguage(lang) {
this.loading = true
try {
await loadLanguagePack(lang)
uni.showToast({
title: this.$t('common.confirm'),
icon: 'success'
})
} catch (error) {
uni.showToast({
title: '加载语言包失败',
icon: 'none'
})
} finally {
this.loading = false
}
}
}
}
</script>案例三:日期和数字的国际化
场景:根据不同语言和地区格式化日期、时间和数字。
实现步骤:
- 使用 JavaScript 的 Intl 对象
- 创建日期和数字格式化工具
- 在组件中使用格式化方法
代码示例:
创建 src/utils/format.js:
// 日期格式化
export function formatDate(date, lang = 'zh-CN') {
return new Intl.DateTimeFormat(lang, {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
}).format(date)
}
// 时间格式化
export function formatTime(date, lang = 'zh-CN') {
return new Intl.DateTimeFormat(lang, {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}).format(date)
}
// 数字格式化
export function formatNumber(num, lang = 'zh-CN') {
return new Intl.NumberFormat(lang).format(num)
}
// 货币格式化
export function formatCurrency(amount, currency = 'CNY', lang = 'zh-CN') {
return new Intl.NumberFormat(lang, {
style: 'currency',
currency: currency
}).format(amount)
}在组件中使用:
<template>
<view class="container">
<view class="format-item">
<text class="label">日期:</text>
<text class="value">{{ formattedDate }}</text>
</view>
<view class="format-item">
<text class="label">时间:</text>
<text class="value">{{ formattedTime }}</text>
</view>
<view class="format-item">
<text class="label">数字:</text>
<text class="value">{{ formattedNumber }}</text>
</view>
<view class="format-item">
<text class="label">货币:</text>
<text class="value">{{ formattedCurrency }}</text>
</view>
</view>
</template>
<script>
import { formatDate, formatTime, formatNumber, formatCurrency } from '@/utils/format'
export default {
computed: {
formattedDate() {
return formatDate(new Date(), this.$i18n.locale)
},
formattedTime() {
return formatTime(new Date(), this.$i18n.locale)
},
formattedNumber() {
return formatNumber(1234567.89, this.$i18n.locale)
},
formattedCurrency() {
const currency = this.$i18n.locale === 'zh-CN' ? 'CNY' : 'USD'
return formatCurrency(1234.56, currency, this.$i18n.locale)
}
}
}
</script>
<style>
.container {
padding: 20rpx;
}
.format-item {
display: flex;
margin-bottom: 20rpx;
}
.label {
width: 100rpx;
font-weight: bold;
}
.value {
flex: 1;
}
</style>国际化最佳实践
1. 语言包组织
- 按模块划分:将语言包按功能模块组织,如 login、home、user 等
- 使用命名空间:使用嵌套对象结构,避免翻译键冲突
- 统一命名规范:使用小写字母和下划线,保持命名一致性
2. 性能优化
- 懒加载语言包:只加载当前需要的语言包
- 缓存语言包:将语言包缓存到本地存储
- 避免频繁切换:减少不必要的语言切换操作
3. 用户体验
- 自动检测语言:根据设备语言设置自动选择应用语言
- 提供语言切换选项:在应用设置中提供语言切换功能
- 保存语言偏好:将用户选择的语言保存到本地存储
4. 特殊场景处理
- 文本方向:对于从右到左的语言(如阿拉伯语),需要调整布局方向
- 日期格式:不同地区的日期格式可能不同,需要使用国际化的日期格式化
- 货币符号:不同国家的货币符号位置可能不同,需要使用国际化的货币格式化
5. 开发工具
- 使用国际化插件:如 VS Code 的 i18n Ally 插件,提高开发效率
- 自动提取翻译键:使用工具自动从代码中提取需要翻译的文本
- 翻译管理系统:使用专业的翻译管理系统管理多语言内容
总结回顾
本章节介绍了 uni-app 中的国际化实现方法,包括:
- 国际化基础概念:了解国际化和本地化的区别,以及语言包的基本概念
- vue-i18n 插件使用:安装和配置 vue-i18n,创建语言包文件,在组件中使用国际化
- 动态语言切换:实现语言的动态切换和保存用户语言偏好
- 动态加载语言包:从服务器获取语言包,实现动态更新
- 日期和数字格式化:使用 Intl 对象格式化日期、时间和数字
- 国际化最佳实践:语言包组织、性能优化、用户体验和特殊场景处理
通过本章节的学习,您应该能够:
- 在 uni-app 中实现基本的国际化功能
- 创建和管理多语言语言包
- 实现动态语言切换和保存
- 处理日期、时间和数字的国际化
- 遵循国际化开发的最佳实践
国际化是现代应用开发的重要组成部分,通过合理的国际化实现,可以大大提升应用的用户体验和全球竞争力。在实际开发中,应根据应用的具体需求选择合适的国际化方案,并不断优化和完善国际化实现。