专栏首页前端之攻略vue 项目中英文切换

vue 项目中英文切换

最近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英文语言包

import enLocale from 'element-ui/lib/locale/lang/en'
const en = {
   "person":{
   "name":"name",
   "gender":"gender",
   "age":"age"
   },
   ...enLocale
}
export default en

zh.js为中文文件包,

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

export default zh

index.js

import en from "./en"
import zh from "./zh"
export default {
   en,
   zh
}

i18n.js

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实例中

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

使用方法

    <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>
    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中配置

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

使用方法

.vue页面

来自组件:{{ $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

<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

<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>

子组件

<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

const i18n = new VueI18n({
   locale: localStorage.getItem("currentLanage") || "zh",
   messages,
   silentTranslationWarn: true
})

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 搜索框自适应大小 原

    (adsbygoogle = window.adsbygoogle || []).push({});

    tianyawhl
  • vue 批量清空文本框

    在el-dialog 对话框中经常会输入一些信息,但是在关闭的时候我们需要清空输入的信息,如果不清空下次打开信息会存在

    tianyawhl
  • highcharts 自适应div的宽度

    如果窗口变化时,highcharts图表是自带自适应的,但是切换折叠菜单时,highchats图表并不自适应外层div的宽度。如何实现适应div的宽度?

    tianyawhl
  • Vue 3 计算属性和侦听器

    我们都知道,模板内的表达式计算是非常便利的,但是如果涉及到非常复杂的计算方式,一个结算结果如果依赖很多个变量,就会变得难以维护了,所以计算属性就此应运而生了。

    公众号---志学Python
  • 神经网络和深度学习(三) ——浅层神经网络的表示与输出

    神经网络和深度学习(三)——浅层神经网络的表示与输出 (原创内容,转载请注明来源,谢谢) 一、神经网络的表示 神经网络,实质上是一些输入,经过多层神经元的处理...

    用户1327360
  • Dubbo 分布式架构搭建教育 PC 站 - 前端:Vue 代码

    RendaZhang
  • 探秘 Mach-O 文件

    之前负责项目的包体积优化学习了 Mach-O 文件的格式,那么 Mach-O 究竟是怎么样的文件,知道它的组成之后我们又能做点什么?本文会从 Mach-O 文件...

    会写bug的程序员
  • CVPR 2020丨基于记忆增强的全局-局部整合网络:更准确的视频物体检测方法

    终于把这篇NAS最新的综述整理的survey放了上来,文件比较大,内容比较多。这个NAS的survey是A Comprehensive Survey of Ne...

    马上科普尚尚
  • 你有对象嘛?要不我们new一个?

    开学了,别人都有对象了,甚者大一的学弟学妹居然携带家属来报道,看到操场的他们,上自习的他们,要不是是冷风吹的有点冷我甚者以为现在是春天,说起来你可能不信当时我就...

    DataScience
  • 说好的举报来了!格力怒斥中国移动:到底是谁弄虚作假?

    怎么解读格力的心情呢?大概是这样的——"OK,你们私下交易没问题,我不中标我也没有意见!但你们联起手来说我弄虚作假想搞我,那就别怪我不客气了!"

    悲了伤的白犀牛

扫码关注云+社区

领取腾讯云代金券