国际化(i18n)
23:18概述
本项目使用 uView Pro 内置的 useLocale 实现国际化,彻底替代 vue-i18n。uView Pro 的国际化方案同时覆盖组件库内置文案与项目业务文案,支持响应式切换与持久化,所有文本内容都能实时更新。
项目特性
- 🌍 多语言支持 - 支持中文、英文等多语言
- 🔄 动态切换 - 运行时即时切换语言无需重新加载
- 📦 JSON 配置 - 使用 JSON 文件管理语言包
- 💬 组件级别 - 支持在组件中使用翻译
- 🎯 类型安全 - TypeScript 支持完整的类型检查
- 🔧 Composables 使用 - 通过
useLocale提供的t()函数进行翻译
初始化配置
uView Pro 配置
在 src/main.ts 中:
typescript
import uViewPro from 'uview-pro'
import { createSSRApp } from 'vue'
import { enUS, zhCN } from '@/locale'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
app.use(uViewPro, {
theme: {
// ...主题配置
},
locale: {
locales: [zhCN, enUS], // 注册语言包
defaultLocale: 'zh-CN', // 默认语言
},
})
return {
app,
}
}语言包结构
简体中文语言包
创建 src/locale/lang/zh-CN.json:
json
{
"name": "zh-CN",
"label": "简体中文",
"locale": "zh-Hans",
"common": {
"appName": "uView Pro 启动项目",
"home": "首页",
"about": "关于",
"settings": "设置",
"logout": "退出登录",
"confirm": "确定",
"cancel": "取消",
"loading": "加载中...",
"noData": "暂无数据"
},
"home": {
"welcome": "欢迎使用 uView Pro",
"description": "这是一个快速启动项目"
},
"about": {
"title": "关于我们",
"version": "版本"
}
}英文语言包
创建 src/locale/lang/en-US.json:
json
{
"name": "en-US",
"label": "English",
"locale": "en",
"common": {
"appName": "uView Pro Starter",
"home": "Home",
"about": "About",
"settings": "Settings",
"logout": "Logout",
"confirm": "OK",
"cancel": "Cancel",
"loading": "Loading...",
"noData": "No Data"
},
"home": {
"welcome": "Welcome to uView Pro",
"description": "This is a quick start project"
},
"about": {
"title": "About Us",
"version": "Version"
}
}语言包导出
在 src/locale/index.ts 中导出语言包:
typescript
import enUS from './lang/en-US.json' // 英文
import zhCN from './lang/zh-CN.json' // 简体中文
export {
enUS,
zhCN,
}注意:每个语言包必须包含以下三个字段:
name:语言包唯一标识(如zh-CN、en-US)label:语言显示名称(如简体中文、English)locale:uni-app 语言标识(如zh-Hans、en)
基本使用
在 Script 中使用
vue
<script setup lang="ts">
import { useLocale } from 'uview-pro'
const { t } = useLocale()
const appName = t('common.appName')
const message = t('home.welcome')
function getMessage() {
return t('common.loading')
}
</script>在模板中使用
vue
<script setup lang="ts">
import { useLocale } from 'uview-pro'
const { t } = useLocale()
</script>
<template>
<view class="container">
<!-- 使用 t 翻译文本 -->
<text>{{ t('common.appName') }}</text>
<text>{{ t('home.welcome') }}</text>
</view>
</template>带参数的翻译
语言包配置
json
{
"messages": {
"hello": "你好,{name}",
"count": "你有 {count} 条消息"
}
}使用翻译
vue
<script setup lang="ts">
import { useLocale } from 'uview-pro'
const { t } = useLocale()
// 简单参数
const greeting = t('messages.hello', { name: '张三' })
// 输出: 你好,张三
// 复数形式
const message = t('messages.count', { count: 5 })
// 输出: 你有 5 条消息
</script>
<template>
<text>{{ greeting }}</text>
<text>{{ message }}</text>
</template>高级用法
动态切换语言
创建 src/composables/useLang.ts:
typescript
import { useLocale } from 'uview-pro'
export function useLang() {
const { setLocale } = useLocale()
// 切换语言
function switchLang(lang: string, locale?: string) {
// 切换 uniapp 语言
locale && uni.setLocale(locale)
uni.setStorageSync('UNI_LOCALE', locale)
// 切换 uView Pro 语言
setLocale(lang)
}
return {
switchLang,
}
}在组件中使用:
vue
<script setup lang="ts">
import { useLocale } from 'uview-pro'
import { useLang } from '@/composables'
const { t, locales, currentLocale } = useLocale()
const { switchLang } = useLang()
function selectLocale(lang: string, locale?: string) {
switchLang(lang, locale)
}
</script>
<template>
<view class="locale-selector">
<text>当前语言:{{ currentLocale.label }}</text>
<view v-for="loc in locales" :key="loc.name">
<u-button
:type="currentLocale.name === loc.name ? 'primary' : 'default'"
@click="selectLocale(loc.name, loc.locale)"
>
{{ loc.label }}
</u-button>
</view>
</view>
</template>useLocale API 详解
typescript
import { useLocale } from 'uview-pro'
const { t, setLocale, currentLocale, locales } = useLocale()| 属性/方法 | 类型 | 说明 |
|---|---|---|
t | (key: string, params?: Record<string, any>) => string | 翻译函数,支持参数替换 |
setLocale | (name: string) => void | 切换语言 |
currentLocale | Ref<Locale> | 当前语言对象,包含 name、label、locale 等 |
locales | Ref<Locale[]> | 已注册的所有语言包列表 |
指定命名空间翻译
typescript
import { useLocale } from 'uview-pro'
// 指定 uModal 命名空间
const { t } = useLocale('uModal')
const text = t('confirmText') // 等价于 t('uModal.confirmText')
// 等价于
const { t } = useLocale()
const text = t('uModal.confirmText')常见场景
条件渲染
vue
<script setup lang="ts">
import { useLocale } from 'uview-pro'
const { currentLocale } = useLocale()
</script>
<template>
<view v-if="currentLocale.name === 'zh-CN'" class="zh-only">
仅中文显示
</view>
<view v-else class="en-only">
English only
</view>
</template>嵌套翻译
json
{
"user": {
"profile": {
"name": "姓名",
"email": "邮箱"
}
}
}使用:
vue
<template>
<text>{{ t('user.profile.name') }}</text>
</template>动态翻译
typescript
const keys = ['home.welcome', 'home.description', 'about.title']
const translations = keys.map(key => t(key))组织大型项目的语言包
对于大型项目,建议分文件组织:
src/locale/
├── index.ts
└── lang/
├── zh-CN/
│ ├── index.ts
│ ├── common.json
│ ├── home.json
│ ├── about.json
│ └── user.json
└── en-US/
├── index.ts
├── common.json
├── home.json
├── about.json
└── user.jsonsrc/locale/lang/zh-CN/index.ts:
typescript
import about from './about.json'
import common from './common.json'
import home from './home.json'
import user from './user.json'
export default {
name: 'zh-CN',
label: '简体中文',
locale: 'zh-Hans',
common,
home,
about,
user,
}覆盖组件库默认语言包
uView Pro 内置了组件的默认文案,你可以在注册时局部覆盖:
typescript
// main.ts
app.use(uViewPro, {
locale: {
locales: [{
name: 'zh-CN',
label: '简体中文',
locale: 'zh-Hans',
modal: {
confirmText: '好的', // 自定义确认按钮文案
cancelText: '算了' // 自定义取消按钮文案
},
upload: {
uploadText: '选择文件' // 自定义上传文案
}
}],
defaultLocale: 'zh-CN'
}
})添加新语言包
假设我们要为应用添加法语支持:
typescript
// 首先创建法语语言包文件
// src/locale/lang/fr-FR.ts
export default {
name: 'fr-FR', // 必须要有
label: 'Français', // 必须要有
locale: 'fr', // 必须要有
common: {
appName: 'Projet de démarrage uView Pro',
home: 'Accueil',
about: 'À propos',
settings: 'Paramètres'
},
home: {
welcome: 'Bienvenue sur uView Pro',
description: 'Ceci est un projet de démarrage rapide'
}
// ... 继续添加其他翻译
}在入口注册时引入并添加该语言包:
typescript
// main.ts
import frFR from './locale/lang/fr-FR'
app.use(uViewPro, {
locale: {
locales: [zhCN, enUS, frFR], // 添加法语语言包
defaultLocale: 'zh-CN'
}
})最佳实践
- 统一的 key 命名规范 - 使用
module.feature.name的命名方式 - 避免硬编码 - 所有可见文本都应该使用翻译
- 为默认语言优化 - 确保默认语言的翻译质量最高
- 使用回退语言 - uView Pro 会自动回退到默认语言处理缺失的翻译
- 注意文本长度 - 不同语言的文本长度可能差异很大,要在 UI 设计时考虑
- 测试多语言 - 在所有支持的语言环境下进行测试
- 定期审查 - 定期检查和更新翻译内容
故障排除
翻译不显示
- 检查语言包文件是否存在
- 检查 key 是否拼写正确
- 确保
name、label、locale三个必填字段已配置 - 在浏览器控制台检查是否有错误信息
语言不切换
typescript
// 确保使用正确的方式修改 locale
import { useLocale } from 'uview-pro'
const { setLocale } = useLocale()
// 正确
setLocale('en-US')
// 错误 - 不要直接修改 currentLocale
// currentLocale.value = 'en-US'H5 开发时数据不同步
非 uni_modules 模式下,需在 vite.config.ts 中添加配置排除预构建:
typescript
import { defineConfig } from 'vite'
export default defineConfig({
// ...
optimizeDeps: {
exclude: process.env.UNI_PLATFORM === 'h5' && process.env.NODE_ENV === 'development'
? ['uview-pro']
: []
}
})uni_modules 模式无需额外处理。
