Components

i18n 国际化 vue3 版

i18n 国际化 vue3 版

安装

npm install vue-i18n@9

语言对照表

  • src/lang/en.ts
const en = {
  hello: "hello"
};

export default en;
  • src/lang/zh.ts
const zh = {
  hello: "你好"
};

export default zh;

创建 i18n 实例

  • src/lang/index.ts
import en from "./en";
import zh from "./zh";
import { createI18n } from "vue-i18n";

const messages = { en, zh };

const i18n = createI18n({
  legacy: false, // you must set `false`, to use Composition API
  locale: "en", // set default locale
  fallbackLocale: "en", // set fallback locale
  messages // set locale messages
});

export default i18n;
  • src/main.ts
import i18n from "./lang";
import { createApp } from "vue";

const app = createApp(App);

app.use(i18n);

pinia 读取当前语种

  • src/store/index.ts
export const useMainStore = defineStore("main", {
  state: () => ({
    lang: localStorage.getItem("lang") || "en"
  }),
  getters: {},
  actions: {}
});

引入 element-plus

  • src/App.vue
<template>
  <div class="app-content">
    <!-- element-plus的语言配置 -->
    <el-config-provider :locale="local">
      <router-view v-slot="{ Component }">
        <transition enter-active-class="animate__animated animate__fadeIn">
          <component :is="Component" />
        </transition>
      </router-view>
    </el-config-provider>
  </div>
</template>

<script setup lang="ts">
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import en from "element-plus/lib/locale/lang/en";
import { useMainStore } from "@/store/index";

const store = useMainStore();

// 读取pinia存储的语种 改变element-plus的语种
const local = computed(() => {
  const lang = store.$state.lang;
  if (lang === "zh") {
    return zhCn;
  }
  return en;
});
</script>

<style lang="scss">
.app-content {
  height: 100vh;
}
</style>

使用

<template>
  <div>
    <p class="text-center">{{ t("hello") }}</p>

    <el-pagination :total="100" />

    <button @click="changeLang('zh')">中文</button>
    <button @click="changeLang('en')">英文</button>
  </div>
</template>

<script lang="ts" setup>
import { useI18n } from "vue-i18n";
import { useMainStore } from "@/store/index";

const store = useMainStore();

const { t, locale } = useI18n();

const changeLang = (e: string) => {
  localStorage.setItem("lang", e);
  store.$state.lang = e;
  // 修改 i18n 的语种
  locale.value = e;
};
</script>

i18n 国际化

package.json 中所需要的依赖

注意 vue-i18n 的版本 最好用给定的版本 尝试用 9.x 版本报错
"dependencies": {
    "element-ui": "^2.15.6",
    "js-cookie": "^3.0.1",
    "vue": "^2.6.11",
    "vue-i18n": "^7.3.2",
    "vuex": "^3.4.0"
  },

文件目录结构 src/lang

设置语言对照表

<img src=https://s1.ax1x.com/2022/04/18/Ld96GF.md.png" height=400/>

src/lang/index.js

import Vue from "vue";
// $t 是在 VueI18n 里面写好的
import VueI18n from "vue-i18n";
import Cookies from "js-cookie";
import elementEnLocale from "element-ui/lib/locale/lang/en"; // element-ui lang
import elementZhLocale from "element-ui/lib/locale/lang/zh-CN"; // element-ui lang
import elementEsLocale from "element-ui/lib/locale/lang/es"; // element-ui lang
import elementJaLocale from "element-ui/lib/locale/lang/ja"; // element-ui lang
import enLocale from "./en";
import zhLocale from "./zh";
import esLocale from "./es";
import jaLocale from "./ja";

Vue.use(VueI18n);

const messages = {
  en: {
    ...enLocale,
    ...elementEnLocale
  },
  zh: {
    ...zhLocale,
    ...elementZhLocale
  },
  es: {
    ...esLocale,
    ...elementEsLocale
  },
  ja: {
    ...jaLocale,
    ...elementJaLocale
  }
};
export function getLanguage() {
  const chooseLanguage = Cookies.get("language");
  if (chooseLanguage) return chooseLanguage; // if has not choose language

  const language = (
    navigator.language || navigator.browserLanguage
  ).toLowerCase();
  const locales = Object.keys(messages);
  for (const locale of locales) {
    if (language.indexOf(locale) > -1) {
      return locale;
    }
  }
  return "en";
}
const i18n = new VueI18n({
  // set locale
  // options: en | zh | es
  locale: getLanguage(), // set locale messages
  messages //将语言对照表放入 VueI18n 实例
});

export default i18n;

选择语言下拉框

语言选择下拉框组件 components/langSelect/index.js
<template>
   
  <el-dropdown
    trigger="click"
    class="international"
    @command="handleSetLanguage"
  >
       
    <div>选择语言</div>
       
    <el-dropdown-menu slot="dropdown">
           
      <el-dropdown-item :disabled="language === 'zh'" command="zh">
                中文      
      </el-dropdown-item>
           
      <el-dropdown-item :disabled="language === 'en'" command="en">
                English      
      </el-dropdown-item>
           
      <el-dropdown-item :disabled="language === 'es'" command="es">
                Español      
      </el-dropdown-item>
           
      <el-dropdown-item :disabled="language === 'ja'" command="ja">
                日本語      
      </el-dropdown-item>
         
    </el-dropdown-menu>
     
  </el-dropdown>
</template>

<script>
export default {
  computed: {
    language() {
      //在store里面获取当前设置的语言是什么
      return this.$store.state.language;
    }
  },
  methods: {
    handleSetLanguage(lang) {
      this.$i18n.locale = lang;
      this.$store.dispatch("setLanguage", lang);
      this.$message({
        message: "Switch Language Success",
        type: "success"
      });
    }
  }
};
</script>

store/index.js

import Vue from "vue";
import Vuex from "vuex";
import Cookies from "js-cookie";
import { getLanguage } from "@/lang/index";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    language: getLanguage()
  },
  mutations: {
    SET_LANGUAGE: (state, language) => {
      state.language = language;
      Cookies.set("language", language);
    }
  },
  actions: {
    setLanguage({ commit }, language) {
      commit("SET_LANGUAGE", language);
    }
  },
  modules: {}
});

main.js

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import Element from "element-ui";
import Cookies from "js-cookie";
import "element-ui/lib/theme-chalk/index.css";
import i18n from "./lang"; // internationalization

Vue.config.productionTip = false;

// 这里可以不适用 elemnt
Vue.use(Element, {
  size: Cookies.get("size") || "medium",
  i18n: (key, value) => i18n.t(key, value)
});

new Vue({
  router,
  store,
  i18n, //传入之后组件中可以使用 this.$i18n
  render: (h) => h(App)
}).$mount("#app");

演示 demo

<template>
   
  <div class="home">
    <!-- 使用$t来转换语言 -->

    <h1>{{ $t("route.dashboard") }}</h1>
       
    <h1>{{ $t("route.documentation") }}</h1>

    <!-- 选择语言的组件 -->

    <langSelect></langSelect>
     
  </div>
</template>

<script>
import langSelect from "@/components/langSelect";
export default {
  name: "Home",
  components: { langSelect }
};
</script>

效果如下