這篇文章主要講解了如何實(shí)現(xiàn)微信小程序國(guó)際化探索,內(nèi)容清晰明了,對(duì)此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會(huì)有幫助。
站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到開(kāi)封網(wǎng)站設(shè)計(jì)與開(kāi)封網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:網(wǎng)站制作、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋開(kāi)封地區(qū)。
一、項(xiàng)目結(jié)構(gòu)
整體目錄結(jié)構(gòu)如下圖:
二、工具類封裝及語(yǔ)言包準(zhǔn)備
2.1 語(yǔ)言包準(zhǔn)備
i18n
目錄下的各語(yǔ)言包結(jié)構(gòu)要一致,即對(duì)象的 key
保持一致, value
是對(duì)應(yīng)的語(yǔ)言文本。
建議每個(gè)小模塊分為一個(gè)對(duì)象,單個(gè)對(duì)象的內(nèi)容不宜過(guò)多。
zh-CN.js
export default { common: { language: '語(yǔ)言', chinese: '中文', english: '英語(yǔ)', }, tabBarTitles: ['主頁(yè)', '論壇', '我的'], navTitle: { home: '主頁(yè)', forum: '論壇', mine: '我的', setting: '設(shè)置' }, home: { motto: '我們寧愿擁有一個(gè)不完美的變革,也不愿看到一個(gè)沒(méi)有希望的未來(lái)', respect: '致勇者', getUserInfo: '獲取頭像昵稱' }, forum: { forumModule: '我是論壇模塊', tip: '下面是一個(gè)組件,用來(lái)展示組件的國(guó)際化配置' }, comment: { title: '評(píng)論組件', msg: '網(wǎng)絡(luò)一線牽,珍惜這段緣' }, mine: { title: '這是我的頁(yè)面', toNewPage: '跳轉(zhuǎn)到新頁(yè)面' }, setting: { title: '我是設(shè)置頁(yè)面' } }
en-US.js
export default { common: { language: 'Language', chinese: 'Chinese', english: 'English', }, tabBarTitles: ['Home', 'Forum', 'Mine'], navTitle: { home: 'Home', forum: 'Forum', mine: 'Mine', setting: 'setting' }, home: { motto: 'We would rather have an imperfect change than see a hopeless future', respect: 'to warrior', getUserInfo: 'Get avatar nickname' }, forum: { forumModule: 'I am forum module', tip: 'The following is a component to show the international configuration of the component' }, comment: { title: 'Comment Components', msg: 'The network leads, cherish this relationship' }, mine: { title: 'This is mine page', toNewPage: 'Go to new page' }, setting: { title: 'I am setting page' } }
2.2 工具類 LangUtils 封裝
工具類 LangUtils
封裝了國(guó)際化所需的所有方法,包括獲取當(dāng)前語(yǔ)言、設(shè)置語(yǔ)言、獲取當(dāng)前語(yǔ)言的資源文件、設(shè)置 TabBar
、設(shè)置 NavigationBar
等方法。
實(shí)現(xiàn)思路是把當(dāng)前設(shè)置的語(yǔ)言存在小程序提供的 storage 中,每次項(xiàng)目初始化時(shí)從 storage
中讀取語(yǔ)言,如果沒(méi)有讀到則默認(rèn)設(shè)置為中文。
然后在每個(gè)頁(yè)面或組件的 data
中將頁(yè)面需要用到的文本資源引入進(jìn)來(lái), wxml
中使用 data
中綁定的變量展示文字。同時(shí)在生命周期的 onShow
方法中重新讀取當(dāng)前語(yǔ)言并設(shè)置 data
,使得每次改變語(yǔ)言都能正確的加載語(yǔ)言包。
先看 LangUtils
的代碼:
import zh from '../i18n/zh-CN.js' import en from '../i18n/en-US.js' import Constants from '../constants/Constants'; export default{ //初始化語(yǔ)言設(shè)置。在 app.js 里調(diào)用這個(gè)方法。 initLang(){ //先獲取是不是已存在語(yǔ)言的設(shè)置 let lang = wx.getStorageSync('lang') if(!lang){ //如果不存在,設(shè)置默認(rèn)語(yǔ)言為中文 this.setLang(Constants.langCN) } }, //設(shè)置語(yǔ)言 setLang(lang){ try{ wx.setStorageSync('lang', lang) }catch(e){ console.log('設(shè)置語(yǔ)言失敗', e) } }, //獲取語(yǔ)言設(shè)置 getLang(){ try{ let lang = wx.getStorageSync('lang') return lang; }catch(e){ console.log('獲取語(yǔ)言設(shè)置失敗', e) } }, //獲取當(dāng)前語(yǔ)言下的資源文件 getLangSrc(){ let lang = this.getLang(); if(lang === Constants.langCN){ return zh; } else if(lang === Constants.langEN){ return en; }else{ return zh; } }, //設(shè)置 NavigationBarTitle setNavigationBarTitle(title){ wx.setNavigationBarTitle({ title: title }) }, /** * 設(shè)置 tabBar。因?yàn)?tabBar 是在 app.json 里寫死的,需要使用 wx.setTabBarItem * 循環(huán)設(shè)置 tabBar */ setTabBarLang(){ let tabBarTitles = this.getLangSrc().tabBarTitles; console.log('tabBarTitles', tabBarTitles) tabBarTitles.forEach((item, index) => { console.log(item, index) wx.setTabBarItem({ index: index, text: item, success: (res) => { console.log('setTabBarItem success', res) }, fail: (err) => { console.log('setTabBarItem fail', err) } }); }); }, }
先引入中文和英文的語(yǔ)言包,以便根據(jù)當(dāng)前語(yǔ)言設(shè)置返回對(duì)應(yīng)的資源包。
Constants
是對(duì)常量的封裝,這里保存的是中英文編碼標(biāo)識(shí)。
Constants.js /** * 保存項(xiàng)目中的常量 */ export default{ //中文編碼 langCN: 'zh-CN', //英文編碼 langEN: 'en-US', }
需要注意的是 tabBar
的處理,因?yàn)?tabBar
是寫死在 app.json
中的,不能動(dòng)態(tài)的改變文本,所以每次語(yǔ)言改變只能用小程序暴露出來(lái)的 wx.setTabBarItem
方法循環(huán)的設(shè)置 tabBar
。
至此前期的準(zhǔn)備工作已經(jīng)做完啦,接下來(lái)對(duì)具體的頁(yè)面和組件做處理。
三、項(xiàng)目使用
需要改動(dòng)三個(gè)地方
app.js
初始化語(yǔ)言xxx.js
的 data
添加語(yǔ)言屬性,并在 onShow
生命周期方法中調(diào)用 setData
重新設(shè)置語(yǔ)言xxx.wxml
中的文本替換為 data
里綁定的變量3.1 app.js 初始化語(yǔ)言
在項(xiàng)目入口文件 app.js
中做初始化。
//初始化國(guó)際化語(yǔ)言設(shè)置 import LangUtils from './utils/LangUtils' App({ onLaunch: function () { // 國(guó)際化的初始化 LangUtils.initLang(); LangUtils.setTabBarLang(); } })
3.2 Page 頁(yè)面的國(guó)際化 js 中使用
js 中的使用分三步:
首先引入 LangUtils.js
然后在 data
中定義變量 lang
,通過(guò) ...
對(duì)象的解構(gòu)賦值,把語(yǔ)言文件中對(duì)應(yīng)模塊定義的變量都賦值給 lang
,方便調(diào)用。如果是 settings 模塊,可以這樣寫: lang: {...LangUtils.getLangSrc().settings}
。也可以只寫個(gè)空對(duì)象: lang: {}
,然后在 onShow()
方法里對(duì) lang
賦值。
onShow()
生命周期方法里,更新 lang
的值,以防語(yǔ)言被改變。如果需要設(shè)置小程序標(biāo)題,則再調(diào)用 LangUtils.setNavigationBarTitle()
方法。
// pages/setting/setting.js import LangUtils from '../../utils/LangUtils' let langSrc = LangUtils.getLangSrc() Page({ /** * 頁(yè)面的初始數(shù)據(jù) */ data: { lang: { ...langSrc.setting } }, /** * 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面顯示 */ onShow: function () { this.setLanguage(); }, /** * 重新設(shè)置語(yǔ)言 */ setLanguage() { langSrc = LangUtils.getLangSrc(); this.setData({ lang: { ...langSrc.setting } }) // 設(shè)置 NavigationBarTitle LangUtils.setNavigationBarTitle(langSrc.navTitle.setting); } })
wxml 中使用
wxml 里比較簡(jiǎn)單,跟普通的變量使用方法一樣。
{{lang.title}}
3.2 Component 組件的國(guó)際化
Component
跟 Page
國(guó)際化基本上相同,但因?yàn)樯芷诜椒ú煌?,稍微有點(diǎn)區(qū)別。
Coponents
的 this.setLanguage()
在生命周期的 pageLifetimes
的 show
方法中調(diào)用。
// pages/forum/components/comment.js import LangUtils from '../../../../utils/LangUtils' let langSrc = LangUtils.getLangSrc(); Component({ data: { lang: { ...langSrc.comment } }, pageLifetimes: { // 組件所在頁(yè)面的生命周期函數(shù) show: function () { console.log('page show---') this.setLanguage(); }, }, /** * 組件的方法列表 */ methods: { /** * 重新設(shè)置語(yǔ)言 */ setLanguage() { langSrc = LangUtils.getLangSrc(); this.setData({ lang: { ...langSrc.comment } }) } } })
3.3 切換語(yǔ)言
切換語(yǔ)言放在 demo 的 home
頁(yè)面中。用戶更改語(yǔ)言后要調(diào)用 LangUtils.setLang
更改語(yǔ)言值,還要調(diào)用 LangUtils.setTabBarLang
重新設(shè)置 tabBar
的文本。
切換后的效果
//index.js //獲取應(yīng)用實(shí)例 const app = getApp() import Constants from '../../constants/Constants' // 獲取對(duì)應(yīng)語(yǔ)言的資源文件 import LangUtils from '../../utils/LangUtils' let langSrc = LangUtils.getLangSrc(); // 語(yǔ)言選項(xiàng) const LANGUAGE_OPTIONS = [{ key: Constants.langCN, value: '中文' }, { key: Constants.langEN, value: 'English' } ] Page({ data: { // 通過(guò)解構(gòu)賦值將 common 和 home 下的變量賦值給 lang。最好每個(gè)模塊建一個(gè)對(duì)象 // 對(duì)象里的屬性不宜過(guò)多,否則在 data 里放入太多內(nèi)容會(huì)影響性能,用到什么放什么。 lang: { ...langSrc.common, ...langSrc.home }, langOptions: LANGUAGE_OPTIONS, index: 0 }, onLoad: function () { // 根據(jù)當(dāng)前語(yǔ)言設(shè)置 picker 默認(rèn)選中的值 let lang = LangUtils.getLang(); this.setData({ index: lang === Constants.langCN ? 0 : 1 }) }, onShow: function () { //每次 onShow 重新設(shè)置語(yǔ)言,以防語(yǔ)言更新 this.setLanguage(); }, getUserInfo: function (e) { console.log(e) app.globalData.userInfo = e.detail.userInfo this.setData({ userInfo: e.detail.userInfo, hasUserInfo: true }) }, /** * 選擇語(yǔ)言變化回調(diào)函數(shù) */ onLanguageChange(e) { const index = e.detail.value console.log(e) this.setData({ index: index }) // 更改語(yǔ)言 LangUtils.setLang(this.data.langOptions[index].key); // 重新設(shè)置 tabBar 的語(yǔ)言 LangUtils.setTabBarLang(); this.setLanguage(); }, /** * 重新設(shè)置語(yǔ)言 */ setLanguage() { langSrc = LangUtils.getLangSrc(); this.setData({ lang: { ...langSrc.common, ...langSrc.home } }) // 設(shè)置 NavigationBarTitle LangUtils.setNavigationBarTitle(langSrc.navTitle.home); } })
四、總結(jié)
代碼乍一看還挺多的,但優(yōu)點(diǎn)是不用引入第三方模塊,也不用按要求改項(xiàng)目結(jié)構(gòu)。其實(shí)把前期的準(zhǔn)備工作做完后,后期維護(hù)起來(lái)還是很方便的。
當(dāng)然這個(gè)方案還有可優(yōu)化的地方,比如每個(gè)頁(yè)面的 onShow
方法里都要執(zhí)行相似的邏輯,以后有時(shí)間會(huì)做優(yōu)化。
看完上述內(nèi)容,是不是對(duì)如何實(shí)現(xiàn)微信小程序國(guó)際化探索有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。