Bootstrap

vue2项目实现国际化(若依框架示例)

本文主要梳理vue2项目实现全项目格式化,在导航栏中切换,页面中所有的组件的默认语言随之切换,搭配vue-i18n插件


基础准备

引入插件vue-i18n

安装插件

npm i vue-i18n

【注】安装过程中报错
npm ERR! Cannot read properties of null (reading ‘matches‘)
解决方案:
先清除npm缓存:

npm cache clean --force

再使用pnpm进行安装(未安装的话就npm i pnpm一下即可)

pnpm i vue-i18n

或者在package.json文件中直接添加 “vue-i18n”: “^8.27.1”,版本,在进行重新进行npm install一下也可以
在这里插入图片描述

实现示例流程

1. 创建国际化文件

在src文件目录下创建i18n文件夹,文件夹下创建:element、locales、change-language.vue、index.js四个文件
【en.js文件】

1.1 element文件夹

创建两个文件:en.js,zh-CN.js,
主要用于存放elementUI组件,一些相对固定的文本描述翻译
【en.js】

// 英语
exports.default = {
  el: {
    colorpicker: {
      confirm: 'OK',
      clear: 'Clear'
    },
    datepicker: {
      now: 'Now',
      today: 'Today',
      cancel: 'Cancel',
      clear: 'Clear',
      confirm: 'OK',
      selectDate: 'Select date',
      selectTime: 'Select time',
      startDate: 'Start Date',
      startTime: 'Start Time',
      endDate: 'End Date',
      endTime: 'End Time',
      prevYear: 'Previous Year',
      nextYear: 'Next Year',
      prevMonth: 'Previous Month',
      nextMonth: 'Next Month',
      year: 'year',
      month1: 'January',
      month2: 'February',
      month3: 'March',
      month4: 'April',
      month5: 'May',
      month6: 'June',
      month7: 'July',
      month8: 'August',
      month9: 'September',
      month10: 'October',
      month11: 'November',
      month12: 'December',
      week: 'week',
      weeks: {
        sun: 'Sun',
        mon: 'Mon',
        tue: 'Tue',
        wed: 'Wed',
        thu: 'Thu',
        fri: 'Fri',
        sat: 'Sat'
      },
      months: {
        jan: 'Jan',
        feb: 'Feb',
        mar: 'Mar',
        apr: 'Apr',
        may: 'May',
        jun: 'Jun',
        jul: 'Jul',
        aug: 'Aug',
        sep: 'Sep',
        oct: 'Oct',
        nov: 'Nov',
        dec: 'Dec'
      }
    },
    select: {
      loading: 'Loading',
      noMatch: 'No matching data',
      noData: 'No data',
      placeholder: 'Select'
    },
    cascader: {
      noMatch: 'No matching data',
      loading: 'Loading',
      placeholder: 'Select',
      noData: 'No data'
    },
    pagination: {
      goto: 'Go to',
      pagesize: '/page',
      total: 'Total {total}',
      pageClassifier: ''
    },
    messagebox: {
      title: 'Message',
      confirm: 'OK',
      cancel: 'Cancel',
      error: 'Illegal input'
    },
    upload: {
      deleteTip: 'press delete to remove',
      delete: 'Delete',
      preview: 'Preview',
      continue: 'Continue'
    },
    table: {
      emptyText: 'No Data',
      confirmFilter: 'Confirm',
      resetFilter: 'Reset',
      clearFilter: 'All',
      sumText: 'Sum'
    },
    tree: {
      emptyText: 'No Data'
    },
    transfer: {
      noMatch: 'No matching data',
      noData: 'No data',
      titles: ['List 1', 'List 2'], // to be translated
      filterPlaceholder: 'Enter keyword', // to be translated
      noCheckedFormat: '{total} items', // to be translated
      hasCheckedFormat: '{checked}/{total} checked' // to be translated
    },
    image: {
      error: 'FAILED'
    },
    pageHeader: {
      title: 'Back' // to be translated
    },
    popconfirm: {
      confirmButtonText: 'Yes',
      cancelButtonText: 'No'
    },
    empty: {
      description: 'No Data'
    }
  },
};

【zh-CN.js】

// 中文
exports.default = {
  el: {
    colorpicker: {
      confirm: '确定',
      clear: '清空'
    },
    datepicker: {
      now: '此刻',
      today: '今天',
      cancel: '取消',
      clear: '清空',
      confirm: '确定',
      selectDate: '选择日期',
      selectTime: '选择时间',
      startDate: '开始日期',
      startTime: '开始时间',
      endDate: '结束日期',
      endTime: '结束时间',
      prevYear: '前一年',
      nextYear: '后一年',
      prevMonth: '上个月',
      nextMonth: '下个月',
      year: '年',
      month1: '1 月',
      month2: '2 月',
      month3: '3 月',
      month4: '4 月',
      month5: '5 月',
      month6: '6 月',
      month7: '7 月',
      month8: '8 月',
      month9: '9 月',
      month10: '10 月',
      month11: '11 月',
      month12: '12 月',
      // week: '周次',
      weeks: {
        sun: '日',
        mon: '一',
        tue: '二',
        wed: '三',
        thu: '四',
        fri: '五',
        sat: '六'
      },
      months: {
        jan: '一月',
        feb: '二月',
        mar: '三月',
        apr: '四月',
        may: '五月',
        jun: '六月',
        jul: '七月',
        aug: '八月',
        sep: '九月',
        oct: '十月',
        nov: '十一月',
        dec: '十二月'
      }
    },
    select: {
      loading: '加载中',
      noMatch: '无匹配数据',
      noData: '无数据',
      placeholder: '请选择'
    },
    cascader: {
      noMatch: '无匹配数据',
      loading: '加载中',
      placeholder: '请选择',
      noData: '暂无数据'
    },
    pagination: {
      goto: '前往',
      pagesize: '条/页',
      total: '共 {total} 条',
      pageClassifier: '页'
    },
    messagebox: {
      title: '提示',
      confirm: '确定',
      cancel: '取消',
      error: '输入的数据不合法!'
    },
    upload: {
      deleteTip: '按 delete 键可删除',
      delete: '删除',
      preview: '查看图片',
      continue: '继续上传'
    },
    table: {
      emptyText: '暂无数据',
      confirmFilter: '筛选',
      resetFilter: '重置',
      clearFilter: '全部',
      sumText: '合计'
    },
    tree: {
      emptyText: '暂无数据'
    },
    transfer: {
      noMatch: '无匹配数据',
      noData: '无数据',
      titles: ['列表 1', '列表 2'],
      filterPlaceholder: '请输入搜索内容',
      noCheckedFormat: '共 {total} 项',
      hasCheckedFormat: '已选 {checked}/{total} 项'
    },
    image: {
      error: '加载失败'
    },
    pageHeader: {
      title: '返回'
    },
    popconfirm: {
      confirmButtonText: '确定',
      cancelButtonText: '取消'
    },
    empty: {
      description: '暂无数据'
    }
  },

};
1.2 locales文件夹

创建两个文件:en.js,zh-CN.js,
主要用于存放页面中所需要的除了elementUI自带其他的页面文本描述元素
【en.js】

export default {
  Language: 'English',
  system: {
    homePage: {
      title1: 'title1',
      title2: 'title2',
      description1: 'Last 7 days',
      description2: 'Nearly six months',
    }
  }
};

【zh-CN.js】

export default {
  Language: '中文',
  system: {
    homePage: {
      title1: '标题1',
      title2: '标题2',
      description1: '近7日',
      description2: '近6个月',
    }
  }
};
1.3 index.js

文本集成文件,用于导入到入口文件main.js中,基本结构就是将两个element和locales文件集成导入,为了实现全局控制使用了本地储存localStorage来进行全局控制切换值,默认中文

import Vue from 'vue';
import VueI18n from 'vue-i18n';

Vue.use(VueI18n);

// 各个国家的key
const localeKeys = ['en', 'zh-CN'];

// 各个国家语言包
const messages = {};
for (const key of localeKeys) {
  const langObj = require(`./locales/${key}`).default;
  const langElement = require(`./element/${key}`);
  messages[key] = {
    ...langObj,
    ...langElement ? langElement.default : {}
  };
}

export default new VueI18n({
  locale: localStorage.getItem('change-language') || 'zh-CN',
  messages,
  silentTranslationWarn: true // 忽略翻译警告
});

解析:

  • locale属性:用于控制语言的标识,默认中文,此处使用了localStorage本地储存,方便全局且页面刷新都可以保持选中值

  • messages属性:切换文本的主要内容值,当locale的属性切换,所对应的语言的文本展示

  • silentTranslationWarn:是否忽略翻译警告

1.4 change-language.vue 切换组件

封装国际化语言切换组件,方便调用使用

<template>
  <el-dropdown @command="handle"
               style="cursor: pointer;">
    <span class="el-dropdown-link">
      {{$t('Language')}}<i class="el-icon-caret-bottom el-icon--right"></i>
    </span>
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item v-for="(item, index) of list"
                        :key="index"
                        :disabled="$t('Language') == item.name"
                        :command="item.key">{{item.name}}</el-dropdown-item>
    </el-dropdown-menu>
  </el-dropdown>
</template>

<script>
export default {
  name: 'change-language',
  data() {
    return {
      list: [
        { key: 'en', name: 'English' }, // 英语
        { key: 'zh-CN', name: '中文' }, // 中文
      ],
    }
  },
  methods: {
    handle(value) {
      this.$i18n.locale = value
      localStorage.setItem('change-language', value)
      location.reload()
    },
  },
}
</script>
<style scoped lang="scss">
</style>

2. 全局引入(main.js)

在入口文件main.js文件中进行引入,方便全局使用,

import i18n from './i18n';

Vue.use(Element, {
  i18n: (key, value) => i18n.t(key, value),
});

new Vue({
  el: '#app',
  router,
  store,
  i18n,
  render: h => h(App)
});

3. 在导航栏navbar.vue组件切换逻辑

直接在导航栏引入封装组件

引入:

<ChangeLanguage />
import ChangeLanguage from '@/i18n/change-language'

export default {
  components: {
    ChangeLanguage,
  },
  }

效果:
在这里插入图片描述

4. 在首页示例展示效果

示例组件:
直接使用$t函数直接双向绑定

<template>
  <div class="newMain-container homePage">
    示例代码:
    <br>
    我是title1==={{ $t('system.homePage.title1') }}
    <br>
    我是title2==={{ $t('system.homePage.title2') }}
    <br>
    我是description1===<el-button type="primary">{{ $t('system.homePage.description1') }}</el-button>
   <br>
    我是description2===<el-button type="primary">{{ $t('system.homePage.description2') }}</el-button>
  </div>
</template>

效果:

在这里插入图片描述
在这里插入图片描述

;