虽然本文的题目叫“组件之路---国际化”,但是本文并不是讲国际化方案的,本文的重点是基于antd国际化组件的实现,去分析一类问题的解决思路。
LocaleProvider国际化
antd实现国际化的组件是LocaleProvider,即将需要国际化的组件作为LocaleProvider的子组件使用:
<LocaleProvider>
<A />
<B />
<LocaleProvider>
这里组件A与组件B是在需要的时候进行国际化转换的组件。
这里考虑LocaleProvider与A B组件该如何实现呢?
首先看一个应用方面的需求,如下图所示:
页面中罗列了若干种需要进行国际化的组件,我们选择在中英文两种语言下切换,所有的组件都需要完成更新。
设计思路
1:每个需要国际化的组件都应该有其自身的文案,该文案的组织应该与该组件在同一个目录下:
ComponentA-|
index.js
Locale-|
zh_CN.js
zh_TW.js
en_US.js
...
ComponentB-|
index.js
Locale-|
zh_CN.js
zh_TW.js
en_US.js
...
2:将这些分散的组件文案统一管理。
//index.js
var zh_CN1 = require("ComponentA/Locale/zh_CN");
var zh_CN2 = require("ComponentB/Locale/zh_CN");
export default {
ComponentA:zh_CN1,
ComponentB:zh_CN2,
}
3:容器组件统一在文案中获取数据
var zh_CN = require("./index");
再根据需求将其传给不同的组件
<A locale={zh_CN['ComponentA']} />
<B locale={zh_CN['ComponentB']} />
在逻辑和功能上以上步骤是没有问题的,但是这里我们需要考虑一点就是通过这种参数传递的方式,最好的情况是组件A B就是需要国际化的组件,但是如果需要组件化的组件嵌套在其他组件之内呢?是否需要将参数层层传递呢?
这其实是一个很常见的问题,react中有context的概念可以帮助我们解决这个问题,antd的LocaleProvider其实就是基于context提供文案信息的。
基于context的实现
LocaleProvider作为容器组件,为其他所有子组件提供统一的数据,LocaleProvider需定义childContextTypes以及getChildContext。
static childContextTypes = {
antLocale: PropTypes.object,
};
getChildContext() {
return {
antLocale: {
...this.props.locale,
exist: true,
},
};
}
需要国际化的子组件定义contextTypes,然后通过this.context在组件内部使用传入的文案信息。
static contextTypes = {
antLocale: PropTypes.object,
};
const { antLocale } = this.context;
总结
react 中虽然提供了context这样的方式,但是官方并不推荐直接使用,除非你很清楚的知道你在干什么的情况下。如果你的应用中出现了若干只能通过变量提升或者context的方式传递数据才能解决问题的话,你就需要考虑是否需要引入数据流管理工具了。