前端国际化

  最近做国外项目,需要实现项目的的国际化,这里大致捋一下思路、实现方式。项目技术栈是  vue + antd + java,我大致将需要翻译的内容划分为如下5个部分,接下来会一个一个的说明为何这么区分、如何实现翻译。这里强调一下,很负责的说,目前国际化,就是开发者写对象,一个key关联若干语种的翻译,纯手工翻译,目前不存在任何一下代码包可以一键智能翻译(因为翻译的不准)。ps:包括翻译表格表头,表头和表格体同时翻译都会说明

一、目录:

1、菜单等静态文本的国际化(I18n的使用,及其和antd的一些问题)

2、ui框架+其他外部依赖包的国际化

3、图片的国际化

4、服务端返回的国际化(接口反馈+维护数据)

5、登录页等无用户登录信息的国际化

 

二、菜单等静态文本的国际化

  这些基本的静态信息的国际化,我采用   vue-i18n  这个包来实现的(详细用法请查npm),指令: npm i vue-i18n ;用法很简单,不过在触发翻译的机制上会有一些蛋疼的地方,待会具体写一下。

1、引入、配置

import Vue from 'vue';
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)

const i18n = new VueI18n({
  //定义默认语言
  locale: 'zh', 
  messages:{
    'zh': require('@/constants/lang/zh'),  // 语言配置文件的路径
    'us': require('@/constants/lang/us')
  }
})

new Vue({
    i18n,
    router
    render: (h) => h(App)
}).$mount('#app')
module.exports = {
  // 公共
  common: {
    // 按钮类
    search: '查询',
    reset: '重置',
    collapse: '展开',
    add: '新增',
    delete: '删除',
    edit: '编辑',
    deleteMany: '批量删除',
    import: '导入',
    export: '导出',
    yes: '是',
    no: '否',
    confirm: '确认',
    cancel: '取消',
    changeLanguage: '切换语言',
    // 表格信息类
    createName: '创建人员',
    createTime: '创建时间',
    updateName: '维护人员',
    updateTime: '维护时间',
    operation: '操作',
    // 提示类
    requireRule: '该项为必填项',
    dataImport: '数据导入',
  },
  // 提示信息
  message: {
      text: '简体中文',
      delete: '确定要删除吗?',
      exportExcel: '正在导出Excel...',
      updateBom: '正在更新bom数据...',
      numberAndletter: '仅允许输入数字和字母,并以英文逗号分隔'
  },
  // 文本提示
  placeholder: {
      input: '请输入',
      select: '请选择',
      rangePicker: '开始日期 ~ 结束日期'
  }
}

引入后需要做一个全局配置,目前我仅支持了中英,有需要的加不同语言配置文件即可。注意每个文本的分类,通常按照功能分类, 比如 一个一级菜单、通用按钮、提示信息等等。

 

2、具体使用

// 在HTML中使用
<span>{{ $t(message.delete) }}</span>


// 在js中使用
this.$t(`message.exportExcel`)


// 切换语言
changeLanguage() {
        let lang = this.$store.state.app.language === 'zh' ? 'us' : 'zh';
        this.$i18n.locale = lang;
        this.$store.commit('CHANGE_LANGUAGE', lang )
},

语言属于用户属性,存储在数据库,登陆成功后我将语言存储在vuex中,只要是登陆的都可以保持语种状态。

 

3、遇到的坑

基础使用,自然没问题,但是和别的包配合使用就遇到问题了,大致如下:

(1)antd 的table,翻译他的表头

  这个不能直接在js中翻译columns,因为不会触发自动转换,需要表头采用插槽的方式,如果是操作列需要翻译表格体也是同理,具体看代码

const columns = [
    {  // 只翻译表头
      dataIndex: 'area',
      key: 'area',
      widtd: 120,
      align: 'center',
      slotName: 'calendar.area',
      scopedSlots: { title: 'calendar.area' }
    },
    { // 操作类,翻译表格体,比如翻译 编辑 删除 操作
      key: 'operation',
      fixed: 'right',
      widtd: 120,
      align: 'center',
      slotName: 'common.operation',
      scopedSlots: { title: 'common.operation', customRender: 'operationContent' },
    },
  ];

<a-table 
     rowKey="id" 
    :columns="columns" 
 >
      // 翻译表头
     <template v-for="(item, index) in columns" :slot="item.slotName">
           <span :key="index">{{ $t(item.slotName) }}</span>
      </template>
      // 操作类,翻译表格体,比如翻译 编辑 删除 操
       <span slot="operationContent" slot-scope="text,record">
            <a @click="edit(record)"> {{ $t('common.edit') }}</a>      
        </span>
</a-table>

(2)路由数据的翻译,因为 router 和 I18n 的引入是同时的,所以无法直接翻译路由数据,只能在渲染菜单的时候进行翻译,这个具体要看项目架构了。目前我的处理方式是路由配置价格国际化字段,渲染之前根据字段去判断。

new Vue({
    store,
    i18n,
    router,
    created () {
        bootstrap()
    },
    render: (h) => h(App)
}).$mount('#app')
 
// 路由配置
{
  path: '/basicData/calendar/index/:usage',
  name: 'calendar',
  meta: {
  title: '工作日历信息管理',
  international: 'calendar'   // 有这个字段就转国际化覆盖title值,没有就用title
  },
  component: () => import('@views/basicData/calendar/index.vue')
}

 

三、ui框架+其他外部依赖包的国际化

  1、antd 是有国际化组件的,也是监听vuex中语种字段,很简单就实现的 I18n 和 a-locale-provider 的同步。具体使用如下:

<template>
  <a-locale-provider :locale="locale">
    <div id="app">
      <router-view/>
    </div>
  </a-locale-provider>
</template>

<script>
import { mapState } from 'vuex'
import en_GB from 'ant-design-vue/lib/locale-provider/en_GB'
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import { AppDeviceEnquire } from '@/utils/mixin'

export default {
    mixins: [AppDeviceEnquire],
    data () {
        return {}
    },
    computed: mapState({
      locale: state => state.app.language === 'zh' ? zhCN : en_GB,
    })
}
</script>

  2、其他包,比如 moment 等等,这个就得具体分析了,有的包根本就不支持,有的都是基于数据输入的可以做。选包需慎重。

 

四、图片的国际化

  图片这种也分,如果像新闻这种每天更换的,直接服务端做区分,如果是固定的,就得做好几套,一般直接存储到不同语言目录下,监听全局的 language 变量展示不同路径图片即可

 

五、服务端返回的国际化(接口反馈+维护数据)

  服务端的国际化主要是2块,一是:接口反馈信息,比如成功 失败的提示信息,需要直接返回指定语言的,前端不做任何处理,直接展示; 二是: 配置信息,比如某个下拉列表的信息是需要放在服务端的,就需要服务端按照语言返回。前端当然也能做,但是有些场景不允许前端写死,这类数据需要放在服务端。通常做法是数据加语种字段,用的时候筛选出来即可。

 

六、登录页等无用户登录信息的国际化

  我们通常会将语言信息写到浏览器的 ocalstorage 中,如果涉及到没有用户信息的时候优先读取 ocalstorage ,比如 登录页。这样二次登录的用户是没问题的。如果 ocalstorage  没有,比如首次登陆、清楚本地缓存的情况,服务端会判断其IP的地区,根据当前我们的语种支持范围,选择一个可能性最大的,比如,目前我们项目,除了欧美、中南亚用户全部展示英文,中国展示中文。注意这个只是一个只能推荐,我们只考虑现实,VPN这种不考虑。另外建议登录页不要放太多文本类型的内容。

 

小结:

  好了,这就是我对项目国际化的一些总结,一方面自己做记录,另一方面也希望能对大家有用吧。

 

 

 

 

 

 

 

  

posted @ 2020-06-11 09:28  Mr.聂  阅读(1891)  评论(8编辑  收藏  举报