1.介绍自定义国际化和ElementPlus组件国际化
国际化i18n分为自定义词库国际化和ElementPlus组件国际化
2.实现两者的步骤
安装 vue-i18n
bash
npm i vue-i18n
创建i18n配置文件i18n.ts:
ts
// i18n.ts
import { App } from 'vue'
import { createI18n } from 'vue-i18n'
const install = (app: App) => {
const messages = {
en: {
// 定义你自己的字典,但是请不要和 `el` 重复,这样会导致 ElementPlus 内部组件的翻译失效.
message: {
hello: 'hello world',
},
button:{
default:"button"
}
},
zhCn: {
// 定义你自己的字典,但是请不要和 `el` 重复,这样会导致 ElementPlus 内部组件的翻译失效.
message: {
hello: '你好,世界',
},
button:{
default:"按钮"
}
}
}
const i18n = createI18n({
legacy: false,
globalInjection: true, // 全局模式,可以直接使用 $t 调用 i18n
locale: 'zhCn', //默认为中文模式
fallbackLocale: 'en',
// @ts-ignore
messages
})
app.use(i18n)
}
export default install
注:上面的en和zhCn配置项可以作为单独js文件,然后引入i18n.ts中,能够解耦
在main.js中引入i18n.ts:
js
import { install } from "./i18n"; //{}这样引入就不需要use了,可以直接合并进js代码里面
在App.vue中使用el-config-provider,并书写相关方法实现自定义词库国际化和ElementPlus组件国际化的实现
vue
<!-- TODO: 测试国际化 -->
<script lang="ts">
import { computed, defineComponent, ref } from "vue";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import en from "element-plus/lib/locale/lang/en";
import HelloWorld from "./components/HelloWorld.vue";
type localType = "zhCn" | "en"; //只有ts里面可以这么写,自定义类型
export default defineComponent({
components: {
HelloWorld,
},
setup() {
const local = ref<localType>("zhCn");
const localLanguage = computed(() => {
switch (local.value) {
case "en":
return en;
case "zhCn":
return zhCn;
}
});
return {
local,
localLanguage,
};
},
methods: {
/**
* 切换语言
* @param type
*/
changeLanguage(type: localType): void {
this.local = type;
this.$i18n.locale = type; //只有在methods这才能拿到this,setup里面拿不到
},
},
});
</script>
<template>
<!-- TODO: 测试国际化 -->
<el-config-provider :locale="localLanguage">
<HelloWorld @change="changeLanguage" />
</el-config-provider>
</template>
在HelloWorld.vue中定义按钮,切换中英文,调用外部父组件的方法
vue
<template>
<!-->在这里用$t调用i18n里面定义的内容,$t就相当于i18n对象</-->
<el-button>{{ $t("button.default") }}</el-button>
<el-date-picker v-model="value1" type="date" placeholder="选择日期">
</el-date-picker>
<el-dropdown @command="changeLanguage">
<el-button type="primary">
切换语言<i class="el-icon-arrow-down el-icon--right" />
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="zhCn"> 中文 </el-dropdown-item>
<el-dropdown-item command="en"> 英文 </el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script lang="ts">
import { defineComponent } from "vue";
type localType = "zhCn" | "en";
export default defineComponent({
setup() {
return {
value1: "",
};
},
methods: {
/**
* 切换语言
* @param type
*/
changeLanguage(type: localType): void {
this.$emit("change", type);
},
},
});
</script>
3.目录结构优化解耦
- 在src下 新建 locales 文件夹
以简体中文
和英文
为例
- 在 locales 文件夹下新建 zh-cn.ts
ts
export default {
buttons: {
login: '登录'
},
menus: {
home: '首页'
}
}
- 在 locales 文件夹下新建 en.ts
ts
export default {
buttons: {
login: 'Login'
},
menus: {
home: 'Home'
}
}
- 在 locales 文件夹下新建 index.ts(就相当于之前的i18n.ts)
ts
// i18n.ts
import { App } from 'vue'
import { createI18n } from 'vue-i18n'
import zhCn from './zh-cn'
import en from './en'
const install = (app: App) => {
const messages = {
zhCn,
en
}
const i18n = createI18n({
legacy: false,
globalInjection: true, // 全局模式,可以直接使用 $t 调用 i18n
locale: 'zhCn', //默认为中文模式
fallbackLocale: 'en',
// @ts-ignore
messages
})
app.use(i18n)
}
export default install
4.如何使用i18n对象
4.1 在 template 中的使用
前提:在main.js中引入了index.ts
js
{{ $t('menus.home') }}
4.2 在 ts 中的使用
但是这个时候要使用的话要改变index.ts写法:
ts
// i18n.ts
import { App } from 'vue'
import { createI18n } from 'vue-i18n'
import zhCn from './zh-cn'
import en from './en'
const i18n = createI18n({
legacy: false,
globalInjection: true, // 全局模式,可以直接使用 $t 调用 i18n
locale: 'zhCn', //默认为中文模式
fallbackLocale: 'en',
// @ts-ignore
messages:{
zhCn,
en
}
})
export default i18n
使用:
js
import i18n from './locales'
i18n.global.t('menus.home')
注意:但是这个时候注册在main.js中需要这样:
js
import i18n from "./i18n";
app.use(i18n);
5.elementPlus优化:使用Pinia进行状态管理
Element Plus 官方提供了一个 Vue 组件 ConfigProvider 用于全局配置国际化的设置
修改 locales 文件夹下的 index.ts
修改这句即可 locale: localStorage.getItem('lang') || 'zhCn',
ts
import { App } from 'vue'
import { createI18n } from 'vue-i18n'
import zhCn from './zh-cn'
import en from './en'
const i18n = createI18n({
legacy: false,
globalInjection: true, // 全局模式,可以直接使用 $t 调用 i18n
locale: localStorage.getItem('lang') || 'zhCn',, //之前默认为中文模式,现在是根据本地存储的值决定默认值,所以可以记住用户的选择,关闭浏览器依然成立,所以用户会越用越好用!
fallbackLocale: 'en',
messages:{
zhCn,
en
}
})
export default i18n
修改App.vue
vue
<!-- TODO: 测试国际化 -->
<script lang="ts">
import { computed, defineComponent, ref } from "vue";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import en from "element-plus/lib/locale/lang/en";
import HelloWorld from "./components/HelloWorld.vue";
import { useAppStoreHook } from '@/store/modules/app' //store存放语言配置,这里的useAppStoreHook函数调用后产生的对象就是store对象了
// type localType = "zhCn" | "en"; //只有ts里面可以这么写,自定义类型
export default defineComponent({
components: {
HelloWorld,
},
setup() {
// const local = ref<localType>("zhCn");
const store = useAppStoreHook(); //得到store对象
const localLanguage = computed(() => {
switch (store.local) { //这里应该判断的是store存储的值,进行计算属性,监听变化
case "en":
return en;
case "zhCn":
return zhCn;
}
});
return {
store,
localLanguage,
};
},
methods: {
changeLanguage(type: localType): void { //参数为type,参数类型为localType,返回值类型为void
//这里写调用修改store存储的值的方法
store.local = type;
this.$i18n.locale = type;
// 原来的:
// this.local = type;
// this.$i18n.locale = type; //只有在methods这才能拿到this,setup里面拿不到
},
},
});
</script>
<template>
<!-- TODO: 测试国际化 -->
<el-config-provider :locale="localLanguage">
<HelloWorld @change="changeLanguage"/>
</el-config-provider>
</template>
在src下面创建store文件夹:
store/modules/app.js
js
// store/modules/app
import { defineStore } from 'pinia'
import { store } from '@/store' //感觉是可有可无的
import i18n from '@/locales'
const useAppStore = defineStore('app', {
state: () => {
return {
locale: localStorage.getItem('lang') || 'zhCn'
}
},
actions: {
SET_LOCALE(locale: string) { //语言切换
this.locale = locale
storageLocal.setItem('lang', locale) //这里可能是localStorage更合适一些?
i18n.global.locale.value = locale
}
}
})
// 一般情况下,下面这些代码不用写,除非想给其传入新的store,否则直接在上面的const useAppStore前面加export即可了
export function useAppStoreHook() {
//返回store对象
return useAppStore(store) //这里传的实参感觉也是可有可无的
}