在使用Vue-I18n、Element-Plus的国际化过程中,遇到了Element-Plus组件国际化以及在js定义一个数组,并将这个数据展示到页面上切换语言环境不生效问题,踩了一些坑,所以记录一下最终解决结果,以防以后再次遇到可以回溯查询。
前期准备
安装Element-Plus、vue-i18n
yarn add element-plus
yarn add vue-i18n@10
引入Element-Plus组件库
// main.js
import { createApp } from "vue";
import App from "./App.vue";
// 引入ElementPlus
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
const app = createApp(App);
app.use(ElementPlus).mount("#app");
创建vue-i18n实例,并整合Element-Plus的语言包
// i18.js
import { createI18n } from "vue-i18n";
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import en from 'element-plus/es/locale/lang/en';
const Chinese = {
common: {
title: '标题',
theme: '主题',
}
}
const English = {
common: {
title: 'Title',
theme: 'Theme',
}
}
const i18n = createI18n({
legacy: false, // Composition API 模式, 如果想要在js中运用国际化需要配置该项
globalInjection: true, // 全局注册 $t方法
locale: localStorage.getItem('lan') || "chinese",
allowComposition: true,
messages: {
// 整合Element-Plus中英文语言包
chinese: {...Chinese, ...zhCn},
english: {...English, ...en}
},
});
export default i18n;
引入vue-i18n
// main.js
import { createApp } from "vue";
import App from "./App.vue";
// 引入ElementPlus
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
// 引入i18n国际化
import i18n from './i18n.js'
const app = createApp(App);
app.use(ElementPlus).use(i18n).mount("#app");
动态切换语言环境
vue-i18n
- 修改vue-i18n实例中locale的值,实现语言环境的动态切换
<template>
<div>
<button @click="changeLanguage('english')">English</button>
<button @click="changeLanguage('chinese')">中文</button>
</div>
</template>
<script setup>
import { useI18n } from 'vue-i18n';
const { locale } = useI18n();
const changeLanguage = (lang) => {
locale.value = lang;
localStorage.setItem('lan', lang) // localStorage不会被vue响应式监听器监听到,所以语言切换不是实时的需要刷新页面才能生效
};
// 实时生效的方法,使用pinia等状态库对lan的值进行存储和更新
</script>
语言实时更新
// 安装pinia
yarn add pinia
// main.js
import App from './App.vue;
import { createApp } from "vue";
import { createPinia} from "pinia";
const app = createApp(App);
const pinia = createPinia();
app.use(pinia).mount('#app');
// store.js
import { defineStore } from "pinia";
import { ref } from "vue";
const useCommonStore = defineStore('common', () => {
const lan = ref(localStorage.getItem('lan'));
const setLan = (lang) => {
lan.value = lang;
}
return {
lan,
setLan,
}
})
修改changeLang方法
import useCommonStore "./store.js";
const commonStore = useCommonStore();
const changeLanguage = (lang) => {
locale.value = lang;
commonStore.setLan(lang);
localStorage.setItem('lan', lang) // localStorage不会被vue响应式监听器监听到,所以语言切换不是实时的需要刷新页面才能生效
};
Element-Plus
- 通过ElConfigProvider组件实现Element-Plus组件全局国际化配置的设置
// App.vue
<template>
<el-config-provider :locale="locale">
<router-view></router-view>
</el-config-provider>
</template>
<script setup>
import zhCn from "element-plus/es/locale/lang/zh-cn";
import en from "element-plus/es/locale/lang/en";
import { computed } from 'vue';
import useCommonStore from "./store.js"
const commonStore = useCommonStore();
const local = computed(() => {
// return localStorage.getItem('lan') === "chinese" ? zhCn : en;
return commonStore.lan === 'chinese' ? zhCn : en;
})
</script>
JS中定义数据,并将数据展示到页面上
目前还不清楚原理
错误示例
利用ref或者reactive定义数据
<template>
<div>
<div v-for="item in arr.data" :key="item.id">{{item.name}}</div>
</div>
</template>
<script setup>
import { reactive } from 'vue';
import {useI18n} from 'vue-i18n';
const { t } = useI18n();
const arr = reactive({
data: [
{id: 1, name: t('common.title')},
{id: 2, name: t('common.theme')}
]
})
</script>
正确示例
利用computed定义数据
<template>
<div>
<div v-for="item in arr" :key="item.id">{{item.name}}</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const arr = computed(() => {
return [
{id: 1, name: t('common.title')},
{id: 2, name: t('common.theme')}
]
})
</script>