[6.x] Skip React Intl placeholder during pseudo localization. (#26465)

This commit is contained in:
Aleh Zasypkin 2018-11-30 14:19:08 +01:00 committed by GitHub
parent 21ffb1ed5e
commit 432cf1b562
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -25,6 +25,28 @@ import * as i18n from '../core';
import { isPseudoLocale, translateUsingPseudoLocale } from '../core/pseudo_locale';
import { injectI18n } from './inject';
/**
* To translate label that includes nested `FormattedMessage` instances React Intl
* replaces them with special placeholders (@__uid__@ELEMENT-uid-counter@__uid__@)
* and maps them back with nested translations after `formatMessage` processes
* original string, so we shouldn't modify these special placeholders with pseudo
* translations otherwise React Intl won't be able to properly replace placeholders.
* It's implementation detail of the React Intl, but since pseudo localization is dev
* only feature we should be fine here.
* @param message
*/
function translateFormattedMessageUsingPseudoLocale(message: string) {
const formattedMessageDelimiter = message.match(/@__.{10}__@/);
if (formattedMessageDelimiter !== null) {
return message
.split(formattedMessageDelimiter[0])
.map(part => (part.startsWith('ELEMENT-') ? part : translateUsingPseudoLocale(part)))
.join(formattedMessageDelimiter[0]);
}
return translateUsingPseudoLocale(message);
}
/**
* If pseudo locale is detected, default intl.formatMessage should be decorated
* with the pseudo localization function.
@ -34,7 +56,8 @@ function wrapIntlFormatMessage(child: React.ReactNode) {
return React.createElement(
injectI18n(({ intl }) => {
const formatMessage = intl.formatMessage;
intl.formatMessage = (...args) => translateUsingPseudoLocale(formatMessage(...args));
intl.formatMessage = (...args) =>
translateFormattedMessageUsingPseudoLocale(formatMessage(...args));
return React.Children.only(child);
})