[Feature discussion] more robust built-in support for i18n
See original GitHub issueWhat problem does this feature solve?
Let’s see the truth
I suppose that we probably would like to create agnostic to any i18n library, but let’s see the truth - it’s NOT agnostic already - antd using own tiny library to solve i18n problems and LocaleProvider is part of it.
More over, because of lack of functionalities we have to create hacks here and there, extend it with getLocale() in most components that needed it and etc.
I suggest to revise it and use external solution (I still remember time when we switched to moment for dates).
There are 3 main players on the market: i18next, react-intl and polyglot. I suggest to stick with polyglot
And here is my why:
-
it’s small and not bloated - 2.8k minified (probably we already have half of it to solve i18n problems with own implementation)
-
interpolation and pluralization out of box (E.g.: Pagination/Transfer already potential users of pluralization)
-
easy to use, easy to integrate, really small API to learn
-
it’s battle-tested and supported by Airbnb
What does the proposed API look like?
How it can helps us? (just example)
- we will create global variable at _utils
polyglot = new Polyglot();
- remove own workarounds to get i18n and replace it with something like:
polyglot.t('Table.filterTitle', {_: 'default title'});
-
all current locale files will be same as right now - without any changes
-
to change locale for app we will use LocaleProvider as like now but with some changes(just example):
import React, { PropTypes } from 'react';
import { polyglot } from '../utils';
/**
* i18n provider with some shorthand helpers
*/
export class I18Provider extends React.Component {
initLocale({ locale, messages }) {
polyglot.locale(locale);
polyglot.clear();
polyglot.extend(messages);
}
getChildContext = () => ({
i18n: polyglot.t.bind(polyglot)
});
componentWillMount() {
this.initLocale(this.props);
}
componentWillReceiveProps(nextProps) {
if (nextProps.locale !== this.props.locale) {
this.initLocale(nextProps);
}
}
render() {
return React.Children.only(this.props.children);
}
}
I18Provider.propTypes = {
children: PropTypes.element.isRequired,
locale: React.PropTypes.string.isRequired,
messages: React.PropTypes.object.isRequired,
};
I18Provider.childContextTypes = {
i18n: PropTypes.func.isRequired,
};
/**
* i18n wrapper for component
* @param WrappedComponent
* @returns {function(*, *): XML}
*/
export const injectI18n = (WrappedComponent) => {
function getDisplayName(component) {
return component.displayName || component.name || 'Component';
}
const InjectI18n = (props, context) => <WrappedComponent {...props} i18n={context.i18n} />;
InjectI18n.contextTypes = {
i18n: PropTypes.func.isRequired,
};
InjectI18n.displayName = `InjectI18n(${getDisplayName(WrappedComponent)})`;
return InjectI18n;
};
-
after that anyone will have built-in support for i18n. And no any magic anymore. Just 2.8Kb to bundle and functionalities that will be enough for 99% of apps.
-
moreover, to override built-in locale we will need to do just something like this:
polyglot.extend({
Table: {
filterTitle: 'my supper title!',
}
);
Issue Analytics
- State:
- Created 6 years ago
- Comments:15 (15 by maintainers)
Top GitHub Comments
I can refactor code and make PR for last version that I wrote here.
@benjycui it’s 1, 2 and also:
LocaleProvider doesn’t support pluralization, E.g. Transfer uses singular and plural words (item/items), but in Russian we have like 5 cases for plural.
If I want to create own component based on antd and make it public, then I will have to solve i18n problem by self again, because antd doesn’t provide any functionalities for it.
If I want to make app to support i18n, then I will have to solve this problem again.
I just ask, why end-users must solve i18n problem again and again when antd already solved it internally with own limited solution (no pluralization)?! If antd will provide public API for i18n (just improve LocaleProvider a bit), then users will not have any problems with i18n locales in own apps in 99% cases.
Let’s recap. E.g. we upgrade LocaleProvider with these methods:
In this case our LocaleProvide will solve all the cases that I mentioned: 1,2,3,4,5: for 1,3,4,5 - use antLocale.t, for 2 - use antLocale.extend,
For Components we can improve injectLocale too. E.g.:
and use it like this:
From app side user can use antLocale like this:
So as you see, in 99% cases built-in LocaleProvider will be enough in that case