react-intl 3.9.3 → 3.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -1
- package/dist/components/createFormattedComponent.d.ts +2 -1
- package/dist/components/createFormattedComponent.js +7 -2
- package/dist/components/html-message.js +1 -1
- package/dist/components/injectIntl.d.ts +1 -1
- package/dist/components/message.js +13 -4
- package/dist/components/plural.d.ts +1 -1
- package/dist/components/provider.js +14 -9
- package/dist/components/relative.js +3 -10
- package/dist/formatters/dateTime.js +2 -2
- package/dist/formatters/displayName.d.ts +2 -0
- package/dist/formatters/displayName.js +25 -0
- package/dist/formatters/message.d.ts +1 -0
- package/dist/formatters/message.js +19 -18
- package/dist/index.d.ts +7 -3
- package/dist/index.js +5 -2
- package/dist/react-intl.api.md +22 -5
- package/dist/react-intl.d.ts +64 -15
- package/dist/react-intl.js +5821 -5655
- package/dist/react-intl.js.map +1 -1
- package/dist/react-intl.min.js +1 -1
- package/dist/react-intl.min.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +5 -7
- package/lib/components/createFormattedComponent.d.ts +2 -1
- package/lib/components/createFormattedComponent.js +7 -2
- package/lib/components/html-message.js +1 -1
- package/lib/components/injectIntl.d.ts +1 -1
- package/lib/components/message.js +5 -3
- package/lib/components/plural.d.ts +1 -1
- package/lib/components/provider.js +14 -9
- package/lib/components/relative.js +3 -10
- package/lib/formatters/dateTime.js +2 -2
- package/lib/formatters/displayName.d.ts +2 -0
- package/lib/formatters/displayName.js +22 -0
- package/lib/formatters/message.d.ts +1 -0
- package/lib/formatters/message.js +12 -18
- package/lib/index.d.ts +7 -3
- package/lib/index.js +4 -1
- package/lib/react-intl.d.ts +20 -7
- package/lib/tsdoc-metadata.json +1 -1
- package/lib/types.d.ts +6 -1
- package/lib/utils.d.ts +1 -1
- package/lib/utils.js +4 -6
- package/package.json +38 -39
- package/src/components/createFormattedComponent.tsx +5 -0
- package/src/components/provider.tsx +26 -11
- package/src/components/relative.tsx +6 -15
- package/src/formatters/displayName.ts +35 -0
- package/src/formatters/message.ts +13 -18
- package/src/index.ts +7 -1
- package/src/types.ts +16 -5
- package/src/utils.ts +5 -7
package/lib/utils.js
CHANGED
|
@@ -11,12 +11,7 @@ file in the root directory of React's source tree.
|
|
|
11
11
|
import * as React from 'react';
|
|
12
12
|
import IntlMessageFormat from 'intl-messageformat';
|
|
13
13
|
import memoizeIntlConstructor from 'intl-format-cache';
|
|
14
|
-
|
|
15
|
-
// this is to interop with TypeScript since `invariant`
|
|
16
|
-
// does not export a default
|
|
17
|
-
// https://github.com/rollup/rollup/issues/1267
|
|
18
|
-
import * as invariant_ from 'invariant';
|
|
19
|
-
const invariant = invariant_.default || invariant_;
|
|
14
|
+
import { invariant } from '@formatjs/intl-utils';
|
|
20
15
|
const ESCAPED_CHARS = {
|
|
21
16
|
38: '&',
|
|
22
17
|
62: '>',
|
|
@@ -69,6 +64,7 @@ export function createIntlCache() {
|
|
|
69
64
|
relativeTime: {},
|
|
70
65
|
pluralRules: {},
|
|
71
66
|
list: {},
|
|
67
|
+
displayNames: {},
|
|
72
68
|
};
|
|
73
69
|
}
|
|
74
70
|
/**
|
|
@@ -78,6 +74,7 @@ export function createIntlCache() {
|
|
|
78
74
|
export function createFormatters(cache = createIntlCache()) {
|
|
79
75
|
const RelativeTimeFormat = Intl.RelativeTimeFormat;
|
|
80
76
|
const ListFormat = Intl.ListFormat;
|
|
77
|
+
const DisplayNames = Intl.DisplayNames;
|
|
81
78
|
return {
|
|
82
79
|
getDateTimeFormat: memoizeIntlConstructor(Intl.DateTimeFormat, cache.dateTime),
|
|
83
80
|
getNumberFormat: memoizeIntlConstructor(Intl.NumberFormat, cache.number),
|
|
@@ -85,6 +82,7 @@ export function createFormatters(cache = createIntlCache()) {
|
|
|
85
82
|
getRelativeTimeFormat: memoizeIntlConstructor(RelativeTimeFormat, cache.relativeTime),
|
|
86
83
|
getPluralRules: memoizeIntlConstructor(Intl.PluralRules, cache.pluralRules),
|
|
87
84
|
getListFormat: memoizeIntlConstructor(ListFormat, cache.list),
|
|
85
|
+
getDisplayNames: memoizeIntlConstructor(DisplayNames, cache.displayNames),
|
|
88
86
|
};
|
|
89
87
|
}
|
|
90
88
|
export function getNamedFormat(formats, type, name, onError) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-intl",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.1",
|
|
4
4
|
"description": "Internationalize React apps. This library provides React components and an API to format dates, numbers, and strings, including pluralization and handling translations.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"intl",
|
|
@@ -131,50 +131,49 @@
|
|
|
131
131
|
"types": "./lib/react-intl.d.ts",
|
|
132
132
|
"sideEffects": false,
|
|
133
133
|
"dependencies": {
|
|
134
|
-
"@formatjs/intl-
|
|
135
|
-
"@formatjs/intl-
|
|
136
|
-
"@formatjs/intl-
|
|
137
|
-
"@formatjs/
|
|
134
|
+
"@formatjs/intl-displaynames": "^1.2.0",
|
|
135
|
+
"@formatjs/intl-listformat": "^1.4.1",
|
|
136
|
+
"@formatjs/intl-relativetimeformat": "^4.5.9",
|
|
137
|
+
"@formatjs/intl-unified-numberformat": "^3.2.0",
|
|
138
|
+
"@formatjs/intl-utils": "^2.2.0",
|
|
138
139
|
"@types/hoist-non-react-statics": "^3.3.1",
|
|
139
|
-
"@types/invariant": "^2.2.
|
|
140
|
-
"hoist-non-react-statics": "^3.3.
|
|
141
|
-
"intl-format-cache": "4.2.
|
|
142
|
-
"intl-
|
|
143
|
-
"intl-messageformat": "
|
|
144
|
-
"intl-messageformat-parser": "3.5.1",
|
|
145
|
-
"invariant": "^2.1.1",
|
|
140
|
+
"@types/invariant": "^2.2.31",
|
|
141
|
+
"hoist-non-react-statics": "^3.3.2",
|
|
142
|
+
"intl-format-cache": "^4.2.21",
|
|
143
|
+
"intl-messageformat": "^7.8.4",
|
|
144
|
+
"intl-messageformat-parser": "^3.6.4",
|
|
146
145
|
"shallow-equal": "^1.2.1"
|
|
147
146
|
},
|
|
148
147
|
"peerDependencies": {
|
|
149
148
|
"react": "^16.3.0"
|
|
150
149
|
},
|
|
151
150
|
"devDependencies": {
|
|
152
|
-
"@babel/core": "^7.
|
|
153
|
-
"@babel/node": "^7.
|
|
154
|
-
"@babel/plugin-proposal-class-properties": "^7.
|
|
155
|
-
"@babel/plugin-transform-modules-commonjs": "^7.
|
|
156
|
-
"@babel/preset-env": "^7.
|
|
157
|
-
"@babel/preset-react": "^7.
|
|
158
|
-
"@formatjs/intl-pluralrules": "^1.
|
|
159
|
-
"@microsoft/api-documenter": "^7.7.
|
|
160
|
-
"@microsoft/api-extractor": "^7.7.
|
|
151
|
+
"@babel/core": "^7.8.4",
|
|
152
|
+
"@babel/node": "^7.8.4",
|
|
153
|
+
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
|
154
|
+
"@babel/plugin-transform-modules-commonjs": "^7.8.3",
|
|
155
|
+
"@babel/preset-env": "^7.8.4",
|
|
156
|
+
"@babel/preset-react": "^7.8.3",
|
|
157
|
+
"@formatjs/intl-pluralrules": "^1.5.2",
|
|
158
|
+
"@microsoft/api-documenter": "^7.7.12",
|
|
159
|
+
"@microsoft/api-extractor": "^7.7.8",
|
|
161
160
|
"@types/benchmark": "^1.0.31",
|
|
162
161
|
"@types/enzyme": "^3.10.4",
|
|
163
|
-
"@types/jest": "^24.
|
|
162
|
+
"@types/jest": "^24.9.1",
|
|
164
163
|
"@types/prop-types": "^15.7.3",
|
|
165
|
-
"@types/react": "^16.9.
|
|
166
|
-
"@types/react-dom": "^16.9.
|
|
167
|
-
"@typescript-eslint/eslint-plugin": "^2.
|
|
168
|
-
"@typescript-eslint/parser": "^2.
|
|
164
|
+
"@types/react": "^16.9.19",
|
|
165
|
+
"@types/react-dom": "^16.9.5",
|
|
166
|
+
"@typescript-eslint/eslint-plugin": "^2.19.0",
|
|
167
|
+
"@typescript-eslint/parser": "^2.19.0",
|
|
169
168
|
"babel-jest": "^24.9.0",
|
|
170
169
|
"benchmark": "^2.1.0",
|
|
171
|
-
"core-js": "^3.4
|
|
170
|
+
"core-js": "^3.6.4",
|
|
172
171
|
"cross-env": "^6.0.3",
|
|
173
|
-
"enzyme": "^3.
|
|
174
|
-
"enzyme-adapter-react-16": "^1.15.
|
|
175
|
-
"enzyme-to-json": "^3.4.
|
|
176
|
-
"eslint": "^6.
|
|
177
|
-
"eslint-plugin-react": "^7.
|
|
172
|
+
"enzyme": "^3.11.0",
|
|
173
|
+
"enzyme-adapter-react-16": "^1.15.2",
|
|
174
|
+
"enzyme-to-json": "^3.4.4",
|
|
175
|
+
"eslint": "^6.8.0",
|
|
176
|
+
"eslint-plugin-react": "^7.18.3",
|
|
178
177
|
"fs-extra": "^8.1.0",
|
|
179
178
|
"full-icu": "^1.3.0",
|
|
180
179
|
"glob": "^7.1.6",
|
|
@@ -186,19 +185,19 @@
|
|
|
186
185
|
"prettier": "^1.19.1",
|
|
187
186
|
"react": "^16.12.0",
|
|
188
187
|
"react-dom": "^16.12.0",
|
|
189
|
-
"rimraf": "^3.0.
|
|
190
|
-
"rollup": "^1.
|
|
188
|
+
"rimraf": "^3.0.1",
|
|
189
|
+
"rollup": "^1.31.0",
|
|
191
190
|
"rollup-plugin-babel": "^4.3.3",
|
|
192
191
|
"rollup-plugin-commonjs": "^10.1.0",
|
|
193
192
|
"rollup-plugin-node-resolve": "^5.2.0",
|
|
194
193
|
"rollup-plugin-replace": "^2.0.0",
|
|
195
194
|
"rollup-plugin-typescript2": "^0.25.3",
|
|
196
|
-
"rollup-plugin-uglify": "^6.0.
|
|
197
|
-
"standard-version": "^7.0
|
|
198
|
-
"ts-jest": "^24.
|
|
199
|
-
"ts-node": "^8.
|
|
195
|
+
"rollup-plugin-uglify": "^6.0.4",
|
|
196
|
+
"standard-version": "^7.1.0",
|
|
197
|
+
"ts-jest": "^24.3.0",
|
|
198
|
+
"ts-node": "^8.6.2",
|
|
200
199
|
"tslib": "^1.9.3",
|
|
201
|
-
"typescript": "
|
|
200
|
+
"typescript": "^3.7.5"
|
|
202
201
|
},
|
|
203
202
|
"scripts": {
|
|
204
203
|
"benchmark": "cross-env NODE_ENV=production TS_NODE_PROJECT=./tsconfig.cjs.json ts-node test/perf/index.tsx",
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
FormatDateOptions,
|
|
6
6
|
FormatNumberOptions,
|
|
7
7
|
FormatListOptions,
|
|
8
|
+
FormatDisplayNameOptions,
|
|
8
9
|
} from '../types';
|
|
9
10
|
import {Context} from './injectIntl';
|
|
10
11
|
|
|
@@ -13,6 +14,9 @@ enum DisplayName {
|
|
|
13
14
|
formatTime = 'FormattedTime',
|
|
14
15
|
formatNumber = 'FormattedNumber',
|
|
15
16
|
formatList = 'FormattedList',
|
|
17
|
+
// Note that this DisplayName is the locale display name, not to be confused with
|
|
18
|
+
// the name of the enum, which is for React component display name in dev tools.
|
|
19
|
+
formatDisplayName = 'FormattedDisplayName',
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
enum DisplayNameParts {
|
|
@@ -27,6 +31,7 @@ type Formatter = {
|
|
|
27
31
|
formatTime: FormatDateOptions;
|
|
28
32
|
formatNumber: FormatNumberOptions;
|
|
29
33
|
formatList: FormatListOptions;
|
|
34
|
+
formatDisplayName: FormatDisplayNameOptions;
|
|
30
35
|
};
|
|
31
36
|
|
|
32
37
|
export const FormattedNumberParts: React.FC<Formatter['formatNumber'] & {
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
createIntlCache,
|
|
15
15
|
} from '../utils';
|
|
16
16
|
import {IntlConfig, IntlShape, Omit, IntlCache} from '../types';
|
|
17
|
-
import areIntlLocalesSupported from 'intl-locales-supported';
|
|
18
17
|
import {formatNumber, formatNumberToParts} from '../formatters/number';
|
|
19
18
|
import {formatRelativeTime} from '../formatters/relativeTime';
|
|
20
19
|
import {
|
|
@@ -27,6 +26,7 @@ import {formatPlural} from '../formatters/plural';
|
|
|
27
26
|
import {formatMessage, formatHTMLMessage} from '../formatters/message';
|
|
28
27
|
import * as shallowEquals_ from 'shallow-equal/objects';
|
|
29
28
|
import {formatList} from '../formatters/list';
|
|
29
|
+
import {formatDisplayName} from '../formatters/displayName';
|
|
30
30
|
const shallowEquals: typeof shallowEquals_ =
|
|
31
31
|
(shallowEquals_ as any).default || shallowEquals_;
|
|
32
32
|
|
|
@@ -79,26 +79,36 @@ export function createIntl(
|
|
|
79
79
|
): IntlShape {
|
|
80
80
|
const formatters = createFormatters(cache);
|
|
81
81
|
const resolvedConfig = {...DEFAULT_INTL_CONFIG, ...config};
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
) {
|
|
86
|
-
const {locale, defaultLocale, onError} = resolvedConfig;
|
|
87
|
-
if (typeof onError === 'function') {
|
|
82
|
+
const {locale, defaultLocale, onError} = resolvedConfig;
|
|
83
|
+
if (!locale) {
|
|
84
|
+
if (onError) {
|
|
88
85
|
onError(
|
|
89
86
|
createError(
|
|
90
|
-
`
|
|
91
|
-
`Using default locale: "${defaultLocale}" as fallback.`
|
|
87
|
+
`"locale" was not configured, using "${defaultLocale}" as fallback. See https://github.com/formatjs/react-intl/blob/master/docs/API.md#intlshape for more details`
|
|
92
88
|
)
|
|
93
89
|
);
|
|
94
90
|
}
|
|
95
|
-
|
|
96
91
|
// Since there's no registered locale data for `locale`, this will
|
|
97
92
|
// fallback to the `defaultLocale` to make sure things can render.
|
|
98
93
|
// The `messages` are overridden to the `defaultProps` empty object
|
|
99
94
|
// to maintain referential equality across re-renders. It's assumed
|
|
100
95
|
// each <FormattedMessage> contains a `defaultMessage` prop.
|
|
101
96
|
resolvedConfig.locale = resolvedConfig.defaultLocale || 'en';
|
|
97
|
+
} else if (!Intl.NumberFormat.supportedLocalesOf(locale).length && onError) {
|
|
98
|
+
onError(
|
|
99
|
+
createError(
|
|
100
|
+
`Missing locale data for locale: "${locale}" in Intl.NumberFormat. Using default locale: "${defaultLocale}" as fallback. See https://github.com/formatjs/react-intl/blob/master/docs/Getting-Started.md#runtime-requirements for more details`
|
|
101
|
+
)
|
|
102
|
+
);
|
|
103
|
+
} else if (
|
|
104
|
+
!Intl.DateTimeFormat.supportedLocalesOf(locale).length &&
|
|
105
|
+
onError
|
|
106
|
+
) {
|
|
107
|
+
onError(
|
|
108
|
+
createError(
|
|
109
|
+
`Missing locale data for locale: "${locale}" in Intl.DateTimeFormat. Using default locale: "${defaultLocale}" as fallback. See https://github.com/formatjs/react-intl/blob/master/docs/Getting-Started.md#runtime-requirements for more details`
|
|
110
|
+
)
|
|
111
|
+
);
|
|
102
112
|
}
|
|
103
113
|
return {
|
|
104
114
|
...resolvedConfig,
|
|
@@ -146,6 +156,11 @@ export function createIntl(
|
|
|
146
156
|
formatMessage: formatMessage.bind(null, resolvedConfig, formatters),
|
|
147
157
|
formatHTMLMessage: formatHTMLMessage.bind(null, resolvedConfig, formatters),
|
|
148
158
|
formatList: formatList.bind(null, resolvedConfig, formatters.getListFormat),
|
|
159
|
+
formatDisplayName: formatDisplayName.bind(
|
|
160
|
+
null,
|
|
161
|
+
resolvedConfig,
|
|
162
|
+
formatters.getDisplayNames
|
|
163
|
+
),
|
|
149
164
|
};
|
|
150
165
|
}
|
|
151
166
|
|
|
@@ -178,6 +193,6 @@ export default class IntlProvider extends React.PureComponent<
|
|
|
178
193
|
|
|
179
194
|
render(): JSX.Element {
|
|
180
195
|
invariantIntlContext(this.state.intl);
|
|
181
|
-
return <Provider value={this.state.intl
|
|
196
|
+
return <Provider value={this.state.intl}>{this.props.children}</Provider>;
|
|
182
197
|
}
|
|
183
198
|
}
|
|
@@ -8,13 +8,7 @@ import {Context} from './injectIntl';
|
|
|
8
8
|
import {FormatRelativeTimeOptions} from '../types';
|
|
9
9
|
import {Unit} from '@formatjs/intl-relativetimeformat';
|
|
10
10
|
import {invariantIntlContext} from '../utils';
|
|
11
|
-
|
|
12
|
-
// Since rollup cannot deal with namespace being a function,
|
|
13
|
-
// this is to interop with TypeScript since `invariant`
|
|
14
|
-
// does not export a default
|
|
15
|
-
// https://github.com/rollup/rollup/issues/1267
|
|
16
|
-
import * as invariant_ from 'invariant';
|
|
17
|
-
const invariant: typeof invariant_ = (invariant_ as any).default || invariant_;
|
|
11
|
+
import {invariant} from '@formatjs/intl-utils';
|
|
18
12
|
const MINUTE = 60;
|
|
19
13
|
const HOUR = 60 * 60;
|
|
20
14
|
const DAY = 60 * 60 * 24;
|
|
@@ -82,13 +76,6 @@ function canIncrement(unit: Unit = 'second'): boolean {
|
|
|
82
76
|
return INCREMENTABLE_UNITS.includes(unit);
|
|
83
77
|
}
|
|
84
78
|
|
|
85
|
-
function verifyProps(updateIntervalInSeconds?: number, unit?: Unit): void {
|
|
86
|
-
invariant(
|
|
87
|
-
!updateIntervalInSeconds || (updateIntervalInSeconds && canIncrement(unit)),
|
|
88
|
-
'Cannot schedule update with unit longer than hour'
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
79
|
export class FormattedRelativeTime extends React.PureComponent<Props, State> {
|
|
93
80
|
// Public for testing
|
|
94
81
|
_updateTimer: any = null;
|
|
@@ -107,7 +94,11 @@ export class FormattedRelativeTime extends React.PureComponent<Props, State> {
|
|
|
107
94
|
|
|
108
95
|
constructor(props: Props) {
|
|
109
96
|
super(props);
|
|
110
|
-
|
|
97
|
+
invariant(
|
|
98
|
+
!props.updateIntervalInSeconds ||
|
|
99
|
+
!!(props.updateIntervalInSeconds && canIncrement(props.unit)),
|
|
100
|
+
'Cannot schedule update with unit longer than hour'
|
|
101
|
+
);
|
|
111
102
|
}
|
|
112
103
|
|
|
113
104
|
scheduleNextUpdate(
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {IntlConfig, Formatters, IntlFormatters} from '../types';
|
|
2
|
+
import {filterProps, createError} from '../utils';
|
|
3
|
+
import {
|
|
4
|
+
DisplayNamesOptions,
|
|
5
|
+
DisplayNames as IntlDisplayNames,
|
|
6
|
+
} from '@formatjs/intl-displaynames';
|
|
7
|
+
|
|
8
|
+
const DISPLAY_NAMES_OPTONS: Array<keyof DisplayNamesOptions> = [
|
|
9
|
+
'localeMatcher',
|
|
10
|
+
'style',
|
|
11
|
+
'type',
|
|
12
|
+
'fallback',
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
export function formatDisplayName(
|
|
16
|
+
{locale, onError}: Pick<IntlConfig, 'locale' | 'onError'>,
|
|
17
|
+
getDisplayNames: Formatters['getDisplayNames'],
|
|
18
|
+
value: Parameters<IntlFormatters['formatDisplayName']>[0],
|
|
19
|
+
options: Parameters<IntlFormatters['formatDisplayName']>[1] = {}
|
|
20
|
+
): string | undefined {
|
|
21
|
+
const DisplayNames: typeof IntlDisplayNames = (Intl as any).DisplayNames;
|
|
22
|
+
if (!DisplayNames) {
|
|
23
|
+
onError(
|
|
24
|
+
createError(`Intl.DisplayNames is not available in this environment.
|
|
25
|
+
Try polyfilling it using "@formatjs/intl-displaynames"
|
|
26
|
+
`)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const filteredOptions = filterProps(options, DISPLAY_NAMES_OPTONS);
|
|
30
|
+
try {
|
|
31
|
+
return getDisplayNames(locale, filteredOptions).of(value);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
onError(createError('Error formatting display name.', e));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -5,12 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import * as React from 'react';
|
|
8
|
-
|
|
9
|
-
// this is to interop with TypeScript since `invariant`
|
|
10
|
-
// does not export a default
|
|
11
|
-
// https://github.com/rollup/rollup/issues/1267
|
|
12
|
-
import * as invariant_ from 'invariant';
|
|
13
|
-
const invariant: typeof invariant_ = (invariant_ as any).default || invariant_;
|
|
8
|
+
import {invariant} from '@formatjs/intl-utils';
|
|
14
9
|
|
|
15
10
|
import {
|
|
16
11
|
Formatters,
|
|
@@ -77,6 +72,10 @@ function deepMergeFormatsAndSetTimeZone(
|
|
|
77
72
|
};
|
|
78
73
|
}
|
|
79
74
|
|
|
75
|
+
export const prepareIntlMessageFormatHtmlOutput = (
|
|
76
|
+
chunks: (string | object)[]
|
|
77
|
+
): React.ReactElement => React.createElement(React.Fragment, null, ...chunks);
|
|
78
|
+
|
|
80
79
|
export function formatMessage(
|
|
81
80
|
{
|
|
82
81
|
locale,
|
|
@@ -123,17 +122,12 @@ export function formatMessage(
|
|
|
123
122
|
string,
|
|
124
123
|
PrimitiveType | React.ReactElement | FormatXMLElementFn
|
|
125
124
|
> = {}
|
|
126
|
-
): string | React.ReactNodeArray {
|
|
125
|
+
): string | React.ReactNodeArray | React.ReactElement {
|
|
127
126
|
const {id, defaultMessage} = messageDescriptor;
|
|
128
127
|
|
|
129
128
|
// `id` is a required field of a Message Descriptor.
|
|
130
|
-
invariant(id, '[React Intl] An `id` must be provided to format a message.');
|
|
131
|
-
|
|
132
|
-
throw new Error(
|
|
133
|
-
'[React Intl] An `id` must be provided to format a message.'
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
const message = messages && messages[id];
|
|
129
|
+
invariant(!!id, '[React Intl] An `id` must be provided to format a message.');
|
|
130
|
+
const message = messages && messages[String(id)];
|
|
137
131
|
formats = deepMergeFormatsAndSetTimeZone(formats, timeZone);
|
|
138
132
|
defaultFormats = deepMergeFormatsAndSetTimeZone(defaultFormats, timeZone);
|
|
139
133
|
|
|
@@ -198,17 +192,18 @@ export function formatMessage(
|
|
|
198
192
|
)
|
|
199
193
|
);
|
|
200
194
|
if (typeof message === 'string') {
|
|
201
|
-
return message || defaultMessage || id;
|
|
195
|
+
return message || defaultMessage || String(id);
|
|
202
196
|
}
|
|
203
|
-
return defaultMessage || id;
|
|
197
|
+
return defaultMessage || String(id);
|
|
204
198
|
}
|
|
205
199
|
if (
|
|
206
200
|
formattedMessageParts.length === 1 &&
|
|
207
201
|
typeof formattedMessageParts[0] === 'string'
|
|
208
202
|
) {
|
|
209
|
-
return (formattedMessageParts[0] as string) || defaultMessage || id;
|
|
203
|
+
return (formattedMessageParts[0] as string) || defaultMessage || String(id);
|
|
210
204
|
}
|
|
211
|
-
|
|
205
|
+
|
|
206
|
+
return prepareIntlMessageFormatHtmlOutput(formattedMessageParts);
|
|
212
207
|
}
|
|
213
208
|
|
|
214
209
|
export function formatHTMLMessage(
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
export * from './types';
|
|
8
|
-
export
|
|
8
|
+
export function defineMessages<T, U extends Record<string, T>>(msgs: U): U {
|
|
9
|
+
return msgs;
|
|
10
|
+
}
|
|
9
11
|
import {
|
|
10
12
|
createFormattedComponent,
|
|
11
13
|
createFormattedDateTimePartsComponent,
|
|
@@ -13,6 +15,7 @@ import {
|
|
|
13
15
|
import {CustomFormatConfig} from './types';
|
|
14
16
|
import {UnifiedNumberFormatOptions} from '@formatjs/intl-unified-numberformat';
|
|
15
17
|
import {IntlListFormatOptions} from '@formatjs/intl-listformat';
|
|
18
|
+
import {DisplayNamesOptions} from '@formatjs/intl-displaynames/lib';
|
|
16
19
|
export {
|
|
17
20
|
default as injectIntl,
|
|
18
21
|
Provider as RawIntlProvider,
|
|
@@ -38,6 +41,9 @@ export const FormattedNumber: React.FC<UnifiedNumberFormatOptions &
|
|
|
38
41
|
export const FormattedList: React.FC<IntlListFormatOptions & {
|
|
39
42
|
value: React.ReactNode[];
|
|
40
43
|
}> = createFormattedComponent('formatList');
|
|
44
|
+
export const FormattedDisplayName: React.FC<DisplayNamesOptions & {
|
|
45
|
+
value: string | number | object;
|
|
46
|
+
}> = createFormattedComponent('formatDisplayName');
|
|
41
47
|
export const FormattedDateParts = createFormattedDateTimePartsComponent(
|
|
42
48
|
'formatDate'
|
|
43
49
|
);
|
package/src/types.ts
CHANGED
|
@@ -15,6 +15,7 @@ import IntlRelativeTimeFormat, {
|
|
|
15
15
|
import {MessageFormatElement} from 'intl-messageformat-parser';
|
|
16
16
|
import {UnifiedNumberFormatOptions} from '@formatjs/intl-unified-numberformat';
|
|
17
17
|
import IntlListFormat, {IntlListFormatOptions} from '@formatjs/intl-listformat';
|
|
18
|
+
import {DisplayNames, DisplayNamesOptions} from '@formatjs/intl-displaynames';
|
|
18
19
|
|
|
19
20
|
export interface IntlConfig {
|
|
20
21
|
locale: string;
|
|
@@ -58,6 +59,11 @@ export type FormatPluralOptions = Exclude<
|
|
|
58
59
|
|
|
59
60
|
export type FormatListOptions = Exclude<IntlListFormatOptions, 'localeMatcher'>;
|
|
60
61
|
|
|
62
|
+
export type FormatDisplayNameOptions = Exclude<
|
|
63
|
+
DisplayNamesOptions,
|
|
64
|
+
'localeMatcher'
|
|
65
|
+
>;
|
|
66
|
+
|
|
61
67
|
export interface IntlFormatters {
|
|
62
68
|
formatDate(
|
|
63
69
|
value: Parameters<Intl.DateTimeFormat['format']>[0] | string,
|
|
@@ -107,14 +113,15 @@ export interface IntlFormatters {
|
|
|
107
113
|
descriptor: MessageDescriptor,
|
|
108
114
|
values?: Record<string, PrimitiveType>
|
|
109
115
|
): React.ReactNode;
|
|
110
|
-
formatList(
|
|
111
|
-
values: Array<string>,
|
|
112
|
-
opts?: FormatListOptions
|
|
113
|
-
): string;
|
|
116
|
+
formatList(values: Array<string>, opts?: FormatListOptions): string;
|
|
114
117
|
formatList(
|
|
115
118
|
values: Array<string | React.ReactNode>,
|
|
116
119
|
opts?: FormatListOptions
|
|
117
120
|
): React.ReactNode;
|
|
121
|
+
formatDisplayName(
|
|
122
|
+
value: Parameters<DisplayNames['of']>[0],
|
|
123
|
+
opts?: FormatDisplayNameOptions
|
|
124
|
+
): string | undefined;
|
|
118
125
|
}
|
|
119
126
|
|
|
120
127
|
export interface Formatters {
|
|
@@ -136,6 +143,9 @@ export interface Formatters {
|
|
|
136
143
|
getListFormat(
|
|
137
144
|
...args: ConstructorParameters<typeof IntlListFormat>
|
|
138
145
|
): IntlListFormat;
|
|
146
|
+
getDisplayNames(
|
|
147
|
+
...args: ConstructorParameters<typeof DisplayNames>
|
|
148
|
+
): DisplayNames;
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
export interface IntlShape extends IntlConfig, IntlFormatters {
|
|
@@ -149,10 +159,11 @@ export interface IntlCache {
|
|
|
149
159
|
relativeTime: Record<string, IntlRelativeTimeFormat>;
|
|
150
160
|
pluralRules: Record<string, Intl.PluralRules>;
|
|
151
161
|
list: Record<string, IntlListFormat>;
|
|
162
|
+
displayNames: Record<string, DisplayNames>;
|
|
152
163
|
}
|
|
153
164
|
|
|
154
165
|
export interface MessageDescriptor {
|
|
155
|
-
id?: string;
|
|
166
|
+
id?: string | number;
|
|
156
167
|
description?: string | object;
|
|
157
168
|
defaultMessage?: string;
|
|
158
169
|
}
|
package/src/utils.ts
CHANGED
|
@@ -13,13 +13,8 @@ import {IntlConfig, IntlCache, CustomFormats, Formatters} from './types';
|
|
|
13
13
|
import * as React from 'react';
|
|
14
14
|
import IntlMessageFormat from 'intl-messageformat';
|
|
15
15
|
import memoizeIntlConstructor from 'intl-format-cache';
|
|
16
|
-
|
|
17
|
-
// this is to interop with TypeScript since `invariant`
|
|
18
|
-
// does not export a default
|
|
19
|
-
// https://github.com/rollup/rollup/issues/1267
|
|
20
|
-
import * as invariant_ from 'invariant';
|
|
16
|
+
import {invariant} from '@formatjs/intl-utils';
|
|
21
17
|
import {IntlRelativeTimeFormatOptions} from '@formatjs/intl-relativetimeformat';
|
|
22
|
-
const invariant: typeof invariant_ = (invariant_ as any).default || invariant_;
|
|
23
18
|
|
|
24
19
|
const ESCAPED_CHARS: Record<number, string> = {
|
|
25
20
|
38: '&',
|
|
@@ -54,7 +49,7 @@ export function filterProps<T extends Record<string, any>, K extends string>(
|
|
|
54
49
|
}, {} as Pick<T, K>);
|
|
55
50
|
}
|
|
56
51
|
|
|
57
|
-
export function invariantIntlContext(intl?: any):
|
|
52
|
+
export function invariantIntlContext(intl?: any): asserts intl {
|
|
58
53
|
invariant(
|
|
59
54
|
intl,
|
|
60
55
|
'[React Intl] Could not find required `intl` object. ' +
|
|
@@ -102,6 +97,7 @@ export function createIntlCache(): IntlCache {
|
|
|
102
97
|
relativeTime: {},
|
|
103
98
|
pluralRules: {},
|
|
104
99
|
list: {},
|
|
100
|
+
displayNames: {},
|
|
105
101
|
};
|
|
106
102
|
}
|
|
107
103
|
|
|
@@ -114,6 +110,7 @@ export function createFormatters(
|
|
|
114
110
|
): Formatters {
|
|
115
111
|
const RelativeTimeFormat = (Intl as any).RelativeTimeFormat;
|
|
116
112
|
const ListFormat = (Intl as any).ListFormat;
|
|
113
|
+
const DisplayNames = (Intl as any).DisplayNames;
|
|
117
114
|
return {
|
|
118
115
|
getDateTimeFormat: memoizeIntlConstructor(
|
|
119
116
|
Intl.DateTimeFormat,
|
|
@@ -127,6 +124,7 @@ export function createFormatters(
|
|
|
127
124
|
),
|
|
128
125
|
getPluralRules: memoizeIntlConstructor(Intl.PluralRules, cache.pluralRules),
|
|
129
126
|
getListFormat: memoizeIntlConstructor(ListFormat, cache.list),
|
|
127
|
+
getDisplayNames: memoizeIntlConstructor(DisplayNames, cache.displayNames),
|
|
130
128
|
};
|
|
131
129
|
}
|
|
132
130
|
|