From 2708650f1797dd2fb34bb26e1b945bd5f84c72f9 Mon Sep 17 00:00:00 2001 From: SleepWalker Date: Mon, 11 Nov 2019 10:40:05 +0200 Subject: [PATCH] Upgrade to intl@^3.0.0 --- .flowconfig | 1 + babel.config.js | 2 + flow-typed/npm/react-intl_v2.x.x.js | 38 ++- package.json | 11 +- src/components/i18n/IntlProvider.js | 46 ++-- src/components/i18n/actions.js | 12 +- src/components/i18n/reducer.js | 14 +- .../languageSwitcher/LanguageSwitcher.js | 24 +- src/components/profile/Profile.js | 6 +- src/components/ui/RelativeTime.js | 19 ++ src/components/ui/form/FormComponent.js | 27 +- src/components/ui/index.js | 2 + src/components/user/actions.js | 7 +- src/index.js | 4 +- src/services/errorsDict/errorsDict.js | 5 +- src/services/i18n.js | 53 ---- src/services/i18n/i18n.js | 85 +++++++ src/services/i18n/index.js | 2 + src/services/i18n/intlPolyfill.js | 100 ++++++++ webpack.config.js | 11 +- yarn.lock | 234 ++++++++++++------ 21 files changed, 500 insertions(+), 203 deletions(-) create mode 100644 src/components/ui/RelativeTime.js delete mode 100644 src/services/i18n.js create mode 100644 src/services/i18n/i18n.js create mode 100644 src/services/i18n/index.js create mode 100644 src/services/i18n/intlPolyfill.js diff --git a/.flowconfig b/.flowconfig index 031b7ad..24d5741 100644 --- a/.flowconfig +++ b/.flowconfig @@ -17,3 +17,4 @@ module.file_ext=.jsx module.file_ext=.css module.file_ext=.scss module.ignore_non_literal_requires=true +esproposal.optional_chaining=enable diff --git a/babel.config.js b/babel.config.js index 3a244b9..88c917e 100644 --- a/babel.config.js +++ b/babel.config.js @@ -4,6 +4,8 @@ module.exports = { '@babel/plugin-syntax-dynamic-import', '@babel/plugin-proposal-function-bind', '@babel/plugin-proposal-class-properties', + '@babel/plugin-proposal-optional-chaining', + '@babel/plugin-proposal-nullish-coalescing-operator', [ '@babel/plugin-transform-runtime', { diff --git a/flow-typed/npm/react-intl_v2.x.x.js b/flow-typed/npm/react-intl_v2.x.x.js index b9a7638..38d6c10 100644 --- a/flow-typed/npm/react-intl_v2.x.x.js +++ b/flow-typed/npm/react-intl_v2.x.x.js @@ -42,7 +42,9 @@ declare module "react-intl" { declare type $npm$ReactIntl$IntlFormat = { formatDate: (value: any, options?: Object) => string, formatTime: (value: any, options?: Object) => string, - formatRelative: (value: any, options?: Object) => string, + formatRelativeTime: (value: number, options?: $npm$ReactIntl$RelativeFormatOptions & { + format: string + }) => string, formatNumber: (value: any, options?: Object) => string, formatPlural: (value: any, options?: Object) => string, formatMessage: ( @@ -77,8 +79,9 @@ declare module "react-intl" { }; declare type $npm$ReactIntl$RelativeFormatOptions = { - style?: "best fit" | "numeric", - units?: "second" | "minute" | "hour" | "day" | "month" | "year" + numeric?: "auto" | "always", + style?: "short" | "narrow" | "numeric", + unit?: "second" | "minute" | "hour" | "day" | "month" | "year" }; declare type $npm$ReactIntl$NumberFormatOptions = { @@ -161,6 +164,15 @@ declare module "react-intl" { $Diff, InjectIntlVoidProps> >; + declare type IntlCache = any; + + declare function createIntlCache(): IntlCache; + + declare function createIntl(options: { + locale: string, + messages?: {[key: string]: string} + }, cache?: IntlCache): IntlShape; + declare function formatMessage( messageDescriptor: $npm$ReactIntl$MessageDescriptor, values?: Object @@ -177,11 +189,10 @@ declare module "react-intl" { value: any, options?: $npm$ReactIntl$DateTimeFormatOptions & { format: string } ): string; - declare function formatRelative( - value: any, + declare function formatRelativeTime( + value: number, // delta options?: $npm$ReactIntl$RelativeFormatOptions & { - format: string, - now: any + format: string } ): string; declare function formatNumber( @@ -223,12 +234,11 @@ declare module "react-intl" { children?: (formattedDate: string) => React$Node } > {} - declare class FormattedRelative extends React$Component< + declare class FormattedRelativeTime extends React$Component< $npm$ReactIntl$RelativeFormatOptions & { - value: $npm$ReactIntl$DateParseable, + value: number, // delta format?: string, - updateInterval?: number, - initialNow?: $npm$ReactIntl$DateParseable, + updateIntervalInSeconds?: number, children?: (formattedDate: string) => React$Node } > {} @@ -257,6 +267,12 @@ declare module "react-intl" { initialNow?: $npm$ReactIntl$DateParseable } > {} + declare class RawIntlProvider extends React$Component< + {| + children?: React$Node, + value?: IntlShape + |} + > {} declare type IntlShape = $npm$ReactIntl$IntlShape; declare type MessageDescriptor = $npm$ReactIntl$MessageDescriptor; } diff --git a/package.json b/package.json index 6adc775..e29f4bb 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,12 @@ "build:install": "yarn install", "build:webpack": "NODE_PATH=./src webpack --colors -p --bail", "build:quiet": "yarn run clean && yarn run build:webpack --quiet", - "build:dll": "node ./scripts/build-dll.js" + "build:dll": "node ./scripts/build-dll.js", + "build:serve": "http-server --proxy https://dev.account.ely.by ./dist" }, "dependencies": { + "@formatjs/intl-pluralrules": "^1.3.2", + "@formatjs/intl-relativetimeformat": "^4.4.1", "@hot-loader/react-dom": "^16.11.0", "classnames": "^2.2.6", "copy-to-clipboard": "^3.0.8", @@ -56,7 +59,7 @@ "react-dom": "^16.11.0", "react-helmet": "^5.0.0", "react-hot-loader": "^4.12.16", - "react-intl": "^2.7.2", + "react-intl": "^3.4.0", "react-motion": "^0.5.0", "react-redux": "^7.1.3", "react-router-dom": "^5.1.2", @@ -82,7 +85,7 @@ "@babel/plugin-proposal-function-sent": "^7.7.0", "@babel/plugin-proposal-json-strings": "^7.0.0", "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4", "@babel/plugin-proposal-numeric-separator": "^7.0.0", "@babel/plugin-proposal-optional-chaining": "^7.6.0", "@babel/plugin-proposal-pipeline-operator": "^7.5.0", @@ -96,7 +99,7 @@ "@babel/runtime-corejs3": "^7.7.2", "babel-eslint": "^10.0.3", "babel-loader": "^8.0.0", - "babel-plugin-react-intl": "^2.0.0", + "babel-plugin-react-intl": "^5.1.1", "core-js": "3.4.0", "csp-webpack-plugin": "^2.0.2", "css-loader": "^3.2.0", diff --git a/src/components/i18n/IntlProvider.js b/src/components/i18n/IntlProvider.js index 0ec1962..6225cb4 100644 --- a/src/components/i18n/IntlProvider.js +++ b/src/components/i18n/IntlProvider.js @@ -1,24 +1,32 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; +// @flow +import type { Node } from 'react'; +import type { IntlShape } from 'react-intl'; +import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { RawIntlProvider } from 'react-intl'; +import i18n from 'services/i18n'; -import { IntlProvider as OrigIntlProvider } from 'react-intl'; +type OwnProps = {| + children: Node +|}; -class IntlProvider extends Component { - static displayName = 'IntlProvider'; - static propTypes = { - locale: PropTypes.string, - messages: PropTypes.objectOf(PropTypes.string), - children: PropTypes.element - }; +type Props = { + ...OwnProps, + locale: string +}; - render() { - return ( - - ); - } +function IntlProvider({ children, locale }: Props) { + const [intl, setIntl] = useState(i18n.getIntl()); + + useEffect(() => { + (async () => { + setIntl(await i18n.changeLocale(locale)); + })(); + }, [locale]); + + return {children}; } - -import { connect } from 'react-redux'; - -export default connect(({i18n}) => i18n)(IntlProvider); +export default connect(({ i18n }) => i18n)( + IntlProvider +); diff --git a/src/components/i18n/actions.js b/src/components/i18n/actions.js index 4224f1c..97dc910 100644 --- a/src/components/i18n/actions.js +++ b/src/components/i18n/actions.js @@ -1,26 +1,22 @@ // @flow import i18n from 'services/i18n'; -import captcha from 'services/captcha'; export const SET_LOCALE = 'i18n:setLocale'; export function setLocale(desiredLocale: string) { - return async (dispatch: (action: Object) => any) => { - const { locale, messages } = await i18n.require(i18n.detectLanguage(desiredLocale)); - dispatch(_setLocale(locale, messages)); + return async (dispatch: (action: Object) => any): Promise => { + const locale = i18n.detectLanguage(desiredLocale); - // TODO: probably should be moved from here, because it is a side effect - captcha.setLang(locale); + dispatch(_setLocale(locale)); return locale; }; } -function _setLocale(locale: string, messages: { [string]: string }) { +function _setLocale(locale: string) { return { type: SET_LOCALE, payload: { locale, - messages, }, }; } diff --git a/src/components/i18n/reducer.js b/src/components/i18n/reducer.js index 19ff6d6..837d1fe 100644 --- a/src/components/i18n/reducer.js +++ b/src/components/i18n/reducer.js @@ -1,6 +1,18 @@ +// @flow +import i18n from 'services/i18n'; + import { SET_LOCALE } from './actions'; -export default function(state = {}, {type, payload}) { +type State = { locale: string }; + +const defaultState = { + locale: i18n.detectLanguage() +}; + +export default function( + state: State = defaultState, + { type, payload }: { type: string, payload: State } +): State { if (type === SET_LOCALE) { return payload; } diff --git a/src/components/languageSwitcher/LanguageSwitcher.js b/src/components/languageSwitcher/LanguageSwitcher.js index aa8aa4c..7daa1b5 100644 --- a/src/components/languageSwitcher/LanguageSwitcher.js +++ b/src/components/languageSwitcher/LanguageSwitcher.js @@ -1,6 +1,7 @@ // @flow +import type { IntlShape } from 'react-intl'; import React, { Component } from 'react'; -import { FormattedMessage as Message, intlShape } from 'react-intl'; +import { FormattedMessage as Message, injectIntl } from 'react-intl'; import classNames from 'classnames'; import { connect } from 'react-redux'; import { changeLang } from 'components/user/actions'; @@ -36,6 +37,7 @@ type OwnProps = {| type Props = { ...OwnProps, + intl: IntlShape, selectedLocale: string, changeLang: (lang: string) => void, }; @@ -44,10 +46,6 @@ class LanguageSwitcher extends Component { - static contextTypes = { - intl: intlShape, - }; - state = { filter: '', filteredLangs: this.props.langs, @@ -59,7 +57,7 @@ class LanguageSwitcher extends Component((state) => ({ - selectedLocale: state.i18n.locale, -}), { - changeLang, -})(LanguageSwitcher); +export default injectIntl( + connect((state) => ({ + selectedLocale: state.i18n.locale, + }), { + changeLang, + })(LanguageSwitcher) +); diff --git a/src/components/profile/Profile.js b/src/components/profile/Profile.js index a9d481a..5a41a44 100644 --- a/src/components/profile/Profile.js +++ b/src/components/profile/Profile.js @@ -1,10 +1,12 @@ // @flow import React, { Component } from 'react'; import { connect } from 'react-redux'; -import { FormattedMessage as Message, FormattedRelative as Relative } from 'react-intl'; +import { FormattedMessage as Message } from 'react-intl'; import { Link } from 'react-router-dom'; import Helmet from 'react-helmet'; import { ChangeLanguageLink } from 'components/languageSwitcher'; +import { RelativeTime } from 'components/ui'; + import ProfileField from './ProfileField'; import styles from './profile.scss'; import profileForm from './profileForm.scss'; @@ -85,7 +87,7 @@ class Profile extends Component { link="/profile/change-password" label={} value={) + at: (), }} />} /> diff --git a/src/components/ui/RelativeTime.js b/src/components/ui/RelativeTime.js new file mode 100644 index 0000000..c7f8c86 --- /dev/null +++ b/src/components/ui/RelativeTime.js @@ -0,0 +1,19 @@ +// @flow +import React from 'react'; +import { FormattedRelativeTime } from 'react-intl'; +import { selectUnit } from '@formatjs/intl-utils'; + +function RelativeTime({timestamp}: {timestamp: number}) { + const {unit, value}: {unit: any, value: number} = selectUnit(timestamp); + + return ( + + ); +} + +export default RelativeTime; diff --git a/src/components/ui/form/FormComponent.js b/src/components/ui/form/FormComponent.js index 93ae174..8f8e783 100644 --- a/src/components/ui/form/FormComponent.js +++ b/src/components/ui/form/FormComponent.js @@ -1,13 +1,10 @@ // @flow import type { MessageDescriptor } from 'react-intl'; +import type { Element } from 'react'; import { Component } from 'react'; -import { intlShape } from 'react-intl'; - -export default class FormComponent extends Component { - static contextTypes = { - intl: intlShape, - }; +import i18n from 'services/i18n'; +class FormComponent extends Component { /** * Formats message resolving intl translations * @@ -15,16 +12,16 @@ export default class FormComponent extends Component { * * @return {string} */ - formatMessage(message: string | MessageDescriptor): string { - if (message && message.id) { - if (this.context && this.context.intl) { - message = this.context.intl.formatMessage(message); - } else { - return ''; - } + formatMessage(message: string | MessageDescriptor | Element): string | Element { + if (typeof message === 'string') { + return message; } - return ((message: any): string); + if (message && message.id) { + return i18n.getIntl().formatMessage(message); + } + + return ((message: any): Element); } /** @@ -40,3 +37,5 @@ export default class FormComponent extends Component { onFormInvalid() { } } + +export default FormComponent; diff --git a/src/components/ui/index.js b/src/components/ui/index.js index 813e7b5..fc6a65b 100644 --- a/src/components/ui/index.js +++ b/src/components/ui/index.js @@ -37,3 +37,5 @@ export const SKIN_DARK: Skin = 'dark'; export const SKIN_LIGHT: Skin = 'light'; export const skins: Array = [SKIN_DARK, SKIN_LIGHT]; + +export {default as RelativeTime} from './RelativeTime'; diff --git a/src/components/user/actions.js b/src/components/user/actions.js index 2513bc3..416d7f7 100644 --- a/src/components/user/actions.js +++ b/src/components/user/actions.js @@ -40,13 +40,16 @@ export function setUser(payload: $Shape) { export const CHANGE_LANG = 'USER_CHANGE_LANG'; export function changeLang(lang: string) { return (dispatch: Dispatch, getState: () => State) => dispatch(setLocale(lang)) - .then((lang) => { + .then((lang: string) => { const { id, isGuest, lang: oldLang } = getState().user; + if (oldLang === lang) { return; } - !isGuest && changeLangEndpoint(((id: any): number), lang); // hack to tell Flow that it's defined + if (!isGuest && id) { + changeLangEndpoint(id, lang); + } dispatch({ type: CHANGE_LANG, diff --git a/src/index.js b/src/index.js index 99aa942..149ead6 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,7 @@ import loader from 'services/loader'; import logger from 'services/logger'; import font from 'services/font'; import history, { browserHistory } from 'services/history'; +import i18n from 'services/i18n'; import { loadScript, debounce } from 'functions'; import App from './App'; @@ -28,7 +29,8 @@ authFlow.setStore(store); Promise.all([ userFactory(store), - font.load(['Roboto', 'Roboto Condensed']) + font.load(['Roboto', 'Roboto Condensed']), + i18n.ensureIntl(), // ensure, that intl is polyfilled before any rendering ]).then(() => { ReactDOM.render( , diff --git a/src/services/errorsDict/errorsDict.js b/src/services/errorsDict/errorsDict.js index f12ae31..81a9dba 100644 --- a/src/services/errorsDict/errorsDict.js +++ b/src/services/errorsDict/errorsDict.js @@ -1,6 +1,7 @@ import React from 'react'; -import { FormattedMessage as Message, FormattedRelative as Relative } from 'react-intl'; +import { FormattedMessage as Message } from 'react-intl'; +import { RelativeTime } from 'components/ui'; import { Link } from 'react-router-dom'; import messages from './errorsDict.intl.json'; @@ -76,7 +77,7 @@ const errorsMap = { 'error.recently_sent_message': (props) => ( + time: }} /> ), diff --git a/src/services/i18n.js b/src/services/i18n.js deleted file mode 100644 index 71da502..0000000 --- a/src/services/i18n.js +++ /dev/null @@ -1,53 +0,0 @@ -// @flow -import locales from 'i18n/index.json'; - -import { addLocaleData } from 'react-intl'; - -const SUPPORTED_LANGUAGES = Object.keys(locales); -const DEFAULT_LANGUAGE = 'en'; - -const needPolyfill = !window.Intl; - -function getUserLanguages(userSelectedLang: string): Array { - return [userSelectedLang] - .concat(navigator.languages || []) - .concat(navigator.language || []); -} - -function detectLanguage( - userLanguages: Array, - availableLanguages: Array, - defaultLanguage: string, -): string { - return userLanguages - .map((lang) => lang.split('-').shift().toLowerCase()) - .find((lang) => availableLanguages.indexOf(lang) !== -1) || defaultLanguage; -} - -export default { - detectLanguage(lang: string): string { - return detectLanguage(getUserLanguages(lang), SUPPORTED_LANGUAGES, DEFAULT_LANGUAGE); - }, - - require(locale: string): Promise<{ - locale: string; - messages: { [string]: string }; - }> { - const promises: Array> = [ - import(/* webpackChunkName: "locale-[request]" */`react-intl/locale-data/${locale}.js`), - import(/* webpackChunkName: "locale-[request]" */`i18n/${locale}.json`), - ]; - - if (needPolyfill) { - promises.push(import(/* webpackChunkName: "intl-polyfill" */'intl')); - promises.push(import(/* webpackChunkName: "intl-polyfill-[request]" */`intl/locale-data/jsonp/${locale}.js`)); - } - - return Promise.all(promises) - .then(([localeData, {default: messages}]) => { - addLocaleData(localeData); - - return {locale, messages}; - }); - } -}; diff --git a/src/services/i18n/i18n.js b/src/services/i18n/i18n.js new file mode 100644 index 0000000..142c948 --- /dev/null +++ b/src/services/i18n/i18n.js @@ -0,0 +1,85 @@ +// @flow +import type {IntlShape} from 'react-intl'; +import {createIntl, createIntlCache} from 'react-intl'; +import captcha from 'services/captcha'; +import locales from 'i18n/index.json'; + +import intlPolyfill from './intlPolyfill'; + +const SUPPORTED_LANGUAGES = Object.keys(locales); +const DEFAULT_LANGUAGE = 'en'; + +function getBrowserPreferredLanguages(): string[] { + return [] + .concat(navigator.languages || []) + .concat(navigator.language || []); +} + +function detectLanguage( + userLanguages: string[], + availableLanguages: string[], + defaultLanguage: string, +): string { + return userLanguages + .map((lang) => lang.split('-').shift().toLowerCase()) + .find((lang) => availableLanguages.indexOf(lang) !== -1) || defaultLanguage; +} + +const cache = createIntlCache(); + +let intl: IntlShape; + +class I18N { + detectLanguage(lang: string): string { + return detectLanguage( + [lang].concat(getBrowserPreferredLanguages()).filter((item) => !!item), + SUPPORTED_LANGUAGES, + DEFAULT_LANGUAGE + ); + } + + getIntl(): IntlShape { + if (!intl) { + intl = createIntl({ + locale: 'en', + messages: {} + }, cache); + } + + return intl; + } + + async changeLocale(locale: string = DEFAULT_LANGUAGE): Promise { + const { messages } = await this.require(locale); + + captcha.setLang(locale); + + intl = createIntl({ + locale, + messages + }, cache); + + return intl; + } + + async ensureIntl() { + await intlPolyfill('en'); + } + + async require(locale: string): Promise<{ + locale: string; + messages: { [string]: string }; + }> { + const [{default: messages}] = await Promise.all([ + import(/* webpackChunkName: "locale-[request]" */`i18n/${locale}.json`), + intlPolyfill(locale) + ]); + + return { + locale, + messages + }; + } +} + +export default new I18N(); diff --git a/src/services/i18n/index.js b/src/services/i18n/index.js new file mode 100644 index 0000000..7c364f9 --- /dev/null +++ b/src/services/i18n/index.js @@ -0,0 +1,2 @@ +// @flow +export { default } from './i18n'; diff --git a/src/services/i18n/intlPolyfill.js b/src/services/i18n/intlPolyfill.js new file mode 100644 index 0000000..8ea156f --- /dev/null +++ b/src/services/i18n/intlPolyfill.js @@ -0,0 +1,100 @@ + +// @flow +import logger from 'services/logger'; + +const needs = { + intl: !window.Intl, + plural: !window?.Intl?.PluralRules, + relative: !window?.Intl?.RelativeTimeFormat +}; + +/** + * All modern browsers currently do support all required Intl APIs, + * for the outdated browsers we will polyfill this api on demand + */ + +async function polyfill(locale: string): Promise { + const promises = []; + + if (!needs.intl + && Intl.DateTimeFormat.supportedLocalesOf([locale]).length === 0 + ) { + // fallback to polyfill in case, when browser does not support locale we need + needs.intl = true; + needs.plural = true; + needs.relative = true; + } + + if (needs.intl) { + promises.push(polyfillIntl(locale)); + } else { + if (needs.plural) { + promises.push(polyfillPlural(locale)); + } + + if (needs.relative) { + promises.push(polyfillRelative(locale)); + } + } + + try { + await Promise.all(promises); + } catch (error) { + logger.warn('Error loading intl polyfills', { + error + }); + } +} + +async function polyfillIntl(locale: string): Promise { + // do not rely on tests provided by polyfill implementation + // forcibly apply polyfill, because if this function was called + // this means that browser does not support some of locales + const {default: Intl} = await import( + /* webpackChunkName: "intl" */ + 'intl' + ); + + window.Intl = Intl; + + // MUST be loaded in series with the main polyfill + await Promise.all([ + import( + // WARNING: .js extension is required for proper function of ContextReplacementPlugin + /* webpackChunkName: "intl-[request]" */ + `intl/locale-data/jsonp/${locale}.js` + ), + polyfillPlural(locale), + polyfillRelative(locale), + ]); +} + +async function polyfillPlural(locale: string): Promise { + await import( + /* webpackChunkName: "intl-pluralrules" */ + '@formatjs/intl-pluralrules/polyfill' + ); + + // MUST be loaded in series with the main polyfill + await import( + // WARNING: .js extension is required for proper function of ContextReplacementPlugin + /* webpackChunkName: "intl-pluralrules-[request]" */ + `@formatjs/intl-pluralrules/dist/locale-data/${locale}.js` + ); +} + +async function polyfillRelative(locale: string): Promise { + await import( + /* webpackChunkName: "intl-relativetimeformat" */ + '@formatjs/intl-relativetimeformat/polyfill' + ); + + // MUST be loaded in series with the main polyfill + await import( + // WARNING: .js extension is required for proper function of ContextReplacementPlugin + /* webpackChunkName: "intl-relativetimeformat-[request]" */ + `@formatjs/intl-relativetimeformat/dist/locale-data/${locale}.js` + ); +} + +export default polyfill; diff --git a/webpack.config.js b/webpack.config.js index 92835b5..3a15d32 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -57,7 +57,7 @@ const webpackConfig = { modules: [rootPath, 'node_modules'], extensions: ['.js', '.jsx', '.json'], alias: { - 'react-dom': '@hot-loader/react-dom' + 'react-dom': isProduction ? 'react-dom' : '@hot-loader/react-dom' } }, @@ -137,10 +137,10 @@ const webpackConfig = { } ), // restrict webpack import context, to create chunks only for supported locales - // @see services/i18n.js + // @see services/i18n/intlPolyfill.js new webpack.ContextReplacementPlugin( /locale-data/, - new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js`) + new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js$`) ), // @see components/i18n/localeFlags.js new webpack.ContextReplacementPlugin( @@ -264,7 +264,10 @@ if (isProduction) { splitChunks: { cacheGroups: { vendor: { - test: (m) => String(m.context).includes('node_modules') && !String(m.context).includes('flag-icon-css'), + test: (m) => String(m.context).includes('node_modules') + // icons and intl with relateed polyfills are allowed + // to be splitted to other chunks + && !/\/(flag-icon-css|intl|@formatjs)\//.test(String(m.context)), name: 'vendors', chunks: 'all', }, diff --git a/yarn.lock b/yarn.lock index 0d20307..1d879a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,7 +32,7 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@^7.7.2": +"@babel/core@^7.6.2", "@babel/core@^7.7.2": version "7.7.2" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91" integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ== @@ -374,16 +374,16 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.2.3.tgz#32f5df65744b70888d17872ec106b02434ba1489" integrity sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA== +"@babel/parser@^7.1.0", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2": + version "7.7.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043" + integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A== + "@babel/parser@^7.4.4", "@babel/parser@^7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872" integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew== -"@babel/parser@^7.7.0", "@babel/parser@^7.7.2": - version "7.7.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043" - integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A== - "@babel/plugin-proposal-async-generator-functions@^7.7.0": version "7.7.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971" @@ -475,7 +475,7 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-logical-assignment-operators" "^7.2.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.4.4.tgz#41c360d59481d88e0ce3a3f837df10121a769b39" integrity sha512-Amph7Epui1Dh/xxUxS2+K22/MUi6+6JVTvy3P58tja3B6yKTSjwwx0/d83rF7551D6PVSSoplQb8GCwqec7HRw== @@ -1177,6 +1177,15 @@ lodash "^4.17.10" to-fast-properties "^2.0.0" +"@babel/types@^7.3.0", "@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7" + integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@babel/types@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0" @@ -1186,15 +1195,6 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" -"@babel/types@^7.7.0", "@babel/types@^7.7.1", "@babel/types@^7.7.2": - version "7.7.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7" - integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - "@cypress/listr-verbose-renderer@0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" @@ -1213,6 +1213,39 @@ debug "^3.1.0" lodash.once "^4.1.1" +"@formatjs/intl-pluralrules@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-1.3.2.tgz#10b4d09526739d2146ef5e05c8540db3343862c7" + integrity sha512-ZPHR7c4dEQ+7Y2pav2p55xfB8fbNMdr8iUqiH+T1FcXWDBE3ISlp/qU0fii97P4Co4dRXA6LCpfcdVcfQzzSmw== + dependencies: + "@formatjs/intl-utils" "^1.4.0" + +"@formatjs/intl-relativetimeformat@^4.2.1": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-4.4.0.tgz#8de1d25457cd34531c87f3fa4c7d381606f010ed" + integrity sha512-8lXOWWvoIPJR8Ak1uywE/gajBmHppfIg6a1o/fyd3t6NV7Qe+PVj7SJ5SgyRUcK3xQVA6AXpDJ7LCyjo5iOD8g== + dependencies: + "@formatjs/intl-utils" "^1.4.0" + +"@formatjs/intl-relativetimeformat@^4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-4.4.1.tgz#2277daba93462781d126abfe071f3aa66c247a19" + integrity sha512-VOc/uvZy1qmw7ssBMumNdinDg3Hvzbvmiqaaz8SMr+znYXd1D6Ogd2JsaskSrr3/bJOscEN5W4wNHFl1McfffQ== + dependencies: + "@formatjs/intl-utils" "^1.4.0" + +"@formatjs/intl-unified-numberformat@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@formatjs/intl-unified-numberformat/-/intl-unified-numberformat-2.1.0.tgz#0b8ef3bc3ebbafb40a65f09606a3fc414f1a392a" + integrity sha512-0zL5DKRe4KiaupyiwT8ckTmE1aPlb2fsR0deMGN4QVlkdCxsCDMrLykrLyrhBa9fthTDaGR4Qh+bALk/sa4Vcg== + dependencies: + "@formatjs/intl-utils" "^1.4.0" + +"@formatjs/intl-utils@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@formatjs/intl-utils/-/intl-utils-1.4.0.tgz#b59fdf78bbae9f99c500a298bf73b1945f5991f1" + integrity sha512-z5HyJumGzORM+5SpvkAlp/hu0AHDeZcUNKSmj9NjS7kWxOGZMuAdS3X1K5XiE0j5I8r8s8SIaz0IQOdMA1WFeA== + "@hot-loader/react-dom@^16.11.0": version "16.11.0" resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.11.0.tgz#c0b483923b289db5431516f56ee2a69448ebf9bd" @@ -1268,6 +1301,39 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== +"@types/babel__core@^7.1.2": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30" + integrity sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.0.tgz#f1ec1c104d1bb463556ecb724018ab788d0c172a" + integrity sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" + integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.7.tgz#2496e9ff56196cc1429c72034e07eab6121b6f3f" + integrity sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw== + dependencies: + "@babel/types" "^7.3.0" + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -1282,6 +1348,19 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/hoist-non-react-statics@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + +"@types/invariant@^2.2.30": + version "2.2.30" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.30.tgz#20efa342807606ada5483731a8137cb1561e5fe9" + integrity sha512-98fB+yo7imSD2F7PF7GIpELNgtLNgo5wjivu0W5V4jx+KVVJxo6p/qN4zdzSTBWy4/sN3pPyXwnhRSD28QX+ag== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -1302,7 +1381,7 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== -"@types/react@^15.0.0 || ^16.0.0": +"@types/react@*", "@types/react@^15.0.0 || ^16.0.0": version "16.9.11" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120" integrity sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ== @@ -1310,6 +1389,11 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/schema-utils@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/schema-utils/-/schema-utils-1.0.0.tgz#295d36f01e2cb8bc3207ca1d9a68e210db6b40cb" + integrity sha512-YesPanU1+WCigC/Aj1Mga8UCOjHIfMNHZ3zzDsUY7lI8GlKnh/Kv2QwJOQ+jNQ36Ru7IfzSedlG14hppYaN13A== + "@types/sizzle@2.3.2": version "2.3.2" resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" @@ -1982,22 +2066,18 @@ babel-plugin-dynamic-import-node@^2.3.0: dependencies: object.assign "^4.1.0" -babel-plugin-react-intl@^2.0.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-2.4.0.tgz#292fca8030603a9e0476973290836aa0c7da17e2" - integrity sha512-r67nOQdpKxPtDFiJHquTt9dBG0xOlBk1u3rForULNrDXvTzg5RRHbB7RLqqMWOvqfP2znTo0C+e/PLnPKt+JXA== +babel-plugin-react-intl@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-5.1.1.tgz#3c3d8af13aeb7b50c6470fc3d7abe9bdbae9f6da" + integrity sha512-kkghFOjjssYRiVPxwV/6q4WFhpkYw2LnpQAuvqHHDvPbOH2bcAz2U+GXy+W7pzSwH2FPnqegCbzJ4nPogVRGwg== dependencies: - babel-runtime "^6.2.0" - intl-messageformat-parser "^1.2.0" - mkdirp "^0.5.1" - -babel-runtime@^6.2.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" + "@babel/core" "^7.6.2" + "@babel/helper-plugin-utils" "^7.0.0" + "@types/babel__core" "^7.1.2" + "@types/schema-utils" "^1.0.0" + fs-extra "^8.0.1" + intl-messageformat-parser "^3.2.2" + schema-utils "^2.2.0" backo2@1.0.2: version "1.0.2" @@ -3030,11 +3110,6 @@ core-js@^1.0.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= -core-js@^2.4.0: - version "2.6.9" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" - integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== - core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -4781,6 +4856,15 @@ fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^8.0.1: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.6" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" @@ -5086,6 +5170,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== +graceful-fs@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + greedy-interval-packer@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/greedy-interval-packer/-/greedy-interval-packer-1.2.0.tgz#d6da11f3661bb797812da78a1ea510678a2a8739" @@ -5685,29 +5774,28 @@ interpret@1.2.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== -intl-format-cache@^2.0.5: - version "2.2.9" - resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-2.2.9.tgz#fb560de20c549cda20b569cf1ffb6dc62b5b93b4" - integrity sha512-Zv/u8wRpekckv0cLkwpVdABYST4hZNTDaX7reFetrYTJwxExR2VyTqQm+l0WmL0Qo8Mjb9Tf33qnfj0T7pjxdQ== +intl-format-cache@^4.2.3, intl-format-cache@^4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-4.2.5.tgz#6319f5707cdc766ab5c196990a6e55b0df9cc70f" + integrity sha512-xvvog/4HTVhJIg5dexcs6Ji/ROlolCgtz3std23bLEmucoGPrUVrYQPTcBWR314NM9khm4JSrdOamv9SEtvCUg== -intl-messageformat-parser@1.4.0, intl-messageformat-parser@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz#b43d45a97468cadbe44331d74bb1e8dea44fc075" - integrity sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU= +intl-locales-supported@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/intl-locales-supported/-/intl-locales-supported-1.8.0.tgz#cfec56f5ac8cbb828bd5ce3155c4392555cd5c5c" + integrity sha512-y1K5NaNM/WjwZcRy4TtRZ4kR8TCXfoPlX2MFbFGWqqYBD0jPG8liX/cU8aBzk2j5+bu1W6ztlLtOfCPAEwQc3A== -intl-messageformat@^2.0.0, intl-messageformat@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-2.2.0.tgz#345bcd46de630b7683330c2e52177ff5eab484fc" - integrity sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw= +intl-messageformat-parser@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-3.2.2.tgz#28cacc80a53823a28b5ecaf16b3b35d0a1d5f9d2" + integrity sha512-ax9639ST77YimAddTH/0Q9qhXuYS8ZVsoqOZinqnS90MbXaNuIq+KIdifaIndwI+lMEv3o+qNaGycXYvlh17rw== + +intl-messageformat@^7.3.3: + version "7.5.0" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-7.5.0.tgz#53582b6e911d4f41434e9d897b4789d2a2b2ff8e" + integrity sha512-s08OFUbRVUPTiXS8OOP06OhfehM1K4ughymhOazY4OhQMO+RiY4bnmsqRgYe7XorETg7mZnwJX1M34sJrzKoOA== dependencies: - intl-messageformat-parser "1.4.0" - -intl-relativeformat@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/intl-relativeformat/-/intl-relativeformat-2.2.0.tgz#6aca95d019ec8d30b6c5653b6629f9983ea5b6c5" - integrity sha512-4bV/7kSKaPEmu6ArxXf9xjv1ny74Zkwuey8Pm01NH4zggPP7JHwg2STk8Y3JdspCKRDriwIyLRfEXnj2ZLr4Bw== - dependencies: - intl-messageformat "^2.0.0" + intl-format-cache "^4.2.5" + intl-messageformat-parser "^3.2.2" intl@^1.2.5: version "1.2.5" @@ -8787,16 +8875,22 @@ react-hot-loader@^4.12.16: shallowequal "^1.1.0" source-map "^0.7.3" -react-intl@^2.7.2: - version "2.9.0" - resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-2.9.0.tgz#c97c5d17d4718f1575fdbd5a769f96018a3b1843" - integrity sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA== +react-intl@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-3.4.0.tgz#25986ac75b3c0073c0a7bce31ab2cb1b8bbf421c" + integrity sha512-pW+z0ngVtPzICQeBrvoxk/YOotjFjVMvqxf/q0hjfM4CLvzIWJW/7MQcOz8ujD0Agf146mYOUv0//a9JM4H6Tg== dependencies: + "@formatjs/intl-relativetimeformat" "^4.2.1" + "@formatjs/intl-unified-numberformat" "^2.1.0" + "@types/hoist-non-react-statics" "^3.3.1" + "@types/invariant" "^2.2.30" hoist-non-react-statics "^3.3.0" - intl-format-cache "^2.0.5" - intl-messageformat "^2.1.0" - intl-relativeformat "^2.1.0" + intl-format-cache "^4.2.3" + intl-locales-supported "^1.6.0" + intl-messageformat "^7.3.3" + intl-messageformat-parser "^3.2.2" invariant "^2.1.1" + shallow-equal "^1.1.0" react-is@^16.10.2, react-is@^16.9.0: version "16.11.0" @@ -9090,11 +9184,6 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.12.0: version "0.12.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" @@ -9511,7 +9600,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.4.1: +schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.2.0, schema-utils@^2.4.1: version "2.5.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.5.0.tgz#8f254f618d402cc80257486213c8970edfd7c22f" integrity sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ== @@ -9656,6 +9745,11 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +shallow-equal@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.0.tgz#fd828d2029ff4e19569db7e19e535e94e2d1f5cc" + integrity sha512-Z21pVxR4cXsfwpMKMhCEIO1PCi5sp7KEp+CmOpBQ+E8GpHwKOw2sEzk7sgblM3d/j4z4gakoWEoPcjK0VJQogA== + shallowequal@^1.0.1, shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"