前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vue 项目中英文切换

vue 项目中英文切换

作者头像
tianyawhl
发布2020-10-28 14:14:37
2.9K0
发布2020-10-28 14:14:37
举报
文章被收录于专栏:前端之攻略

最近vue项目需要中英文切换,查了资料,发现大部分都是采用 vue-i18n,但是写的比较简单,大部分都是全局引入语言包,遇到的几个问题

1、如何结合element-ui 实现中英文切换

2、如何在组件中使用各自的语言包

3、中英文切换如何刷新页面,特别是中英文切换时根据当前语言调用中文或者英文接口

全局引入语言包实现中英文切换

一、安装vue-i18n,我安装的版本是 "vue-i18n": "^8.22.0",

npm install --save vue-i18n

新建一个common文件夹,里面含有如下文件

en.js 为英文文件包,enLocale为element英文语言包

代码语言:javascript
复制
import enLocale from 'element-ui/lib/locale/lang/en'
const en = {
   "person":{
   "name":"name",
   "gender":"gender",
   "age":"age"
   },
   ...enLocale
}
export default en

zh.js为中文文件包,

代码语言:javascript
复制
import zhLocale from 'element-ui/lib/locale/lang/zh-CN'
const zh = {
   "person":{
      "name":"名称new",
      "gender":"性别",
      "age":"年龄"
   },
   ...zhLocale
}

export default zh

index.js

代码语言:javascript
复制
import en from "./en"
import zh from "./zh"
export default {
   en,
   zh
}

i18n.js

代码语言:javascript
复制
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from './index.js'
import store from '@/store'
Vue.use(VueI18n)
console.log("hi")
const i18n = new VueI18n({
   locale: localStorage.getItem("currentLanage") || "zh",
   messages,
   // silentTranslationWarn: true 
})

export default i18n

在main.js中引文i18n并注册到vue实例中

代码语言:javascript
复制
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import i18n from "./common/i18n/i18n.js"
import ElementUI from 'element-ui'
// 引入element-ui 样式文件
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI, {
  i18n: (key, value) => i18n.t(key, value)
})
new Vue({
  i18n,
  router,
  store,
  render: h => h(App)
}).$mount('#app')

注意:不同的vue=i18n版本和element-ui结合的方式不同。具体见element-ui的官网 https://element.eleme.cn/#/zh-CN/component/i18n

使用方法

代码语言:javascript
复制
    <div>
      来自全局:
      <span>{{ $t("person.name") }}</span>
      <el-date-picker v-model="value1" type="date" ></el-date-picker>
    </div>

    <div class="page-top">
      <div class>
        <div class="left pull-left logo-wrap">
          <img src="../assets/imgs/emerson-logo.png" alt class="pull-left" />
          <span class="pull-left topName">GasNet Master</span>
        </div>
        <div class="right pull-right">
          <span class="margin_r20 top_language">
            <a href="javascript:void(0)" :class="{active:isZh}" @click="changeLanage('zh')">中文</a> |
            <a href="javascript:void(0)" :class="{active:!isZh}" @click="changeLanage('en')">英文</a>
          </span>
          <a href="javascript:void(0)">About</a>
          <a href="javascript:void(0)">Help</a>
          <a href>Logout</a>
        </div>
      </div>
    </div>
代码语言:javascript
复制
    changeLanage(lang) {
      if (lang == "zh") {
        this.isZh = true;
        this.$i18n.locale = lang;
        localStorage.setItem("currentLanage", lang);
      } else if (lang == "en") {
        this.isZh = false;
        this.$i18n.locale = lang;
        localStorage.setItem("currentLanage", lang);      
      }     
    }

上面实现了基本的中英文切换,但是如果把所以得语言都放到全局,不容易维护,一般是把通用的放在全局,每个页面特有的放在组件中

安装vue-i18n-loader

npm install --save @kazupon/vue-i18n-loader

vue-cli3中配置 vue.config.js中配置

代码语言:javascript
复制
  chainWebpack: config => {
    config.module
      .rule('i18n')
      .resourceQuery(/blockType=i18n/)
      .type("javascript/auto")
      .use('i18n')
      .loader('@kazupon/vue-i18n-loader')
      .end()
  },

使用方法

.vue页面

代码语言:javascript
复制
来自组件:{{ $t("helloworld") }}

<i18n>
{
  "en": {
    "placeholder":"pick a day",
    "helloworld": "hello world!"
  },

  "zh": {
    "placeholder":"选择日期",
    "helloworld": "你好,世界new!"
  }
}

</i18n>

关于如果实现中英文切换时根据当前语言调用中文或者英文接口 ( 通过provide inject 实现 ),假如中英切换按钮在Home.vue上,Home.vue含有

<router-view></router-view> 来承载子路由

App.vue

代码语言:javascript
复制
<template>
    <div id="app">       
        <router-view v-if="isRouterAlive"/>
    </div>
</template>
<script>
export default{
    name:"app",
    provide(){
        return {reload:this.reload}
    },
    data(){
        return {
            isRouterAlive:true
        }
    },
    methods:{
        reload(){
            this.isRouterAlive = false
            this.$nextTick(function(){
                this.isRouterAlive = true
            })
        }
    }
}

</script>

Home.vue

代码语言:javascript
复制
<template>
  <div>
    <div>
      来自全局:
      <span>{{ $t("person.name") }}</span>
    </div>

    <div class="page-top">
      <div class>
        <div class="left pull-left logo-wrap">
          <img src="../assets/imgs/emerson-logo.png" alt class="pull-left" />
          <span class="pull-left topName">GasNet Master</span>
        </div>
        <div class="right pull-right">
          <span class="margin_r20 top_language">
            <a href="javascript:void(0)" :class="{active:isZh}" @click="changeLanage('zh')">中文</a> |
            <a href="javascript:void(0)" :class="{active:!isZh}" @click="changeLanage('en')">英文</a>
          </span>
          <a href="javascript:void(0)">About</a>
          <a href="javascript:void(0)">Help</a>
          <a href>Logout</a>
        </div>
      </div>
    </div>
    <el-menu
      router
      mode="horizontal"
      :default-active="$route.path"
      background-color="#004b8e"
      text-color="#fff"
      active-text-color="#ffD04B"
    >
      <NavMenu v-for="item in menuData" :key="item.id" :menuItem="item"></NavMenu>
    </el-menu>
    <router-view></router-view>
  </div>
</template>
<script>
import NavMenu from "@/components/NavMenu.vue";
export default {
  inject: ["reload"],
  data() {
    return {
      isZh:
        localStorage.getItem("currentLanage") == null
          ? true
          : localStorage.getItem("currentLanage") == "zh"
          ? true
          : false
    };
  },
  computed: {
    menuData() {
      return this.$store.state.menuData;
    }
  },

  methods: {
    changeLanage(lang) {
      if (lang == "zh") {
        this.isZh = true;
        this.$i18n.locale = lang;
        localStorage.setItem("currentLanage", lang);
        this.reload();
      } else if (lang == "en") {
        this.isZh = false;
        this.$i18n.locale = lang;
        localStorage.setItem("currentLanage", lang);
        this.reload();
      }
      //  this.$i18n.locale = this.lang  // 只对局部有效  ,删除局部倒是对全局有效
    }
  },
  components: { NavMenu }
};
</script>

子组件

代码语言:javascript
复制
<template>
  <div>
    <div class="block">
      <span class="demonstration">默认</span>
      <el-date-picker v-model="value1" type="date" :placeholder="$t('placeholder')">
      </el-date-picker>
    </div>
    <div>来自全局:{{$t("person.age")}}</div>
    <div>来自组件:{{ $t("helloworld") }}</div>
    
    <!-- 调用接口,切换语言时需要重新加载页面,home页面用到 inject:["reload"],-->
    <h2>{{ info }}</h2>
    <!-- 切换语言按钮在组件内 只能切换组件内的语言,如果删除组件内的语言则可以切换全局的语言,但是一般切换按钮也不会在组件内 -->
    <el-button @click="changeLanage">切换语言</el-button>
  </div>
</template>
<i18n>
{
  "en": {
    "placeholder":"pick a day",
    "helloworld": "hello world!"
  },

  "zh": {
    "placeholder":"选择日期",
    "helloworld": "你好,世界new!"
  }
}

</i18n>
<script>
import NavMenu from "@/components/NavMenu.vue";
export default {
  data() {
    return {
      info: "",
      value1: ''
    };
  },
  computed: {
    menuData() {
      return this.$store.state.menuData;
    },
  },
  components: { NavMenu },
  created() {
    this.getInfo();
  },
  methods: {
    changeLanage(){
      this.$i18n.locale = "en"
    },
    getInfo() {
      let lang = localStorage.getItem("currentLanage") || "zh";
      console.log(lang);
      this.$axios.get("mock/data_" + lang + ".json").then((res) => {
        console.log(res.data.info);
        this.info = res.data.info;
      });
    },
  },
};
</script>

发现在子组件中同时使用全局的语言包和局部语言包,会报警告

vue-i18n.esm.js?a925:33 [vue-i18n] Value of key 'person.age' is not a string or function !

[vue-i18n] Fall back to translate the keypath 'person.age' with root locale.

但是能正常切换语言,只需要在VueI18n 实例中配置silentTranslationWarn: true

代码语言:javascript
复制
const i18n = new VueI18n({
   locale: localStorage.getItem("currentLanage") || "zh",
   messages,
   silentTranslationWarn: true
})
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档