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

posted @ 2020-10-20 18:35  平平无奇小辣鸡  阅读(4305)  评论(0编辑  收藏  举报