✅ vue-i18n 集成 ✅ 模块化语言包管理 ✅ 中英文双语支持 ✅ 语言切换功能 ✅ 持久化存储 ✅ Pinia 状态管理 ✅ 可复用组件 ✅ 完整文档
intelligent-etmf-system-applet/
├── i18n/ # i18n 配置
│ ├── index.js # i18n 初始化
│ └── README.md # 使用文档
├── locales/ # 语言包(按模块分组)
│ ├── common/ # 通用模块
│ │ ├── zh_CN.js # 中文翻译
│ │ └── en_US.js # 英文翻译
│ ├── pages/ # 页面模块
│ │ └── home/ # 首页
│ │ ├── zh_CN.js # 中文翻译
│ │ └── en_US.js # 英文翻译
│ ├── components/ # 组件模块
│ │ └── languageSwitcher/ # 语言切换组件
│ │ ├── zh_CN.js # 中文翻译
│ │ └── en_US.js # 英文翻译
│ ├── index.js # 语言包总导出
│ ├── README.md # 语言包管理文档
│ ├── STRUCTURE.md # 目录结构说明
│ └── COMPONENT_I18N.md # 组件国际化指南
├── store/ # 状态管理
│ └── locale.js # 语言切换 store
├── utils/ # 工具函数
│ └── i18n.js # i18n 工具函数
├── components/ # 组件
│ └── LanguageSwitcher/ # 语言切换组件
│ └── index.vue
└── main.js # 已集成 i18n
<template>
<view>
<!-- 基础用法 -->
<text>{{ t('home.title') }}</text>
<!-- 嵌套键 -->
<text>{{ t('common.button.submit') }}</text>
<!-- 带参数 -->
<text>{{ t('common.greeting', { name: userName }) }}</text>
</view>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const userName = '张三'
</script>
<template>
<view class="user-card">
<!-- 使用组件专属翻译 -->
<text>{{ t('components.userCard.title') }}</text>
<!-- 使用通用翻译 -->
<button>{{ t('common.button.confirm') }}</button>
<!-- 动态键 -->
<text>{{ t(`components.userCard.status.${user.status}`) }}</text>
</view>
</template>
<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const props = defineProps({
user: Object
})
</script>
<template>
<view class="header">
<!-- 方式1:使用封装的组件 -->
<LanguageSwitcher />
<!-- 方式2:自定义切换逻辑 -->
<button @click="changeLanguage">切换语言</button>
</view>
</template>
<script setup>
import { useLocaleStore } from '@/store/locale'
import LanguageSwitcher from '@/components/LanguageSwitcher/index.vue'
const localeStore = useLocaleStore()
const changeLanguage = () => {
// 切换到下一个语言
localeStore.toggleLocale()
// 或切换到指定语言
// localeStore.setLocale('en-US')
}
</script>
import { t } from '@/utils/i18n'
// 在 API 请求中使用
const showError = () => {
uni.showToast({
title: t('common.message.error'),
icon: 'none'
})
}
// 在工具函数中使用
const formatStatus = (status) => {
return t(`order.status.${status}`)
}
创建 UserCard 组件的翻译:
locales/components/userCard/zh_CN.js 和 en_US.jslocales/index.js 中注册到 components 下t('components.userCard.title')详细指南:请查看 组件国际化指南
在对应目录下创建语言文件。例如创建产品管理页面模块:
创建 locales/pages/product/zh_CN.js:
export default {
title: '产品管理',
list: {
title: '产品列表',
empty: '暂无产品'
},
detail: {
name: '产品名称',
price: '价格',
stock: '库存'
},
action: {
add: '添加产品',
edit: '编辑',
delete: '删除'
}
}
创建 locales/pages/product/en_US.js:
export default {
title: 'Product Management',
list: {
title: 'Product List',
empty: 'No products'
},
detail: {
name: 'Product Name',
price: 'Price',
stock: 'Stock'
},
action: {
add: 'Add Product',
edit: 'Edit',
delete: 'Delete'
}
}
在 locales/index.js 中导入新模块:
// 导入通用模块
import commonZhCN from './common/zh_CN'
import commonEnUS from './common/en_US'
// 导入页面模块
import homeZhCN from './pages/home/zh_CN'
import homeEnUS from './pages/home/en_US'
import productZhCN from './pages/product/zh_CN' // 新增
import productEnUS from './pages/product/en_US' // 新增
// 导入组件模块
import languageSwitcherZhCN from './components/languageSwitcher/zh_CN'
import languageSwitcherEnUS from './components/languageSwitcher/en_US'
export const messages = {
'zh-CN': {
common: commonZhCN,
home: homeZhCN,
product: productZhCN, // 新增
components: {
languageSwitcher: languageSwitcherZhCN
}
},
'en-US': {
common: commonEnUS,
home: homeEnUS,
product: productEnUS, // 新增
components: {
languageSwitcher: languageSwitcherEnUS
}
}
}
注意:
components 对象下<template>
<view>
<text>{{ t('product.title') }}</text>
<text>{{ t('product.detail.name') }}</text>
</view>
</template>
为每个现有模块创建新语言的翻译文件:
locales/
├── common/
│ ├── zh_CN.js
│ ├── en_US.js
│ └── ja_JP.js # 新增日文
└── pages/
└── home/
├── zh_CN.js
├── en_US.js
└── ja_JP.js # 新增日文
在 locales/index.js 中:
import commonZhCN from './common/zh_CN'
import commonEnUS from './common/en_US'
import commonJaJP from './common/ja_JP' // 新增
import homeZhCN from './pages/home/zh_CN'
import homeEnUS from './pages/home/en_US'
import homeJaJP from './pages/home/ja_JP' // 新增
export const messages = {
'zh-CN': {
common: commonZhCN,
home: homeZhCN
},
'en-US': {
common: commonEnUS,
home: homeEnUS
},
'ja-JP': { // 新增
common: commonJaJP,
home: homeJaJP
}
}
export const localeList = [
{ label: '简体中文', value: 'zh-CN' },
{ label: 'English', value: 'en-US' },
{ label: '日本語', value: 'ja-JP' } // 新增
]
locales/common/ 下pages/home/、pages/user/),每个子目录下包含各语言版本api/、components/ 等)优势:
// ✅ 推荐:清晰的层级结构
{
user: {
profile: {
title: '个人资料',
field: {
name: '姓名',
email: '邮箱'
}
}
}
}
// ❌ 不推荐:扁平结构
{
userProfileTitle: '个人资料',
userProfileFieldName: '姓名'
}
// 定义
{
welcome: '欢迎,{name}!',
itemCount: '共 {count} 项'
}
// 使用
t('common.welcome', { name: '张三' })
t('common.itemCount', { count: 10 })
确保同一模块下所有语言文件的翻译键完全一致:
// ✅ 正确:locales/pages/user/zh_CN.js 和 locales/pages/user/en_US.js 键名相同
// zh_CN.js
{ user: { name: '姓名' } }
// en_US.js
{ user: { name: 'Name' } }
// ❌ 错误:键名不一致
// zh_CN.js
{ user: { name: '姓名' } }
// en_US.js
{ user: { userName: 'Name' } } // 键名不同!
提示:建议同时打开同一模块的不同语言文件进行对比编辑
const localeStore = useLocaleStore()
// 状态
localeStore.currentLocale // 当前语言:'zh-CN' | 'en-US'
localeStore.availableLocales // 可用语言列表
// 方法
localeStore.setLocale('en-US') // 切换到指定语言
localeStore.toggleLocale() // 切换到下一个语言
localeStore.getCurrentLocaleName() // 获取当前语言显示名称
const { t, locale, te } = useI18n()
t('home.title') // 翻译文本
t('common.greeting', { name: 'John' }) // 带参数翻译
locale.value // 当前语言
te('home.title') // 检查键是否存在
import { t, getLocale, setLocale, hasKey } from '@/utils/i18n'
t('home.title') // 翻译文本
getLocale() // 获取当前语言
setLocale('en-US') // 设置语言
hasKey('home.title') // 检查键是否存在
原因:翻译键不存在或拼写错误
解决:
原因:使用了非响应式的方式获取翻译
解决:
// ❌ 错误:在 setup 外部获取
const title = t('home.title')
// ✅ 正确:在模板中使用或使用 computed
{{ t('home.title') }}
// 或
const title = computed(() => t('home.title'))
原因:i18n 配置不兼容
解决:确保使用以下配置
createI18n({
legacy: false, // 必须:使用 Composition API
globalInjection: true, // 必须:全局注入
// ...
})
如有问题或建议,请联系项目维护者。