vue-i18n与Element-Plus国际化整合

522 阅读3分钟

在使用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>