Skip to content

国际化(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-CNen-US
  • label:语言显示名称(如 简体中文English
  • locale:uni-app 语言标识(如 zh-Hansen

基本使用

在 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切换语言
currentLocaleRef<Locale>当前语言对象,包含 namelabellocale
localesRef<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.json

src/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'
  }
})

最佳实践

  1. 统一的 key 命名规范 - 使用 module.feature.name 的命名方式
  2. 避免硬编码 - 所有可见文本都应该使用翻译
  3. 为默认语言优化 - 确保默认语言的翻译质量最高
  4. 使用回退语言 - uView Pro 会自动回退到默认语言处理缺失的翻译
  5. 注意文本长度 - 不同语言的文本长度可能差异很大,要在 UI 设计时考虑
  6. 测试多语言 - 在所有支持的语言环境下进行测试
  7. 定期审查 - 定期检查和更新翻译内容

故障排除

翻译不显示

  1. 检查语言包文件是否存在
  2. 检查 key 是否拼写正确
  3. 确保 namelabellocale 三个必填字段已配置
  4. 在浏览器控制台检查是否有错误信息

语言不切换

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 模式无需额外处理。

相关文档