国际化(i18n)是多语言项目的核心需求,本文将带你从零开始配置 Vue 3 项目的国际化功能,包括基础翻译、语言切换、第三方组件库(如 VXETable)适配,以及解决常见的插件报错问题。
1. 技术栈
- Vue 3(Composition API)
- TypeScript
vue-i18n
(v9+,Vue 3 专用版本)- Vite(构建工具,本文示例基于 Vite)
- 可选:i18n-ally(VS Code 插件,辅助翻译开发)
首先安装 vue-i18n
:
sql
npm install vue-i18n@9 --save
# 或
yarn add vue-i18n@9
涉及配置的文件
perl
src/
└── i18n
| └──locales/
| └── zh-CN/ # 中文语言包
| │ └── test.json # 业务模块翻译
| │ └── index.json # 暴露全部的json
| └── en/ # 英文语言包
| | └── test.json
| | └── index.json # 暴露全部的json
| └──index.ts # 国际化配置
| └──use-locale.ts # 监听引入组件(按需求引入)
└──main.ts # 入口文件配置
使用
ts
/* src/i18n/locales/zh-CN/index.ts */
// 暴露出当前文件所有的中文配置
const zhLocale = Object.fromEntries(
Object.entries(import.meta.glob('./*.json', { eager: true })
).map(([key, value]) => {
const moduleName = key.replace(/^\.\/(.*)\.json$/, '$1')
return [moduleName, (value as any).default]
})
)
export default zhLocale
json
/* src/i18n/locales/zh-CN/test.json */
{
"haha": "哈哈"
}
ts
/* src/i18n/locales/en/index.ts */
const enLocale = Object.fromEntries(
Object.entries(import.meta.glob('./*.json', { eager: true })
).map(([key, value]) => {
const moduleName = key.replace(/^\.\/(.*)\.json$/, '$1')
return [moduleName, (value as any).default]
})
)
export default enLocale
json
/* src/i18n/locales/en/test.json */
{
"haha": "haha"
}
ts
/* src/i18n/locales/index.ts */
// 国际化配置
import { createI18n } from 'vue-i18n'
import zhLocale from './locales/zh-CN'
import enLocale from './locales/en'
/* 这里根据情况导入,用到什么引入什么 */
// VXETable国际化
import zhCN from 'vxe-pc-ui/lib/language/zh-CN'
import en from 'vxe-table/lib/locale/lang/en-US'
const messages = {
zh_CN: { ...zhLocale, ...zhCN },
en: { ...enLocale, ...en }
}
console.log('messages',messages)
// 本地获取储存的默认的语言(如果没有就使用中文)
const defaultLocale = localStorage.getItem('localelanguage') || 'zh_CN'
// 语言配置
const localesLanguage = createI18n({
messages,
locale: defaultLocale,
fallbackLocale: 'zh_CN', //翻译缺失的时候使用
legacy: false,//使用 composition API 模式
globalInjection: true, //全局注册$t函数
})
export default localesLanguage
ts
/* src/i18n/locales/use-locale.ts */
/**
* AntDesignVue、Dayjs 国际化配置
*/
import { ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import type { Locale } from 'ant-design-vue/es/locale-provider'
// AntDesignVue
import zh_CN from 'ant-design-vue/es/locale/zh_CN'
import en from 'ant-design-vue/es/locale/en_US'
// Dayjs
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
import 'dayjs/locale/zh-tw'
const antLocales = { zh_CN, en }
const eleLocales = { zh_CN: eleZh_CN, en: eleEn }
export function useLocale() {
const { locale } = useI18n()
const antLocale = ref<Locale>()
watch(
locale,
() => {
antLocale.value = antLocales[locale.value]
dayjs.locale(locale.value.toLowerCase().replace(/_/g, '-'))
},
{ immediate: true }
)
return { antLocale }
}
vue
//任意vue文件测试
<template>
<div>
<div>{{ t("test.haha") }}</div>
<el-button
type="primary"
@click="changeLanguege('zh_CN')"
v-if="language.includes('en')"
>English</el-button
>
<el-button
type="primary"
@click="changeLanguege('en')"
v-if="language.includes('zh_CN')"
>简体中文</el-button
>
</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const { locale } = useI18n();
const language = computed(() => [locale.value]);
const changeLanguege = (lang: string) => {
locale.value = lang;
console.log("Current language:", locale.value);
};
</script>