前端不使用i18n該如何優(yōu)雅的實現(xiàn)多語言
前言:
關(guān)于ERP管理系統(tǒng)的多語言,或者其他應(yīng)用的多語言一直是我們比較麻煩的問題,大部分是使用 i18n 在代碼里進行配置,如果想要修改語言就要自己去改代碼!
今天我們分享一下如何不使用 i18n 去實現(xiàn)多語言,用到以下的技術(shù)棧:
ERP管理系統(tǒng):Vue + 若依 + Element-ui
微信小程序 :uniapp + uView
一、業(yè)務(wù)需求
1. 確定業(yè)務(wù)
最近要實現(xiàn)多語言的 ERP,以及對應(yīng)的H5、小程序;但是因為語言可能不確定,需求是客戶自己去添加、修改自己想要的語言,所以就需要在 ERP 上實現(xiàn) 一個叫 language(可以定義語言) 的功能,可以去給客戶提供一個可以添加默認語言、添加新的語言、修改、刪除當前語言的平臺,如果當前語言沒有加過翻譯則用 [ key ] 這種方式去提醒客戶,該 key 未加多語言!然后我們的ERP、H5、小程序就可以使用當前的全局多語言...
2. 實現(xiàn)思路
思路其實比較簡單,但是復(fù)雜的需求往往離不開后端大佬支持!下面我們一起來捋一捋我們的實現(xiàn)思路(假設(shè)我們現(xiàn)在的需求是三個地區(qū)的語言:簡體中文、繁體中文、英文)!
① 既然我們再 ERP 上需要有一個 language 的功能供客戶去操作語言,考慮到客戶還可能設(shè)置默認語言,添加多種不同地區(qū)的語言,所以我們的 UI 可以像下圖設(shè)計的那樣;
② 新增完地區(qū)語言以后我們該如何讓去修改、新增的不同地區(qū)的語言呢?我們這個時候就需要 一個子頁面,負責新增當前 key 的多語言,查詢當前 key 的多語言去做修改,看完下圖你就會明白啦?。?!
③經(jīng)過以上兩個步驟我們已經(jīng)成功的讓客戶實現(xiàn)了想要的效果,但是我們要怎么把后端大哥保存好的東西拿過來用呢
1. 保存時的數(shù)據(jù)結(jié)構(gòu):
{ key: "Status" texts:[ { "languageName": "en-GB", "text": "Status" }, { "languageName": "zh-CN", "text": "狀態(tài)" }, { "languageName": "zh-HK", "text": "狀態(tài)" } ] }
關(guān)于ERP 查詢時的數(shù)據(jù)結(jié)構(gòu)這里就不一一列舉了,和上面類似!
2. ERP | H5 | 微信小程序 用時查詢的數(shù)據(jù)結(jié)構(gòu):
// ERP | H5 | 微信小程序 用時的查詢 // language_texts 是我們再 SQL Table 中存儲的所有多語言集合 language_texts : { key : 當前語言的value, // 如何知道當前語言,我們稍后再說 key : value, key : value, ... : ... ... : ... }
3. 前端如何使用已經(jīng)保存好的數(shù)據(jù)結(jié)構(gòu)呢?
其實有了上面查詢我們就可以用到 language_texts[ key ] 的方式去取出來我們想要的語言數(shù)據(jù);使用的話也比較簡單,js html 中的不同使用方法下面給大家一 一講解 ;
值得我們思考的問題是 我們該何時把 當前語言集全部查詢出來?
我這里采用的方案是在 new Vue 之前去調(diào)用我們當前的 VFrame方法,這樣我們可以確保 我們的多語言所有的 [ key ] [ value ] 可以成功加載,具體步驟請看下方!
二、實現(xiàn)步驟
1. 新建 VFrame.js 文件
我這里的 VFrame.js 是直接建在Src 目錄下的
import axiso from 'axios' import { getAll } from '@/api/uxretail/application.js' const format = require('string-format') export default class VFrame { static host; static wsUrl; /** * 在vue實例化之前調(diào)用異步start方法 */ static start() { return new Promise((resolve, reject) => { axiso.request({ url: "/static/appconfig.json", method: "get", }).then(result => { VFrame.host = (result.host || window.location.host); VFrame.wsUrl = "ws://" + VFrame.host + ":" + result.wsPort + "/ws/notify/"; VFrame.getAll(resolve); }).catch(error => { reject(error); }); }); } static getAll(resolve) { getAll().then(res => { VFrame.applicationResource = res resolve() }); } static l(key, ...args) { if (localStorage.getItem("ux_debug_language")) { return `[${key}]` } if (!VFrame.applicationResource) { return key } if (VFrame.applicationResource.language_texts) { let res = VFrame.applicationResource.language_texts[key]; if (res) { return format(res, args); } else { return `[${key}]` } } return key; } }
2. main.js 中 使用我們新建的 VFrame.js
上面我們說到 VFrame 的執(zhí)行時機,我們可以看下面代碼!
import Vue from "vue"; import App from "./App"; import store from "./store"; import router from "./router"; import VFrame from "./framework/VFrame"; Vue.prototype.l = VFrame.l; // 這個為了方便用 VFrame ,并沒有其他用途 Vue.prototype.$ux = { v: VFrame } // 重要的就是這一步,VFrame 的執(zhí)行時機 VFrame.start().then(() => { //set layout to store store.commit("dragLayout/initLayout") new Vue({ el: "#app", router, store, render: h => h(App) }); });
3. html js 中使用我們配置好的多語言
Html 中使用: 【 l("Key") 】
<div> {{ l('ManyLanguage') }} </div> <el-form :model="item" :rules="tableRules"> <el-form-item :label="l("ManyLanguage")" prop="language"> <el-input v-model="item.language"></el-input> </el-form-item> </el-form>
js 中使用: 【 this.l("Key") 】
export default{ data(){ return { language:this.l("ManyLanguage") } }, created(){ console.log(this.l("MyLanguage")) }, }
經(jīng)過上面一番操作我們已經(jīng)可以在管理系統(tǒng)中成功的調(diào)用當前多語言了;
那么我們 VFrame 中的 getAll() API 調(diào)用時 如何返回我們剛好我們想要的語言呢?
我們就要處理 【 request.js 】中的封裝,在請求攔截中去攜帶我們自定義的請求頭信息,后端大佬去對應(yīng)的處理即可!
import Cookies from "js-cookie"; import axios from "axios"; axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8"; // 創(chuàng)建axios實例 const service = axios.create({ // axios中請求配置有baseURL選項,表示請求URL公共部分 baseURL: process.env.VUE_APP_BASE_API, // 超時 timeout: 120000 }); service.interceptors.request.use( config => { var cultureName = Cookies.get(CONSTANT.UX_LANGUAGE); if (cultureName) { config.headers[CONSTANT.UX_LANGUAGE] = cultureName; // 讓每個請求攜帶自定義token 請根據(jù)實際情況自行修改 } })
三、微信小程序中使用
實現(xiàn)步驟就像上面寫的步驟一樣,那么注意點是什么呢( 本文用的是uniapp去開發(fā)的微信小程序,也是基于 vue 的語法 )?
在 uniapp 里面我們不能寫的像我們上面那樣,因為 uniapp 是不支持的,那么這個時候我們?nèi)绾稳ゴ_保頁面加載完成時,多語言可以全部返回呢?
答:做一個預(yù)加載頁,當我們多語言成功返回以后跳轉(zhuǎn)至業(yè)務(wù)頁面
1. 完成上方基礎(chǔ) VFrame 創(chuàng)建,main.js 中掛載,但是不要在用 new vue 勿動(不然會報錯)!
因為小程序有 Tabbar 所以我們的 VFrame.js 需要多一個方法;
import { request } from "util/request.js"; export default class VFrame { static applicationResource; /** * 在vue實例化之前調(diào)用異步start方法 */ static start() { return new Promise((resolve, reject) => { request({ url: '/application/getAppAll', //activityType=0 查詢?nèi)? method: 'GET', hideLoading: true, data: { orgId: uni.getStorageSync('companyOrgId') } }).then(res => { VFrame.applicationResource = res.data.result resolve(res) }); }); } static l(key, args) { if (VFrame.applicationResource && VFrame.applicationResource.language_texts) { let res = VFrame.applicationResource.language_texts[key]; if (res) { return res; } else { return `[${key}]` } } return key; } static tabbarLanguage(tabbarList) { let language = uni.getStorageSync('language') || 'zh-CN' if (language) { switch (language) { case 'en-GB': tabbarList[0].text = "Coupons" tabbarList[1].text = "Stamp" tabbarList[2].text = "Account" tabbarList[3].text = "Discount" tabbarList[4].text = "Favourite" break case 'zh-CN': tabbarList[0].text = "電子優(yōu)惠券" tabbarList[1].text = "電子印花" tabbarList[2].text = "我的賬戶" tabbarList[3].text = "優(yōu)惠獎賞" tabbarList[4].text = "我的最愛" break case 'zh-HK': tabbarList[0].text = "電子優(yōu)惠券" tabbarList[1].text = "電子印花" tabbarList[2].text = "我的賬戶" tabbarList[3].text = "優(yōu)惠獎賞" tabbarList[4].text = "我的最愛" break } } return tabbarList } }
2. 預(yù)加載頁面的制作
新建 preload.vue
<template> <view class="preload">fashion-cue</view> </template> <script> import { mapMutations } from 'vuex'; import VFrame from '@/util/VFrame'; export default { name: 'Preload', // 預(yù)加載動畫頁面 data() { return {}; }, methods: { ...mapMutations(['setAppAll']) }, onLoad(e) { console.log('onLoad', e); VFrame.start().then(res => { if (res && res.data.result.brandList && res.data.result.categoryList) { this.setAppAll(res.data.result); } getApp().globalData.isLoaded = true; uni.switchTab({ url: e.redirect ? '/' + e.redirect : '/platforms/mp-weixin/discount/discount' }); }); } }; </script> <style> .preload { width: 100%; font-weight: bold; font-family: 'Arial', 'Microsoft YaHei', '黑體', '宋體', sans-serif; font-size: 2.5rem; text-align: center; background-image: -webkit-linear-gradient(left, black, transparent 25%, black 50%, transparent 75%, black); -webkit-text-fill-color: transparent; -webkit-background-clip: text; -webkit-background-size: 200% 100%; -webkit-animation: masked-animation 2s infinite linear; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -140%); } @-webkit-keyframes masked-animation { 0% { background-position: 0 0; } 100% { background-position: -100% 0; } } </style>
3. 切換語言
切換語言是再次調(diào)用我們的 VFrame.js 中的 start() 方法即可;
但是小程序切換要注意幾個點:
① 自定義請求頭的特殊處理
② 切換完成以后需要刷新當前頁面
③ Tabbar 頁面需要再 onShow 時處理
結(jié)語:
其實實現(xiàn)步驟略微有些繁瑣,但是并不難,主要還是后端大佬的配合!
到此這篇關(guān)于前端不使用i18n該如何優(yōu)雅的實現(xiàn)多語言的文章就介紹到這了,更多相關(guān)前端實現(xiàn)多語言內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript面向?qū)ο髣?chuàng)建對象的方式小結(jié)
這篇文章主要介紹了javascript面向?qū)ο髣?chuàng)建對象的方式,結(jié)合實例形式總結(jié)分析了javascript常見的7種創(chuàng)建對象的方式,需要的朋友可以參考下2019-07-07JavaScript對象數(shù)組排序函數(shù)及六個用法
本文給大家分享一個用于數(shù)組或者對象的排序的函數(shù)。該函數(shù)可以以任意深度的數(shù)組或者對象的值作為排序基數(shù)對數(shù)組或的元素進行排序2015-12-12