1. 程式人生 > 實用技巧 >vue-i18n實現不重新整理頁面切換頁面語言和element-ui的語言

vue-i18n實現不重新整理頁面切換頁面語言和element-ui的語言

開發環境

系統環境 windows 10
vue版本 2.6.11
λ node -v v12.19.0 λ npm -v 6.14.8 λ vue -V @vue/cli 4.5.7

專案目錄結構

安裝必要的包

vue-i18n
element-ui
vue-router
vuex

  

新建i18n檔案的翻譯語言包

// src/store/i18n/lang/en.js
// explore 的方式需要加花括號匯入
import { enHello } from './modules/HelloWorld'

export default {
    ...enHello,
    login: {
        username: 'username'
    },
    chooseDate: 'Choose Date:',
    exchangeLanguage: 'Exchange Language',
    home: 'Home',
    about: 'about'
}

 

// src/store/i18n/lang/zh.js

import {zhHello} from './modules/HelloWorld'

export default {
    ...zhHello,
    login: {
        username: '使用者名稱'
    },
    chooseDate: '選擇日期:',
    exchangeLanguage: '切換語言',
    home: '首頁',
    about: '關於'

}

  

// src/store/i18n/lang/modules/HelloWorld.js

export const  enHello = {
  date: 'Date',
  title: 'Sport Brands',
  nike: 'Nike',
  adi: 'Adidas',
  nb: 'New Balance',
  ln: 'LI Ning'
};

export const zhHello = {
  date: '日期',
  title: '運動品牌',
  nike: '耐克',
  adi: '阿迪達斯',
  nb: '新百倫',
  ln: '李寧'
};

  

// src/store/i18n/index.js

// 引入必要的庫
import Vue from 'vue'
import VueI18n from 'vue-i18n'
// 引入element ui國際化檔案
import elen from 'element-ui/lib/locale/lang/en'
import elcn from 'element-ui/lib/locale/lang/zh-CN'
import ElementLocale from 'element-ui/lib/locale'

// 引入工具函式
import { getStorage, getBrowserLang } from '@/util'

// 引入專案中需要用到的中英文文案配置js
import enLocale from './lang/en'
import cnLocale from './lang/zh'

// 使用vue-i18n庫
Vue.use(VueI18n);

// 獲取當前語言(初始化時localStorage裡沒有存語言,預設為瀏覽器當前的語言)
const lang = getStorage('lang') || getBrowserLang();

// 組合element ui 和 專案自身的文案檔案
const messages = {
    'en': {
        ...elen,
        ...enLocale
    },
    'zh': {
        ...elcn,
        ...cnLocale
    }
};

// 建立vueI18n例項並輸出,在main.js中呼叫
const i18n = new VueI18n({
    locale: lang,
    messages,
    silentFallbackWarn: true,  // 設定為true後,在元件內使用時在瀏覽器不會報警告
});

ElementLocale.i18n((key, value) => i18n.t(key, value));
export default i18n

  

新建工具方法檔案

// src/util.js

// 設定localStorage
export const setStorage = function(key, obj) {
    let json = JSON.stringify(obj);
    window.localStorage.setItem(key, json)
};

// 獲取localStorage
export const getStorage = function(key) {
  const str = window.localStorage.getItem(key);
  if (!str) {
      return null
    }
    return JSON.parse(str)
};

// 移除localStorage
export const removeStorage = function(key) {
    window.localStorage.removeItem(key)
};

// 獲取瀏覽器預設語言
export const getBrowserLang = function() {
  let browserLang = navigator.language ? navigator.language: navigator.browserLanguage;
  let defaultBrowserLang = '';
    if (browserLang.toLowerCase() === 'cn' || browserLang.toLowerCase() === 'zh' || browserLang.toLowerCase() === 'zh-cn') {
        defaultBrowserLang = 'zh'
    } else {
        defaultBrowserLang = 'en'
    }
    return defaultBrowserLang
};

  

配置mian.js

//  src/main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import i18n from "./store/i18n";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);


Vue.config.productionTip = false;

new Vue({
  router,
  store,
  i18n,
  render: h => h(App)
}).$mount('#app');

  

 

使用vuex來變更語言狀態

// src/store/index.js

import {
    getStorage,
    setStorage,
    getBrowserLang
}
from '@/util'

export default {
  state: {
      language: getStorage('lang') || getBrowserLang(), // 專案初始化時,預設為瀏覽器的語言
  },
  getters: {
      language: state => state.language,
    },
  mutations: {
      setLanguage: (state, language) => {
          state.language = language;
          setStorage('lang', language);
      }
  }
}

  

//  src/store/modules/language.js

import {
    getStorage,
    setStorage,
    getBrowserLang
}
from '@/util'

export default {
  state: {
      language: getStorage('lang') || getBrowserLang(), // 專案初始化時,預設為瀏覽器的語言
  },
  getters: {
      language: state => state.language,
    },
  mutations: {
      setLanguage: (state, language) => {
          state.language = language;
          setStorage('lang', language);
      }
  }
}

  

  

修改頁面內容

// src/App.vue

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<style lang="scss">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

</style>

  

注意:data中使用i18n時切換語言不會更新,所以還是得重新整理路由才能根本解決問題。

// src/views/Home.vue

<template>
  <div class="home">
      <HelloWorld msg="Welcome to Your Vue.js App"/>
      <el-main>
        <el-table :data="tableData" style="width: 100%">
          <el-table-column :label="$t('date')" >
              <span class="demonstration">{{ $t("chooseDate") }}</span>
              <el-date-picker v-model="value1" type="date" placeholder=""></el-date-picker>
          </el-table-column>
          <el-table-column prop="name" :label="$t('title')"></el-table-column>
        </el-table>
      </el-main>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'Home',
  components: {
    HelloWorld
  },
    data () {
      return {
        value1: '',
        tableData: [{
            date: '2016-05-02',
            name: this.$t('nike'),
          }, {
            date: '2016-05-04',
            name: this.$t('adi'),
          }, {
            date: '2016-05-01',
            name: this.$t('nb'),
          }, {
            date: '2016-05-03',
            name: this.$t('ln'),
          }]
      }
    }
}
</script>

<style>
  .el-main {
    background-color: #E9EEF3;
    color: #333;
    text-align: center;
  }
</style>

  

注意:在元件中使用i18n配置會導致全域性的狀態不能變更和element-ui語言不能切換。

// src/components/HelloWorld.vue


<template>
  <div class="hello">
    <el-container>
      <el-header>
        <el-row>
          <el-col :span="5"><router-link to="/">{{ $t("home") }}</router-link></el-col>
          <el-col :span="5"><router-link to="/about">{{ $t("about") }}</router-link></el-col>
          <el-col :span="5">{{ $t("exchangeLanguage") }}</el-col>
          <el-col :span="5">
            <el-dropdown @command="handleSetLang" trigger="click">
              <div class="lang-active">
                <div v-for="(lang, i) in langs" :key="`LangActive${i}`" v-show="lang.key === activeLang">{{ lang.value }}
                  <i class="el-icon-arrow-down el-icon--right"></i></div>
              </div>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item v-for="(lang, i) in langs" :key="`Lang${i}`" :command="lang.key">
                  <span class="text">{{ lang.value }}</span></el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </el-col>
          <el-col :span="4">{{$t('login.username')}}</el-col>
        </el-row>

      </el-header>
<!--      <el-main>-->
<!--        <div class="block">-->
<!--          <span class="demonstration">{{ $t("chooseDate") }}</span>-->
<!--          <el-date-picker v-model="value1" type="date" placeholder="">-->
<!--          </el-date-picker>-->
<!--        </div>-->
<!--      </el-main>-->
    </el-container>

  </div>
</template>

<script>
import {
    mapGetters,
    mapMutations
  } from 'vuex';
export default {
  name: 'HelloWorld',
  // i18n:{
  //     messages:{
  //       en: {
  //         title: 'Sport Brands',
  //         nike: 'Nike',
  //         adi: 'Adidas',
  //         nb: 'New Banlance',
  //         ln: 'LI Ning'
  //       },
  //       zh: {
  //         title: '運動品牌',
  //          nike: '耐克',
  //           adi: '阿迪達斯',
  //           nb: '新百倫',
  //           ln: '李寧'
  //       },
  //     }
  // },
  data () {
    return {
      value1: '',
      langs: [{
          key: 'zh',
          value: '中文'
        },
        {
          key: 'en',
          value: 'EngLish'
        },
        ],
    }
  },
 computed: {
      ...mapGetters({
        activeLang: 'language',
      })
    },
 methods: {
      ...mapMutations(['setLanguage']),
      handleSetLang(lang) {
        // 設定i18n.locale 元件庫會按照上面的配置使用對應的文案檔案
        this.$i18n.locale = lang
        // 提交mutations
        this.setLanguage(lang)
      }
    }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
  .el-header {
    background-color: #B3C0D1;
    color: #333;
    text-align: center;
    line-height: 60px;
  }

  body > .el-container {
    margin-bottom: 40px;
  }
  body {
    margin: 0;
    bottom: 0;
  }
  a {
    font-weight: bold;
    color: #2c3e50;
    /*text-decoration: none;*/
  }
  .router-link-exact-active {
      color: #42b983;
  }
</style>

  

最終效果對比

你的start是我前進的動力,謝謝!本文GitHub專案地址

重新整理頁面版連結

本文參考連結1

本文參考連結2