vue-i18n實現不重新整理頁面切換頁面語言和element-ui的語言
阿新 • • 發佈:2020-10-20
開發環境
系統環境 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專案地址