mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-30 02:32:58 +05:30
Upgrade to intl@^3.0.0
This commit is contained in:
parent
705bc2f9d6
commit
2708650f17
@ -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
|
||||
|
@ -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',
|
||||
{
|
||||
|
38
flow-typed/npm/react-intl_v2.x.x.js
vendored
38
flow-typed/npm/react-intl_v2.x.x.js
vendored
@ -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<React$ElementConfig<Component>, 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;
|
||||
}
|
||||
|
11
package.json
11
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",
|
||||
|
@ -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 (
|
||||
<OrigIntlProvider locale="en" {...this.props} />
|
||||
);
|
||||
}
|
||||
function IntlProvider({ children, locale }: Props) {
|
||||
const [intl, setIntl] = useState<IntlShape>(i18n.getIntl());
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
setIntl(await i18n.changeLocale(locale));
|
||||
})();
|
||||
}, [locale]);
|
||||
|
||||
return <RawIntlProvider value={intl}>{children}</RawIntlProvider>;
|
||||
}
|
||||
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
export default connect(({i18n}) => i18n)(IntlProvider);
|
||||
export default connect<Props, OwnProps, _, _, _, _>(({ i18n }) => i18n)(
|
||||
IntlProvider
|
||||
);
|
||||
|
@ -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<string> => {
|
||||
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,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<Props, {
|
||||
filter: string,
|
||||
filteredLangs: LocalesMap,
|
||||
}> {
|
||||
static contextTypes = {
|
||||
intl: intlShape,
|
||||
};
|
||||
|
||||
state = {
|
||||
filter: '',
|
||||
filteredLangs: this.props.langs,
|
||||
@ -59,7 +57,7 @@ class LanguageSwitcher extends Component<Props, {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { selectedLocale, onClose } = this.props;
|
||||
const { selectedLocale, onClose, intl } = this.props;
|
||||
const { filteredLangs } = this.state;
|
||||
|
||||
return (
|
||||
@ -79,7 +77,7 @@ class LanguageSwitcher extends Component<Props, {
|
||||
formStyles.lightTextField,
|
||||
formStyles.greenTextField,
|
||||
)}
|
||||
placeholder={this.context.intl.formatMessage(messages.startTyping)}
|
||||
placeholder={intl.formatMessage(messages.startTyping)}
|
||||
onChange={this.onFilterUpdate}
|
||||
onKeyPress={this.onFilterKeyPress()}
|
||||
autoFocus
|
||||
@ -161,8 +159,10 @@ class LanguageSwitcher extends Component<Props, {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect<Props, OwnProps, _, _, _, _>((state) => ({
|
||||
selectedLocale: state.i18n.locale,
|
||||
}), {
|
||||
changeLang,
|
||||
})(LanguageSwitcher);
|
||||
export default injectIntl(
|
||||
connect<Props, OwnProps, _, _, _, _>((state) => ({
|
||||
selectedLocale: state.i18n.locale,
|
||||
}), {
|
||||
changeLang,
|
||||
})(LanguageSwitcher)
|
||||
);
|
||||
|
@ -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<Props> {
|
||||
link="/profile/change-password"
|
||||
label={<Message {...messages.password} />}
|
||||
value={<Message {...messages.changedAt} values={{
|
||||
at: (<Relative value={user.passwordChangedAt * 1000} updateInterval={1000} />)
|
||||
at: (<RelativeTime timestamp={user.passwordChangedAt * 1000} />),
|
||||
}} />}
|
||||
/>
|
||||
|
||||
|
19
src/components/ui/RelativeTime.js
Normal file
19
src/components/ui/RelativeTime.js
Normal file
@ -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 (
|
||||
<FormattedRelativeTime
|
||||
value={value}
|
||||
unit={unit}
|
||||
numeric="auto"
|
||||
updateIntervalInSeconds={['seconds', 'minute', 'hour'].includes(unit) ? 1 : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default RelativeTime;
|
@ -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<P, S = void> extends Component<P, S> {
|
||||
static contextTypes = {
|
||||
intl: intlShape,
|
||||
};
|
||||
import i18n from 'services/i18n';
|
||||
|
||||
class FormComponent<P, S = void> extends Component<P, S> {
|
||||
/**
|
||||
* Formats message resolving intl translations
|
||||
*
|
||||
@ -15,16 +12,16 @@ export default class FormComponent<P, S = void> extends Component<P, S> {
|
||||
*
|
||||
* @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<any>): string | Element<any> {
|
||||
if (typeof message === 'string') {
|
||||
return message;
|
||||
}
|
||||
|
||||
return ((message: any): string);
|
||||
if (message && message.id) {
|
||||
return i18n.getIntl().formatMessage(message);
|
||||
}
|
||||
|
||||
return ((message: any): Element<any>);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -40,3 +37,5 @@ export default class FormComponent<P, S = void> extends Component<P, S> {
|
||||
onFormInvalid() {
|
||||
}
|
||||
}
|
||||
|
||||
export default FormComponent;
|
||||
|
@ -37,3 +37,5 @@ export const SKIN_DARK: Skin = 'dark';
|
||||
export const SKIN_LIGHT: Skin = 'light';
|
||||
|
||||
export const skins: Array<Skin> = [SKIN_DARK, SKIN_LIGHT];
|
||||
|
||||
export {default as RelativeTime} from './RelativeTime';
|
||||
|
@ -40,13 +40,16 @@ export function setUser(payload: $Shape<User>) {
|
||||
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,
|
||||
|
@ -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(
|
||||
<App store={store} browserHistory={browserHistory} />,
|
||||
|
@ -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) => (
|
||||
<Message {...messages.emailFrequency} values={{
|
||||
// for msLeft @see AuthError.jsx
|
||||
time: <Relative value={props.msLeft} updateInterval={1000} />
|
||||
time: <RelativeTime value={props.msLeft} />
|
||||
}} />
|
||||
),
|
||||
|
||||
|
@ -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<string> {
|
||||
return [userSelectedLang]
|
||||
.concat(navigator.languages || [])
|
||||
.concat(navigator.language || []);
|
||||
}
|
||||
|
||||
function detectLanguage(
|
||||
userLanguages: Array<string>,
|
||||
availableLanguages: Array<string>,
|
||||
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<Promise<any>> = [
|
||||
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};
|
||||
});
|
||||
}
|
||||
};
|
85
src/services/i18n/i18n.js
Normal file
85
src/services/i18n/i18n.js
Normal file
@ -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<IntlShape> {
|
||||
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();
|
2
src/services/i18n/index.js
Normal file
2
src/services/i18n/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
// @flow
|
||||
export { default } from './i18n';
|
100
src/services/i18n/intlPolyfill.js
Normal file
100
src/services/i18n/intlPolyfill.js
Normal file
@ -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<void> {
|
||||
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<void> {
|
||||
// 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<void> {
|
||||
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<void> {
|
||||
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;
|
@ -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',
|
||||
},
|
||||
|
234
yarn.lock
234
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"
|
||||
|
Loading…
Reference in New Issue
Block a user