Fusion組件庫是如何支持多語言能力的

隨著國際化發展,多語言的需求越來越常見,單一的語言已經遠不能滿足需求了。作為一個組件庫,支持多語言也是基本能力。 多語言功能的本質其實是文本的替換,一個詞匯“OK”,在英文語境下是“OK”,日語語境下是“確認”,中文語境下可能是“確定”也可能是“確認”“好的”等等。

本文將以簡單組件為切入點,向大家展示Fusion組件庫是如何支持多語言能力的。

單組件的多語言

我們以一個常見的組件Search舉例,用戶輸入內容后可通過點擊“搜索”、“清除”按鈕觸發相應的事件,簡化代碼后如下:

class Search extends React.Component {render() {return (<div><input /><button>搜索</button><button>清除</button></div>);}
}export default Search;
復制代碼

多語言處理最簡單直接的辦法是直接替換文本,不同語言環境下可能要將“搜索”替換為“search”、“サーチ”,將“清除”替換為“clear”、"クリア"等。同時作為一個組件庫,涉及到的大多是簡單詞匯而不是句子,因此我們首選配置化的方式:

// 抽取語言包
// search-en-us.js
{search: 'search',clear: 'clear'
}
// search-zh-cn.js
{search: '搜索',clear: '清除'
}
復制代碼
import searchZhCN from 'search-zh-cn';class Search extends React.Component {static propTypes = {locale: PropTypes.object};static defaultProps = {locale: searchZhCN};render() {return (<div><input /><button>{locale.search}</button><button>{locale.clear}</button></div>);}
}export default Search;
復制代碼

這樣就實現了單個組件Search的多語言支持。

但是,為每個組件對應一個語言包文件的做法顯然很不方便。Fusion Next作為一個PC端的React組件庫有50+組件,內置詞匯70多條,目前有13個組件需要國際化語言能力。

以語種為單位,將同一種語言下的映射關系放到一個文件里進行處理的方式更為高效。

多組件的多語言

為便于維護管理,增強可拓展性,我們以語種為單位抽取語言包。將同一語種下所有組件的語言對象{key: '文案'}放到一起,以displayName作為key,語言對象作為value,調整語言包如下:

// 抽取語言包
// zh-cn.js
{Search: {search: '搜索',clear: '清除'},Dialog: {},...
}
復制代碼

這也是Fusion現在語言包的結構 unpkg.com/@alifd/next… 由于語言包結構的調整,需要同時修改Search組件語言對象的默認值:

import zhCN from 'zh-cn';class Search extends React.Component {...static defaultProps = {locale: zhCN.Search}...
}export default Search;
復制代碼

在使用時,用戶將語言包對象以props參數的形式傳給組件即可直接改變文案:

import jaJP from 'xxxx/ja-jp.js';<Search locale={jaJP.Search}>
<Dialog locale={jaJP.Dialog}>
復制代碼

然而,在web應用越來越復雜的現在,很多項目里里可能會用到幾十甚至上百個組件,這樣給每個組件手動傳locale參數的方式一方面比較蠢,另一方面開發者需要關心locale參數,在語言切換時改變值的內容。

并且語言的設置大都是以項目(或者頁面)為單位的,有沒有更聰明、對開發者更友好的使用方式呢?

一鍵設置語言

如果你使用過Fusion Next或者體驗過多語言demo,就可以發現使用方式是這樣的:

import zhCN from 'zh-cn';<ConfigProvider locale={zhCN}><Search /><Dialog />
</ConfigProvider>
復制代碼

使用者在使用時基礎組件時不用關心locale的變化,子組件們共享了<ConfigProvider>組件上傳入的語言配置,更改這一配置可以一鍵設置子組件的語言包。如何實現的這一功能呢?

React中,如果不想通過逐層傳遞props或者state的方式來傳遞數據,不如考慮考慮Context。

1. React Context共享上下文數據

借助Context可以實現跨層級的組件數據傳遞。

它的使用場景是生產者消費者模式,在上面的例子中,<ConfigProvider>就是生產者,<Search> <Dialog>組件就是消費者。 他們分別通過一系列屬性方法(childContextTypes屬性 getChildContext方法/contextTypes屬性),建立起一條通信線。

// 生產者
class ConfigProvider extends React.Component {// 聲明Context對象static childContextTypes = {nextLocale: PropTypes.object}// 返回Context對象getChildContext () {return {nextLocale: {}}}render () {return this.props.children;}
}
復制代碼
// 消費者
import zhCN from 'zh-cn';class Search extends React.Component {static propTypes = {locale: PropTypes.object};static defaultProps = {locale: zhCN.Search};// 聲明需要使用的Context屬性static contextTypes = {nextLocale: PropTypes.object};render() {const locale = Object.assign({}, nextLocale['Search'], locale);return (<div><input /><button>{locale.search}</button><button>{locale.clear}</button></div>);}
}export default Search;
復制代碼

這樣,直接給<ConfigProvider>傳遞國際化參數,就可以改變其子組件所使用的語言包。

數據傳遞的問題解決了,按照這個思路對組件進行改造就可以完美支持一鍵切換語言了~ 事實上,這個解決方案通用性很強,只要子組件(包括自定義組件)都按上面的方式進行改造,就可以支持語言包的切換。

但同時我們也發現,改造工作高度重復,都是新增contextTypes靜態屬性、對props和context上的locale進行merge。有沒有對開發者(基礎組件開發者、業務組件開發者)更友好的方式來降低這部分重復性工作呢?

2.子組件的統一處理

Fusion為Util類組件ConfigProvider增加了一個靜態方法ConfigProvider.config(Component),在這個函數里進行對于locale的改造工作,它返回一個新的受控制的高階組件(HOC)NewComponent。

NewComponent 相當于被 ConfigProvider 代理了一層。

在ConfigProvider.config()這個函數里

  • 為組件新增contextTypes靜態屬性,以便接收來自父組件的context;
  • 為組件props、context傳入的locale進行merge,以便分發處理語言包文案;

這樣,只要子組件經過該函數處理,就可以讓ConfigProvider“遙控”語言包切換

import zhCN from 'zh-cn';class Search extends React.Component {static propTypes = {locale: PropTypes.object};static defaultProps = {locale: zhCN.Search};render() {return (<div><input /><button>{locale.search}</button><button>{locale.clear}</button></div>);}
}
// 經過統一處理
export default ConfigProvider.config(Search);
復制代碼

ConfigProvider.config(Component)的語言包文案分發處理邏輯簡化如下:

// ConfigProvider.jsx
function config(Component) {class ConfigedComponent extends React.Component {static propTypes = {...(Component.propTypes || {}),locale: PropTypes.object,};static contextTypes = {...(Component.contextTypes || {}),nextLocale: PropTypes.object,};render() {// 組件props上直接設置const { locale } = this.props;// ConfigProvider"遙控"設置const { nextLocale = {} } = this.context;// 組件上直接設置語言包,優先級高于在父組件ConfigProvider上設置。const newLocale = Object.assign({},nextLocale[Component.displayName],locale);return (<Component locale={newLocale}/>);}}return ConfigedComponent;
}
復制代碼

這樣就基本完成了組件庫的多語言能力建設,這也是Fusion Next組件庫的多語言支持的思路。

除此之外,ConfigProvider還有內置了其他通用能力,例如組件的鏡像反轉RTL,pure render開關、修改樣式的默認前綴等,更多可以查看 ConfigProvider源代碼 和 使用文檔 了解。

相關鏈接

  • Fusion 多語言切換demo: codepen.io/aboutblank/…
  • Fusion ConfigProvider: fusion.design/component/c…
  • github: github.com/alibaba-fus…

轉載于:https://juejin.im/post/5c6bb4d4f265da2dbd7ff1e0

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536942.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536942.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536942.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql 存儲過程 replace_mysql replace存儲過程

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云數據庫專家保駕護航&#xff0c;為用戶…

注解版poi操作工具

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

Kali Linux 2019.1 發布,Metasploit 更新到 5.0 版本

百度智能云 云生態狂歡季 熱門云產品1折起>>> Kali Linux 2019.1 發布了&#xff0c;Kali 前身 BackTrack&#xff0c;它是一個基于 Debian 的 Linux 發行版&#xff0c;主要用于信息安全行業&#xff0c;其包含了一系列安全、滲透測試和取證工具。此版本 Linux 內核…

peewee mysql_scrapy中利用peewee插入Mysql

前兩天老大布置一個任務&#xff0c;說爬下來的數據要存入數據庫中&#xff0c;丟給我一個peewee&#xff0c;說用這個。當時的我兩眼一抹黑&#xff0c;這是個什么東西呀&#xff0c;我知道scrapy的數據存入數據庫是在pipelines中進行設置但是peewee是什么東西呢。經過兩天不懈…

Java版數據結構與算法——線性表

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

基于 CODING 的 Spring Boot 持續集成項目

本文作者&#xff1a;CODING 用戶 - 廖石榮 持續集成的概念 持續集成(Continuous integration,簡稱 CI&#xff09;是一種軟件開發實踐&#xff0c;即團隊開發成員經常集成他們的工作&#xff0c;通常每個成員每天至少集成一次&#xff0c;也就意味著每天可能會發生多次集成。每…

lvs mysql 端口_LVS配置及多端口服務配置

一、5、各主機IP地址&#xff1a;主機IP網關Client192.168.86.116RouterF0/0:192.168.x.xFo/1:192.168.xx.xxF0/1DirectorEth0:192.168.86.111/24(DIP)Eth0:1:192.168.86.254/32(VIP)F0/1Real 1Eth0:192.168.86.112/24(DIP)lo:1:192.168.86.254/32(VIP)F0/1Real 2Eth0:192.168.…

Mybatis組成部分

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

Stream流與Lambda表達式(一) 雜談

一、流 轉換為數組、集合 package com.java.design.java8.Stream;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;import java.util.A…

一年java工作經驗-面試總結

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

linux mysql python包_03_mysql-python模塊, linux環境下python2,python3的

---恢復內容開始---1、Python2 正常[rootIP ~]#pip install mysql-pythonDEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 wont be maintained after that date. A future version of pip will drop …

我的這套VuePress主題你熟悉吧

最近熬了很多個夜晚, 踩坑無數, 終于寫出了用VuePress驅動的主題. 只需體驗三分鐘&#xff0c;你就會跟我一樣&#xff0c;愛上這款主題. vuepress-theme-indigo-material, 已經發布到npm, 請客官享用~~ 介紹 vuepress-theme-indigo-material 的原主題是hexo-theme-indigo, git…

兩年Java工作經驗應該會些什么技術

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

centos 6 mysql 5.7.13 編譯安裝_Centos 6.5 下面 源碼編譯 安裝 Mysql 5.7.13

安裝軟件依賴包yum -y install gcc gcc-c ncurses ncurses-devel cmake下載軟件包cd /usr/local/srcwget https://downloads.mysql.com/archives/get/file/mysql-5.7.13.tar.gz --no-check-certificate下載 boost 庫&#xff0c;MySQL 5.7.5 開始Boost庫是必需的cd /usr/loca…

LeetCode 237. 刪除鏈表中的節點(Python3)

題目&#xff1a; 請編寫一個函數&#xff0c;使其可以刪除某個鏈表中給定的&#xff08;非末尾&#xff09;節點&#xff0c;你將只被給定要求被刪除的節點。 現有一個鏈表 -- head [4,5,1,9]&#xff0c;它可以表示為: 示例 1: 輸入: head [4,5,1,9], node 5 輸出: [4,1,9…

使用Uniapp隨手記錄知識點

使用uniapp隨手記錄知識點 1 組件內置組件擴展組件 2 vuex狀態管理使用流程mapState 輔助函數gettersMutation 1 組件 內置組件 內置組件內主要包含一些基礎的view button video scroll-view等內置基礎組件&#xff0c;滿足基礎場景 擴展組件 擴展組件是uniapp封裝了一些成…

一年Java經驗應該會些什么

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

mysql查詢各類課程的總學分_基于jsp+mysql的JSP學生選課信息管理系統

運行環境: 最好是java jdk 1.8&#xff0c;我們在這個平臺上運行的。其他版本理論上也可以。IDE環境&#xff1a; Eclipse,Myeclipse,IDEA都可以硬件環境&#xff1a; windows 7/8/10 2G內存以上(推薦4G&#xff0c;4G以上更好)可以實現&#xff1a; 學生&#xff0c;教師角色的…

80端口占用分析

SQL Server 2008 里面的組件——SQL Server Reporting Services (MSSQLSERVER)。是 SQL Server 的日志系統&#xff0c;就是他好端端的突然占用了80端口&#xff0c;而且對于普通人來講&#xff0c;這個組件的作用沒啥用&#xff0c;關掉也是節約資源。 關閉服務 ReportServer …

三年java經驗應該會什么?

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…