Vue I18n
Vue I18n 是 Vue 官方的国际化插件,专为 Vue 应用提供多语言支持 —— 在 CRM 系统中,若需适配海外客户、多语言团队协作、跨境业务场景,Vue I18n 是实现多语言切换的最优解。下面从「核心集成→实战配置→CRM 高频场景→性能优化」全维度讲解,贴合 Vue3 + TS 开发。
一、核心定位(CRM 为什么需要多语言?)
CRM 系统的多语言需求场景:
- 跨境业务:如面向东南亚 / 欧美客户的 CRM,需支持中文 / 英文 / 本地语言;
- 多语言团队:海外分公司员工使用,界面需适配当地语言;
- 合规要求:部分地区要求系统提供本地语言版本;
- 自定义语言包:支持客户按需配置行业专属术语(如外贸 CRM 的 “报关单” 多语言翻译)。
Vue I18n 核心优势:
- 深度适配 Vue3 组合式 API;
- 支持模板 / 脚本 / 组件内多语言;
- 按需加载语言包(减小打包体积);
- 支持变量插值、复数、日期 / 数字格式化(适配 CRM 动态数据)。
二、快速集成(Vue3 + Vite + TS)
1. 安装依赖
bash
运行
# Vue3 对应 vue-i18n@9+
npm install vue-i18n@9 -S
# TS 类型(库自带,无需额外安装)
2. 核心配置(全局初始化)
步骤 1:创建语言包文件
typescript
运行
// src/locales/zh-CN.ts(中文语言包)
export default {
common: {
save: '保存',
cancel: '取消',
submit: '提交',
delete: '删除',
search: '搜索',
reset: '重置'
},
customer: {
title: '客户管理',
name: '客户名称',
phone: '联系电话',
status: '客户状态',
active: '活跃',
inactive: '非活跃',
pending: '待跟进'
},
order: {
title: '订单管理',
id: '订单ID',
amount: '订单金额',
createTime: '创建时间',
status: {
pending: '待付款',
paid: '已付款',
completed: '已完成'
}
}
};
// src/locales/en-US.ts(英文语言包)
export default {
common: {
save: 'Save',
cancel: 'Cancel',
submit: 'Submit',
delete: 'Delete',
search: 'Search',
reset: 'Reset'
},
customer: {
title: 'Customer Management',
name: 'Customer Name',
phone: 'Phone Number',
status: 'Customer Status',
active: 'Active',
inactive: 'Inactive',
pending: 'Pending Follow-up'
},
order: {
title: 'Order Management',
id: 'Order ID',
amount: 'Order Amount',
createTime: 'Create Time',
status: {
pending: 'Pending Payment',
paid: 'Paid',
completed: 'Completed'
}
}
};
步骤 2:初始化 Vue I18n
typescript
运行
// src/locales/index.ts
import { createI18n } from 'vue-i18n';
// 导入语言包
import zhCN from './zh-CN';
import enUS from './en-US';
// 定义支持的语言列表
export const LOCALE_LIST = [
{ label: '中文', value: 'zh-CN' },
{ label: 'English', value: 'en-US' }
];
// 默认语言(优先从本地存储读取,否则用浏览器语言)
const defaultLocale = localStorage.getItem('crm-locale') || (navigator.language === 'en-US' ? 'en-US' : 'zh-CN');
// 创建 i18n 实例
const i18n = createI18n({
legacy: false, // 启用 Composition API 模式(必须!)
locale: defaultLocale, // 当前语言
fallbackLocale: 'zh-CN', // 回退语言(当翻译缺失时)
messages: {
'zh-CN': zhCN,
'en-US': enUS
},
// 全局格式化数字/日期(可选)
numberFormats: {
'zh-CN': {
currency: { style: 'currency', currency: 'CNY' } // 人民币格式化
},
'en-US': {
currency: { style: 'currency', currency: 'USD' } // 美元格式化
}
}
});
export default i18n;
步骤 3:全局注册(main.ts)
typescript
运行
import { createApp } from 'vue';
import App from './App.vue';
import i18n from './locales';
const app = createApp(App);
app.use(i18n); // 注册 i18n
app.mount('#app');
三、CRM 实战用法(核心场景)
场景 1:模板中使用多语言(最常用)
直接用 $t 或 t 函数(Composition API)渲染多语言文本:
vue
<template>
<!-- 基础翻译 -->
<div class="page-header">
<h1>{{ t('customer.title') }}</h1>
<button>{{ t('common.save') }}</button>
</div>
<!-- 嵌套翻译(订单状态) -->
<table>
<tr v-for="order in orderList" :key="order.id">
<td>{{ order.id }}</td>
<td>{{ t(`order.status.${order.status}`) }}</td>
<td>{{ t('common.delete') }}</td>
</tr>
</table>
<!-- 变量插值(动态内容) -->
<div>{{ t('common.notice', { count: unreadCount }) }}</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
// 组合式 API 引入 t 函数
const { t } = useI18n();
// 动态数据
const unreadCount = ref(5);
const orderList = ref([
{ id: 'ORD001', status: 'pending' },
{ id: 'ORD002', status: 'paid' }
]);
</script>
场景 2:脚本中使用多语言
在请求、逻辑处理中使用多语言(如提示文案):
vue
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { ElMessage } from 'element-plus';
const { t } = useI18n();
// 保存客户逻辑
const saveCustomer = async () => {
try {
await api.saveCustomer();
ElMessage.success(t('common.saveSuccess')); // 多语言提示
} catch (err) {
ElMessage.error(t('common.saveFailed'));
}
};
</script>
场景 3:语言切换组件(CRM 全局功能)
封装语言切换下拉框,切换后保存到本地存储:
vue
<template>
<el-select
v-model="currentLocale"
class="locale-select"
@change="handleLocaleChange"
>
<el-option
v-for="item in LOCALE_LIST"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { LOCALE_LIST } from '@/locales';
const { locale } = useI18n();
// 当前语言(双向绑定)
const currentLocale = ref(locale.value);
// 切换语言
const handleLocaleChange = (val: string) => {
locale.value = val; // 更新 i18n 语言
localStorage.setItem('crm-locale', val); // 保存到本地存储
// 可选:刷新页面(如需立即生效所有组件)
// window.location.reload();
};
</script>
场景 4:动态变量 & 复数处理(CRM 统计场景)
适配 “1 条记录”“2 条记录” 等复数场景,或动态插入变量:
typescript
运行
// 先在语言包中定义复数模板
// zh-CN.ts
{
"common": {
"recordCount": "共 {count} 条记录",
"notification": "你有 {count} 条未读消息 |||| 你有 {count} 条未读消息" // 复数格式(|||| 分隔)
}
}
// en-US.ts
{
"common": {
"recordCount": "Total {count} records",
"notification": "You have {count} unread message |||| You have {count} unread messages"
}
}
// 组件中使用
const { t } = useI18n();
console.log(t('common.recordCount', { count: 10 })); // 共 10 条记录
console.log(t('common.notification', { count: 1 })); // 你有 1 条未读消息
console.log(t('common.notification', { count: 5 })); // 你有 5 条未读消息
场景 5:数字 / 日期格式化(CRM 金额 / 时间)
利用 Vue I18n 内置的格式化能力,适配不同语言的数字 / 日期格式:
vue
<template>
<!-- 金额格式化(人民币/美元) -->
<p>{{ $n(order.amount, 'currency') }}</p>
<!-- 日期格式化 -->
<p>{{ $d(order.createTime, 'short') }}</p>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
const { n, d } = useI18n();
// 脚本中使用
const formatAmount = (amount: number) => {
return n(amount, 'currency');
};
</script>
// 配置日期格式化(locales/index.ts)
const i18n = createI18n({
// ...其他配置
datetimeFormats: {
'zh-CN': {
short: { year: 'numeric', month: '2-digit', day: '2-digit' } // 2026-03-20
},
'en-US': {
short: { month: '2-digit', day: '2-digit', year: 'numeric' } // 03/20/2026
}
}
});
四、性能优化(CRM 大型项目)
1. 按需加载语言包(减小首屏体积)
若语言包较大(如包含大量行业术语),可改为异步加载:
typescript
运行
// src/locales/index.ts
const i18n = createI18n({
legacy: false,
locale: 'zh-CN',
fallbackLocale: 'zh-CN',
messages: {
'zh-CN': import('./zh-CN') // 初始只加载中文
}
});
// 动态加载语言包
export const loadLocale = async (locale: string) => {
if (!i18n.global.availableLocales.includes(locale)) {
// 异步导入语言包
const messages = await import(`./${locale}.ts`);
i18n.global.setLocaleMessage(locale, messages.default);
}
i18n.global.locale.value = locale;
localStorage.setItem('crm-locale', locale);
};
// 语言切换时调用
// handleLocaleChange = async (val) => {
// await loadLocale(val);
// };
2. 避免模板中频繁调用 t 函数
频繁调用 t('xxx') 会触发多次翻译解析,可缓存翻译结果:
vue
<script setup lang="ts">
import { useI18n, computed } from 'vue-i18n';
const { t } = useI18n();
// 缓存翻译结果
const translate = computed({
get() {
return {
save: t('common.save'),
cancel: t('common.cancel')
};
}
});
</script>
<template>
<button>{{ translate.save }}</button>
<button>{{ translate.cancel }}</button>
</template>
3. 翻译缺失兜底
配置 missingWarn 关闭开发环境警告,自定义缺失翻译处理:
typescript
运行
const i18n = createI18n({
// ...其他配置
missingWarn: false, // 关闭缺失翻译警告
fallbackWarn: false,
// 自定义缺失翻译处理
missing: (locale, key) => {
console.warn(`[i18n] 缺失翻译:${key} (${locale})`);
return `[${key}]`; // 兜底显示 key
}
});
五、核心避坑点
1. legacy: false 必须设置
忘记设置 legacy: false 会导致 Composition API(useI18n)无法使用,报 t is not a function 错误。
2. 动态 key 翻译不生效
问题:t(order.status.${status}) 若 status 为动态值,开发环境可能不生效;解决方案:
- 确保语言包中存在对应 key;
- 开发环境禁用
vue-i18n的缓存:i18n.global.setLocaleMessage(locale, messages)。
3. 本地存储语言不生效
问题:切换语言后刷新页面,语言还原;解决方案:初始化时优先从 localStorage 读取语言(如配置中的 defaultLocale)。
4. 第三方组件(如 Element Plus)多语言
需单独配置 Element Plus 多语言,与 Vue I18n 联动:
typescript
运行
// main.ts
import ElementPlus from 'element-plus';
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
import enUs from 'element-plus/dist/locale/en.mjs';
import i18n from './locales';
// 动态切换 Element Plus 语言
const updateElementLocale = (locale: string) => {
const app = createApp(App);
app.use(ElementPlus, {
locale: locale === 'zh-CN' ? zhCn : enUs
});
};
// 初始化时调用
updateElementLocale(i18n.global.locale.value);
// 语言切换时重新调用
六、总结(CRM 开发最佳实践)
- 适用场景:
-
- 需多语言支持的跨境 CRM、多语言团队协作场景;
- 纯中文 CRM 无需引入 Vue I18n,完全没必要;
- 核心配置:
-
- 按模块拆分语言包(common/customer/order),便于维护;
- 语言切换后保存到本地存储,刷新不丢失;
- 性能优化:
-
- 大型 CRM 按需加载语言包,缓存翻译结果;
- 自定义缺失翻译兜底,避免页面显示空白;
- 集成第三方组件:
-
- 同步 Element Plus 等第三方组件的多语言,保证体验一致。
Vue I18n 是 CRM 多语言场景的 “刚需工具”,但纯中文场景下完全可以不用;若需多语言,按上述配置可快速实现全系统多语言切换,兼顾性能与可维护性。
更多推荐

所有评论(0)