最近做國外項目,需要實現項目的的國際化,這里大致捋一下思路、實現方式。項目技術棧是 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')
三、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這種不考慮。另外建議登錄頁不要放太多文本類型的內容。
小結:
好了,這就是我對項目國際化的一些總結,一方面自己做記錄,另一方面也希望能對大家有用吧。