Simplify pseudo localization for React components. (#24903)

This commit is contained in:
Aleh Zasypkin 2018-11-02 08:57:47 +01:00 committed by GitHub
parent 6e63be54ef
commit 415be6bf91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -19,10 +19,27 @@
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { IntlProvider, intlShape } from 'react-intl';
import { IntlProvider } from 'react-intl';
import * as i18n from '../core';
import { isPseudoLocale, translateUsingPseudoLocale } from '../core/pseudo_locale';
import { injectI18n } from './inject';
/**
* If pseudo locale is detected, default intl.formatMessage should be decorated
* with the pseudo localization function.
* @param child I18nProvider child component.
*/
function wrapIntlFormatMessage(child: React.ReactNode) {
return React.createElement(
injectI18n(({ intl }) => {
const formatMessage = intl.formatMessage;
intl.formatMessage = (...args) => translateUsingPseudoLocale(formatMessage(...args));
return React.Children.only(child);
})
);
}
/**
* The library uses the provider pattern to scope an i18n context to a tree
@ -31,30 +48,8 @@ import { isPseudoLocale, translateUsingPseudoLocale } from '../core/pseudo_local
*/
export class I18nProvider extends React.PureComponent {
public static propTypes = { children: PropTypes.element.isRequired };
public static contextTypes = { intl: intlShape };
public static childContextTypes = { intl: intlShape };
public getChildContext() {
// if pseudo locale is set, default intl.formatMessage should be decorated
// with the pseudo localization function
if (this.context.intl && isPseudoLocale(i18n.getLocale())) {
const formatMessage = this.context.intl.formatMessage;
this.context.intl.formatMessage = (...args: any[]) => {
return translateUsingPseudoLocale(formatMessage.apply(this.context.intl, args));
};
}
return { intl: this.context.intl };
}
public render() {
const child = React.Children.only(this.props.children);
if (this.context.intl) {
// We can have IntlProvider somewhere within ancestors so we just reuse it
// and don't recreate with another IntlProvider
return child;
}
return (
<IntlProvider
locale={i18n.getLocale()}
@ -64,12 +59,9 @@ export class I18nProvider extends React.PureComponent {
defaultFormats={i18n.getFormats()}
textComponent={React.Fragment}
>
{
// We use `<I18nProvider>{child}</I18nProvider>` trick to decorate intl.formatMessage
// in `getChildContext()` method. I18nProdiver will have `this.context.intl` so the
// recursion won't be infinite
}
{isPseudoLocale(i18n.getLocale()) ? <I18nProvider>{child}</I18nProvider> : child}
{isPseudoLocale(i18n.getLocale())
? wrapIntlFormatMessage(this.props.children)
: this.props.children}
</IntlProvider>
);
}