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项目地址