react-intl 3.9.2 → 3.12.0

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/components/createFormattedComponent.d.ts +2 -1
  3. package/dist/components/createFormattedComponent.js +7 -2
  4. package/dist/components/html-message.js +1 -1
  5. package/dist/components/injectIntl.d.ts +1 -1
  6. package/dist/components/message.js +13 -4
  7. package/dist/components/plural.d.ts +1 -1
  8. package/dist/components/provider.js +3 -2
  9. package/dist/components/relative.js +3 -10
  10. package/dist/formatters/dateTime.js +2 -2
  11. package/dist/formatters/displayName.d.ts +2 -0
  12. package/dist/formatters/displayName.js +25 -0
  13. package/dist/formatters/message.d.ts +1 -0
  14. package/dist/formatters/message.js +19 -18
  15. package/dist/index.d.ts +6 -2
  16. package/dist/index.js +1 -0
  17. package/dist/react-intl.api.md +22 -5
  18. package/dist/react-intl.d.ts +42 -9
  19. package/dist/react-intl.js +595 -389
  20. package/dist/react-intl.js.map +1 -1
  21. package/dist/react-intl.min.js +1 -1
  22. package/dist/react-intl.min.js.map +1 -1
  23. package/dist/types.d.ts +6 -1
  24. package/dist/utils.d.ts +1 -1
  25. package/dist/utils.js +5 -7
  26. package/lib/components/createFormattedComponent.d.ts +2 -1
  27. package/lib/components/createFormattedComponent.js +7 -2
  28. package/lib/components/html-message.js +1 -1
  29. package/lib/components/injectIntl.d.ts +1 -1
  30. package/lib/components/message.js +5 -3
  31. package/lib/components/plural.d.ts +1 -1
  32. package/lib/components/provider.js +3 -2
  33. package/lib/components/relative.js +3 -10
  34. package/lib/formatters/dateTime.js +2 -2
  35. package/lib/formatters/displayName.d.ts +2 -0
  36. package/lib/formatters/displayName.js +22 -0
  37. package/lib/formatters/message.d.ts +1 -0
  38. package/lib/formatters/message.js +12 -18
  39. package/lib/index.d.ts +6 -2
  40. package/lib/index.js +1 -0
  41. package/lib/react-intl.d.ts +18 -5
  42. package/lib/tsdoc-metadata.json +1 -1
  43. package/lib/types.d.ts +6 -1
  44. package/lib/utils.d.ts +1 -1
  45. package/lib/utils.js +4 -6
  46. package/package.json +28 -27
  47. package/src/components/createFormattedComponent.tsx +5 -0
  48. package/src/components/provider.tsx +7 -1
  49. package/src/components/relative.tsx +6 -15
  50. package/src/formatters/displayName.ts +35 -0
  51. package/src/formatters/message.ts +13 -18
  52. package/src/index.ts +4 -0
  53. package/src/types.ts +16 -5
  54. package/src/utils.ts +5 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-intl",
3
- "version": "3.9.2",
3
+ "version": "3.12.0",
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,49 +131,50 @@
131
131
  "types": "./lib/react-intl.d.ts",
132
132
  "sideEffects": false,
133
133
  "dependencies": {
134
- "@formatjs/intl-listformat": "^1.3.1",
135
- "@formatjs/intl-relativetimeformat": "^4.5.1",
136
- "@formatjs/intl-unified-numberformat": "^2.2.0",
134
+ "@formatjs/intl-displaynames": "^1.2.0",
135
+ "@formatjs/intl-listformat": "^1.3.7",
136
+ "@formatjs/intl-relativetimeformat": "^4.5.7",
137
+ "@formatjs/intl-unified-numberformat": "^3.0.4",
138
+ "@formatjs/intl-utils": "^2.0.4",
137
139
  "@formatjs/macro": "^0.2.6",
138
140
  "@types/hoist-non-react-statics": "^3.3.1",
139
- "@types/invariant": "^2.2.30",
141
+ "@types/invariant": "^2.2.31",
140
142
  "hoist-non-react-statics": "^3.3.1",
141
- "intl-format-cache": "^4.2.13",
143
+ "intl-format-cache": "^4.2.19",
142
144
  "intl-locales-supported": "^1.8.4",
143
- "intl-messageformat": "^7.7.2",
144
- "intl-messageformat-parser": "^3.5.1",
145
- "invariant": "^2.1.1",
145
+ "intl-messageformat": "^7.8.2",
146
+ "intl-messageformat-parser": "^3.6.2",
146
147
  "shallow-equal": "^1.2.1"
147
148
  },
148
149
  "peerDependencies": {
149
150
  "react": "^16.3.0"
150
151
  },
151
152
  "devDependencies": {
152
- "@babel/core": "^7.7.5",
153
- "@babel/node": "^7.7.4",
153
+ "@babel/core": "^7.7.7",
154
+ "@babel/node": "^7.7.7",
154
155
  "@babel/plugin-proposal-class-properties": "^7.7.4",
155
156
  "@babel/plugin-transform-modules-commonjs": "^7.7.5",
156
- "@babel/preset-env": "^7.7.6",
157
+ "@babel/preset-env": "^7.7.7",
157
158
  "@babel/preset-react": "^7.7.4",
158
- "@formatjs/intl-pluralrules": "^1.3.9",
159
- "@microsoft/api-documenter": "^7.7.2",
160
- "@microsoft/api-extractor": "^7.7.0",
159
+ "@formatjs/intl-pluralrules": "^1.5.0",
160
+ "@microsoft/api-documenter": "^7.7.3",
161
+ "@microsoft/api-extractor": "^7.7.1",
161
162
  "@types/benchmark": "^1.0.31",
162
163
  "@types/enzyme": "^3.10.4",
163
- "@types/jest": "^24.0.23",
164
+ "@types/jest": "^24.0.25",
164
165
  "@types/prop-types": "^15.7.3",
165
- "@types/react": "^16.9.16",
166
+ "@types/react": "^16.9.17",
166
167
  "@types/react-dom": "^16.9.4",
167
- "@typescript-eslint/eslint-plugin": "^2.11.0",
168
- "@typescript-eslint/parser": "^2.11.0",
168
+ "@typescript-eslint/eslint-plugin": "^2.15.0",
169
+ "@typescript-eslint/parser": "^2.15.0",
169
170
  "babel-jest": "^24.9.0",
170
171
  "benchmark": "^2.1.0",
171
- "core-js": "^3.4.8",
172
+ "core-js": "^3.6.2",
172
173
  "cross-env": "^6.0.3",
173
- "enzyme": "^3.6.0",
174
- "enzyme-adapter-react-16": "^1.15.1",
174
+ "enzyme": "^3.11.0",
175
+ "enzyme-adapter-react-16": "^1.15.2",
175
176
  "enzyme-to-json": "^3.4.3",
176
- "eslint": "^6.7.2",
177
+ "eslint": "^6.8.0",
177
178
  "eslint-plugin-react": "^7.17.0",
178
179
  "fs-extra": "^8.1.0",
179
180
  "full-icu": "^1.3.0",
@@ -187,18 +188,18 @@
187
188
  "react": "^16.12.0",
188
189
  "react-dom": "^16.12.0",
189
190
  "rimraf": "^3.0.0",
190
- "rollup": "^1.27.9",
191
+ "rollup": "^1.29.0",
191
192
  "rollup-plugin-babel": "^4.3.3",
192
193
  "rollup-plugin-commonjs": "^10.1.0",
193
194
  "rollup-plugin-node-resolve": "^5.2.0",
194
195
  "rollup-plugin-replace": "^2.0.0",
195
196
  "rollup-plugin-typescript2": "^0.25.3",
196
- "rollup-plugin-uglify": "^6.0.3",
197
+ "rollup-plugin-uglify": "^6.0.4",
197
198
  "standard-version": "^7.0.1",
198
- "ts-jest": "^24.2.0",
199
+ "ts-jest": "^24.3.0",
199
200
  "ts-node": "^8.5.4",
200
201
  "tslib": "^1.9.3",
201
- "typescript": "~3.3.0"
202
+ "typescript": "^3.7.0"
202
203
  },
203
204
  "scripts": {
204
205
  "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'] & {
@@ -27,6 +27,7 @@ import {formatPlural} from '../formatters/plural';
27
27
  import {formatMessage, formatHTMLMessage} from '../formatters/message';
28
28
  import * as shallowEquals_ from 'shallow-equal/objects';
29
29
  import {formatList} from '../formatters/list';
30
+ import {formatDisplayName} from '../formatters/displayName';
30
31
  const shallowEquals: typeof shallowEquals_ =
31
32
  (shallowEquals_ as any).default || shallowEquals_;
32
33
 
@@ -146,6 +147,11 @@ export function createIntl(
146
147
  formatMessage: formatMessage.bind(null, resolvedConfig, formatters),
147
148
  formatHTMLMessage: formatHTMLMessage.bind(null, resolvedConfig, formatters),
148
149
  formatList: formatList.bind(null, resolvedConfig, formatters.getListFormat),
150
+ formatDisplayName: formatDisplayName.bind(
151
+ null,
152
+ resolvedConfig,
153
+ formatters.getDisplayNames
154
+ ),
149
155
  };
150
156
  }
151
157
 
@@ -178,6 +184,6 @@ export default class IntlProvider extends React.PureComponent<
178
184
 
179
185
  render(): JSX.Element {
180
186
  invariantIntlContext(this.state.intl);
181
- return <Provider value={this.state.intl!}>{this.props.children}</Provider>;
187
+ return <Provider value={this.state.intl}>{this.props.children}</Provider>;
182
188
  }
183
189
  }
@@ -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
- verifyProps(props.updateIntervalInSeconds, props.unit);
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
- // Since rollup cannot deal with namespace being a function,
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
- if (!id) {
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
- return formattedMessageParts;
205
+
206
+ return prepareIntlMessageFormatHtmlOutput(formattedMessageParts);
212
207
  }
213
208
 
214
209
  export function formatHTMLMessage(
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  import {CustomFormatConfig} from './types';
14
14
  import {UnifiedNumberFormatOptions} from '@formatjs/intl-unified-numberformat';
15
15
  import {IntlListFormatOptions} from '@formatjs/intl-listformat';
16
+ import {DisplayNamesOptions} from '@formatjs/intl-displaynames/lib';
16
17
  export {
17
18
  default as injectIntl,
18
19
  Provider as RawIntlProvider,
@@ -38,6 +39,9 @@ export const FormattedNumber: React.FC<UnifiedNumberFormatOptions &
38
39
  export const FormattedList: React.FC<IntlListFormatOptions & {
39
40
  value: React.ReactNode[];
40
41
  }> = createFormattedComponent('formatList');
42
+ export const FormattedDisplayName: React.FC<DisplayNamesOptions & {
43
+ value: string | number | object;
44
+ }> = createFormattedComponent('formatDisplayName');
41
45
  export const FormattedDateParts = createFormattedDateTimePartsComponent(
42
46
  'formatDate'
43
47
  );
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
- // Since rollup cannot deal with namespace being a function,
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: '&amp;',
@@ -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): void {
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