@formatjs/intl 2.3.2 → 2.4.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/index.d.ts +17 -0
- package/index.d.ts.map +1 -0
- package/index.js +40 -0
- package/lib/index.d.ts +17 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +17 -0
- package/lib/src/create-intl.d.ts +11 -0
- package/lib/src/create-intl.d.ts.map +1 -0
- package/lib/src/create-intl.js +55 -0
- package/lib/src/dateTime.d.ts +38 -0
- package/lib/src/dateTime.d.ts.map +1 -0
- package/lib/src/dateTime.js +117 -0
- package/lib/src/displayName.d.ts +6 -0
- package/lib/src/displayName.d.ts.map +1 -0
- package/lib/src/displayName.js +22 -0
- package/lib/src/error.d.ts +34 -0
- package/lib/src/error.d.ts.map +1 -0
- package/lib/src/error.js +88 -0
- package/lib/src/list.d.ts +11 -0
- package/lib/src/list.d.ts.map +1 -0
- package/lib/src/list.js +61 -0
- package/lib/src/message.d.ts +16 -0
- package/lib/src/message.d.ts.map +1 -0
- package/lib/src/message.js +103 -0
- package/lib/src/number.d.ts +17 -0
- package/lib/src/number.d.ts.map +1 -0
- package/lib/src/number.js +54 -0
- package/lib/src/plural.d.ts +7 -0
- package/lib/src/plural.d.ts.map +1 -0
- package/lib/src/plural.js +19 -0
- package/lib/src/relativeTime.d.ts +7 -0
- package/lib/src/relativeTime.d.ts.map +1 -0
- package/lib/src/relativeTime.js +29 -0
- package/lib/src/types.d.ts +103 -0
- package/lib/src/types.d.ts.map +1 -0
- package/lib/src/types.js +1 -0
- package/lib/src/utils.d.ts +12 -0
- package/lib/src/utils.d.ts.map +1 -0
- package/lib/src/utils.js +162 -0
- package/package.json +10 -10
- package/src/create-intl.d.ts +11 -0
- package/src/create-intl.d.ts.map +1 -0
- package/src/create-intl.js +59 -0
- package/src/dateTime.d.ts +38 -0
- package/src/dateTime.d.ts.map +1 -0
- package/src/dateTime.js +126 -0
- package/src/displayName.d.ts +6 -0
- package/src/displayName.d.ts.map +1 -0
- package/src/displayName.js +26 -0
- package/src/error.d.ts +34 -0
- package/src/error.d.ts.map +1 -0
- package/src/error.js +91 -0
- package/src/list.d.ts +11 -0
- package/src/list.d.ts.map +1 -0
- package/src/list.js +66 -0
- package/src/message.d.ts +16 -0
- package/src/message.d.ts.map +1 -0
- package/src/message.js +107 -0
- package/src/number.d.ts +17 -0
- package/src/number.d.ts.map +1 -0
- package/src/number.js +60 -0
- package/src/plural.d.ts +7 -0
- package/src/plural.d.ts.map +1 -0
- package/src/plural.js +23 -0
- package/src/relativeTime.d.ts +7 -0
- package/src/relativeTime.d.ts.map +1 -0
- package/src/relativeTime.js +33 -0
- package/src/types.d.ts +103 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.js +2 -0
- package/src/utils.d.ts +12 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.js +169 -0
- package/BUILD +0 -79
- package/CHANGELOG.md +0 -537
- package/index.ts +0 -38
- package/src/create-intl.ts +0 -159
- package/src/dateTime.ts +0 -204
- package/src/displayName.ts +0 -54
- package/src/error.ts +0 -106
- package/src/list.ts +0 -119
- package/src/message.ts +0 -246
- package/src/number.ts +0 -101
- package/src/plural.ts +0 -45
- package/src/relativeTime.ts +0 -74
- package/src/types.ts +0 -234
- package/src/utils.ts +0 -177
- package/tests/__snapshots__/formatDate.test.ts.snap +0 -13
- package/tests/__snapshots__/formatMessage.test.ts.snap +0 -45
- package/tests/__snapshots__/formatNumber.test.ts.snap +0 -13
- package/tests/__snapshots__/formatRelativeTime.test.ts.snap +0 -19
- package/tests/__snapshots__/formatTime.test.ts.snap +0 -13
- package/tests/create-intl.test.ts +0 -60
- package/tests/error.test.ts +0 -25
- package/tests/formatDate.test.ts +0 -167
- package/tests/formatDisplayNames.test.ts +0 -63
- package/tests/formatList.test.ts +0 -51
- package/tests/formatMessage.test.ts +0 -495
- package/tests/formatNumber.test.ts +0 -172
- package/tests/formatPlural.test.ts +0 -119
- package/tests/formatRelativeTime.test.ts +0 -145
- package/tests/formatTime.test.ts +0 -234
- package/tests/global.d.ts +0 -7
- package/tsconfig.json +0 -5
package/src/utils.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IntlCache,
|
|
3
|
-
CustomFormats,
|
|
4
|
-
Formatters,
|
|
5
|
-
OnErrorFn,
|
|
6
|
-
OnWarnFn,
|
|
7
|
-
ResolvedIntlConfig,
|
|
8
|
-
} from './types'
|
|
9
|
-
import {IntlMessageFormat} from 'intl-messageformat'
|
|
10
|
-
import memoize, {Cache, strategies} from '@formatjs/fast-memoize'
|
|
11
|
-
import {UnsupportedFormatterError} from './error'
|
|
12
|
-
import {DateTimeFormat, NumberFormatOptions} from '@formatjs/ecma402-abstract'
|
|
13
|
-
|
|
14
|
-
export function filterProps<T extends Record<string, any>, K extends string>(
|
|
15
|
-
props: T,
|
|
16
|
-
allowlist: Array<K>,
|
|
17
|
-
defaults: Partial<T> = {}
|
|
18
|
-
): Pick<T, K> {
|
|
19
|
-
return allowlist.reduce((filtered, name) => {
|
|
20
|
-
if (name in props) {
|
|
21
|
-
filtered[name] = props[name]
|
|
22
|
-
} else if (name in defaults) {
|
|
23
|
-
filtered[name] = defaults[name]!
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return filtered
|
|
27
|
-
}, {} as Pick<T, K>)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const defaultErrorHandler: OnErrorFn = error => {
|
|
31
|
-
// @ts-ignore just so we don't need to declare dep on @types/node
|
|
32
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
33
|
-
console.error(error)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const defaultWarnHandler: OnWarnFn = (warning: string) => {
|
|
38
|
-
// @ts-ignore just so we don't need to declare dep on @types/node
|
|
39
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
40
|
-
console.warn(warning)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const DEFAULT_INTL_CONFIG: Pick<
|
|
45
|
-
ResolvedIntlConfig<any>,
|
|
46
|
-
| 'fallbackOnEmptyString'
|
|
47
|
-
| 'formats'
|
|
48
|
-
| 'messages'
|
|
49
|
-
| 'timeZone'
|
|
50
|
-
| 'defaultLocale'
|
|
51
|
-
| 'defaultFormats'
|
|
52
|
-
| 'onError'
|
|
53
|
-
| 'onWarn'
|
|
54
|
-
> = {
|
|
55
|
-
formats: {},
|
|
56
|
-
messages: {},
|
|
57
|
-
timeZone: undefined,
|
|
58
|
-
|
|
59
|
-
defaultLocale: 'en',
|
|
60
|
-
defaultFormats: {},
|
|
61
|
-
|
|
62
|
-
fallbackOnEmptyString: true,
|
|
63
|
-
|
|
64
|
-
onError: defaultErrorHandler,
|
|
65
|
-
onWarn: defaultWarnHandler,
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function createIntlCache(): IntlCache {
|
|
69
|
-
return {
|
|
70
|
-
dateTime: {},
|
|
71
|
-
number: {},
|
|
72
|
-
message: {},
|
|
73
|
-
relativeTime: {},
|
|
74
|
-
pluralRules: {},
|
|
75
|
-
list: {},
|
|
76
|
-
displayNames: {},
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function createFastMemoizeCache<V>(store: Record<string, V>): Cache<string, V> {
|
|
81
|
-
return {
|
|
82
|
-
create() {
|
|
83
|
-
return {
|
|
84
|
-
get(key) {
|
|
85
|
-
return store[key]
|
|
86
|
-
},
|
|
87
|
-
set(key, value) {
|
|
88
|
-
store[key] = value
|
|
89
|
-
},
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Create intl formatters and populate cache
|
|
97
|
-
* @param cache explicit cache to prevent leaking memory
|
|
98
|
-
*/
|
|
99
|
-
export function createFormatters(
|
|
100
|
-
cache: IntlCache = createIntlCache()
|
|
101
|
-
): Formatters {
|
|
102
|
-
const RelativeTimeFormat = (Intl as any).RelativeTimeFormat
|
|
103
|
-
const ListFormat = (Intl as any).ListFormat
|
|
104
|
-
const DisplayNames = (Intl as any).DisplayNames
|
|
105
|
-
const getDateTimeFormat = memoize(
|
|
106
|
-
(...args) => new Intl.DateTimeFormat(...args) as DateTimeFormat,
|
|
107
|
-
{
|
|
108
|
-
cache: createFastMemoizeCache(cache.dateTime),
|
|
109
|
-
strategy: strategies.variadic,
|
|
110
|
-
}
|
|
111
|
-
)
|
|
112
|
-
const getNumberFormat = memoize((...args) => new Intl.NumberFormat(...args), {
|
|
113
|
-
cache: createFastMemoizeCache(cache.number),
|
|
114
|
-
strategy: strategies.variadic,
|
|
115
|
-
})
|
|
116
|
-
const getPluralRules = memoize((...args) => new Intl.PluralRules(...args), {
|
|
117
|
-
cache: createFastMemoizeCache(cache.pluralRules),
|
|
118
|
-
strategy: strategies.variadic,
|
|
119
|
-
})
|
|
120
|
-
return {
|
|
121
|
-
getDateTimeFormat,
|
|
122
|
-
getNumberFormat,
|
|
123
|
-
getMessageFormat: memoize(
|
|
124
|
-
(message, locales, overrideFormats, opts) =>
|
|
125
|
-
new IntlMessageFormat(message, locales, overrideFormats, {
|
|
126
|
-
formatters: {
|
|
127
|
-
getNumberFormat,
|
|
128
|
-
getDateTimeFormat,
|
|
129
|
-
getPluralRules,
|
|
130
|
-
},
|
|
131
|
-
...(opts || {}),
|
|
132
|
-
}),
|
|
133
|
-
{
|
|
134
|
-
cache: createFastMemoizeCache(cache.message),
|
|
135
|
-
strategy: strategies.variadic,
|
|
136
|
-
}
|
|
137
|
-
),
|
|
138
|
-
getRelativeTimeFormat: memoize(
|
|
139
|
-
(...args) => new RelativeTimeFormat(...args),
|
|
140
|
-
{
|
|
141
|
-
cache: createFastMemoizeCache(cache.relativeTime),
|
|
142
|
-
strategy: strategies.variadic,
|
|
143
|
-
}
|
|
144
|
-
),
|
|
145
|
-
getPluralRules,
|
|
146
|
-
getListFormat: memoize((...args) => new ListFormat(...args), {
|
|
147
|
-
cache: createFastMemoizeCache(cache.list),
|
|
148
|
-
strategy: strategies.variadic,
|
|
149
|
-
}),
|
|
150
|
-
getDisplayNames: memoize((...args) => new DisplayNames(...args), {
|
|
151
|
-
cache: createFastMemoizeCache(cache.displayNames),
|
|
152
|
-
strategy: strategies.variadic,
|
|
153
|
-
}),
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export function getNamedFormat<T extends keyof CustomFormats>(
|
|
158
|
-
formats: CustomFormats,
|
|
159
|
-
type: T,
|
|
160
|
-
name: string,
|
|
161
|
-
onError: OnErrorFn
|
|
162
|
-
):
|
|
163
|
-
| NumberFormatOptions
|
|
164
|
-
| Intl.DateTimeFormatOptions
|
|
165
|
-
| Intl.RelativeTimeFormatOptions
|
|
166
|
-
| undefined {
|
|
167
|
-
const formatType = formats && formats[type]
|
|
168
|
-
let format
|
|
169
|
-
if (formatType) {
|
|
170
|
-
format = formatType[name]
|
|
171
|
-
}
|
|
172
|
-
if (format) {
|
|
173
|
-
return format
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
onError(new UnsupportedFormatterError(`No ${type} format named: ${name}`))
|
|
177
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`format API formatDate() options falls back and warns on invalid Intl.DateTimeFormat options 1`] = `
|
|
4
|
-
Array [
|
|
5
|
-
"FORMAT_ERROR",
|
|
6
|
-
]
|
|
7
|
-
`;
|
|
8
|
-
|
|
9
|
-
exports[`format API formatDate() options handles missing named formats and warns 1`] = `
|
|
10
|
-
Array [
|
|
11
|
-
"UNSUPPORTED_FORMATTER",
|
|
12
|
-
]
|
|
13
|
-
`;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`format API formatMessage() fallbacks formats \`defaultMessage\` when message has a syntax error 1`] = `
|
|
4
|
-
Array [
|
|
5
|
-
"FORMAT_ERROR",
|
|
6
|
-
]
|
|
7
|
-
`;
|
|
8
|
-
|
|
9
|
-
exports[`format API formatMessage() fallbacks formats \`defaultMessage\` when message has missing values 1`] = `
|
|
10
|
-
Array [
|
|
11
|
-
"FORMAT_ERROR",
|
|
12
|
-
]
|
|
13
|
-
`;
|
|
14
|
-
|
|
15
|
-
exports[`format API formatMessage() fallbacks returns \`defaultMessage\` source when formatting errors and missing message 1`] = `
|
|
16
|
-
Array [
|
|
17
|
-
"MISSING_TRANSLATION",
|
|
18
|
-
"FORMAT_ERROR",
|
|
19
|
-
]
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
exports[`format API formatMessage() fallbacks returns message \`id\` when message and \`defaultMessage\` are empty 1`] = `
|
|
23
|
-
Array [
|
|
24
|
-
"MISSING_TRANSLATION",
|
|
25
|
-
]
|
|
26
|
-
`;
|
|
27
|
-
|
|
28
|
-
exports[`format API formatMessage() fallbacks returns message \`id\` when message and \`defaultMessage\` are missing 1`] = `
|
|
29
|
-
Array [
|
|
30
|
-
"MISSING_TRANSLATION",
|
|
31
|
-
]
|
|
32
|
-
`;
|
|
33
|
-
|
|
34
|
-
exports[`format API formatMessage() fallbacks returns message source when formatting error and missing \`defaultMessage\` 1`] = `
|
|
35
|
-
Array [
|
|
36
|
-
"FORMAT_ERROR",
|
|
37
|
-
]
|
|
38
|
-
`;
|
|
39
|
-
|
|
40
|
-
exports[`format API formatMessage() fallbacks returns message source when message and \`defaultMessage\` have formatting errors 1`] = `
|
|
41
|
-
Array [
|
|
42
|
-
"FORMAT_ERROR",
|
|
43
|
-
"FORMAT_ERROR",
|
|
44
|
-
]
|
|
45
|
-
`;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`format API formatNumber() options falls back and warns on invalid Intl.NumberFormat options 1`] = `
|
|
4
|
-
Array [
|
|
5
|
-
"FORMAT_ERROR",
|
|
6
|
-
]
|
|
7
|
-
`;
|
|
8
|
-
|
|
9
|
-
exports[`format API formatNumber() options handles missing named formats and warns 1`] = `
|
|
10
|
-
Array [
|
|
11
|
-
"UNSUPPORTED_FORMATTER",
|
|
12
|
-
]
|
|
13
|
-
`;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`format API formatRelativeTime() falls back and warns when no value is provided 1`] = `
|
|
4
|
-
Array [
|
|
5
|
-
"FORMAT_ERROR",
|
|
6
|
-
]
|
|
7
|
-
`;
|
|
8
|
-
|
|
9
|
-
exports[`format API formatRelativeTime() options falls back and warns on invalid IntlRelativeFormat options 1`] = `
|
|
10
|
-
Array [
|
|
11
|
-
"FORMAT_ERROR",
|
|
12
|
-
]
|
|
13
|
-
`;
|
|
14
|
-
|
|
15
|
-
exports[`format API formatRelativeTime() options handles missing named formats and warns 1`] = `
|
|
16
|
-
Array [
|
|
17
|
-
"UNSUPPORTED_FORMATTER",
|
|
18
|
-
]
|
|
19
|
-
`;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`format API formatTime() options falls back and warns on invalid Intl.DateTimeFormat options 1`] = `
|
|
4
|
-
Array [
|
|
5
|
-
"FORMAT_ERROR",
|
|
6
|
-
]
|
|
7
|
-
`;
|
|
8
|
-
|
|
9
|
-
exports[`format API formatTime() options handles missing named formats and warns 1`] = `
|
|
10
|
-
Array [
|
|
11
|
-
"UNSUPPORTED_FORMATTER",
|
|
12
|
-
]
|
|
13
|
-
`;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import {createIntl} from '../src/create-intl'
|
|
2
|
-
|
|
3
|
-
test('createIntl', function () {
|
|
4
|
-
const intl = createIntl({
|
|
5
|
-
locale: 'en',
|
|
6
|
-
messages: {
|
|
7
|
-
foo: 'bar',
|
|
8
|
-
},
|
|
9
|
-
})
|
|
10
|
-
expect(
|
|
11
|
-
intl.formatMessage({
|
|
12
|
-
id: 'foo',
|
|
13
|
-
})
|
|
14
|
-
).toBe('bar')
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
test('should warn when defaultRichTextElements is used with messages', function () {
|
|
18
|
-
const onWarn = jest.fn()
|
|
19
|
-
createIntl({
|
|
20
|
-
locale: 'en',
|
|
21
|
-
messages: {
|
|
22
|
-
foo: 'bar',
|
|
23
|
-
},
|
|
24
|
-
defaultRichTextElements: {},
|
|
25
|
-
onWarn,
|
|
26
|
-
})
|
|
27
|
-
expect(onWarn).toHaveBeenCalledWith(
|
|
28
|
-
expect.stringContaining(
|
|
29
|
-
`defaultRichTextElements" was specified but "message" was not pre-compiled.`
|
|
30
|
-
)
|
|
31
|
-
)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
test('should not warn when defaultRichTextElements is not used', function () {
|
|
35
|
-
const onWarn = jest.fn()
|
|
36
|
-
createIntl({
|
|
37
|
-
locale: 'en',
|
|
38
|
-
messages: {
|
|
39
|
-
foo: 'bar',
|
|
40
|
-
},
|
|
41
|
-
onWarn,
|
|
42
|
-
})
|
|
43
|
-
expect(onWarn).not.toHaveBeenCalled()
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
test('should use the default warn handler when none is passed', function () {
|
|
47
|
-
const warnFn = jest.spyOn(console, 'warn')
|
|
48
|
-
createIntl({
|
|
49
|
-
locale: 'en',
|
|
50
|
-
messages: {
|
|
51
|
-
foo: 'bar',
|
|
52
|
-
},
|
|
53
|
-
defaultRichTextElements: {},
|
|
54
|
-
})
|
|
55
|
-
expect(warnFn).toHaveBeenCalledWith(
|
|
56
|
-
expect.stringContaining(
|
|
57
|
-
`defaultRichTextElements" was specified but "message" was not pre-compiled.`
|
|
58
|
-
)
|
|
59
|
-
)
|
|
60
|
-
})
|
package/tests/error.test.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import {MissingTranslationError} from '../src/error'
|
|
2
|
-
|
|
3
|
-
describe('MissingTranslationError', () => {
|
|
4
|
-
it('records the actual default message', () => {
|
|
5
|
-
const e = new MissingTranslationError(
|
|
6
|
-
{defaultMessage: 'some message'},
|
|
7
|
-
'en'
|
|
8
|
-
)
|
|
9
|
-
expect(e.toString()).toMatch(/default message \(some message\)/)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
it('records the actual default message for MessageFormatElement[]', () => {
|
|
13
|
-
// this works for all `MessageFormatElement` except for `PoundElement`
|
|
14
|
-
const e = new MissingTranslationError(
|
|
15
|
-
{defaultMessage: [{type: 0, value: 'some message'}]},
|
|
16
|
-
'en'
|
|
17
|
-
)
|
|
18
|
-
expect(e.toString()).toMatch(/default message \(some message\)/)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('records the actual default message for PoundElement[]', () => {
|
|
22
|
-
const e = new MissingTranslationError({defaultMessage: [{type: 7}]}, 'en')
|
|
23
|
-
expect(e.toString()).toMatch(/default message \(\{"type":7\}\)/)
|
|
24
|
-
})
|
|
25
|
-
})
|
package/tests/formatDate.test.ts
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
2
|
-
import {formatDate as formatDateFn} from '../src/dateTime'
|
|
3
|
-
import {IntlConfig, IntlFormatters} from '../src/types'
|
|
4
|
-
|
|
5
|
-
describe('format API', () => {
|
|
6
|
-
const {NODE_ENV} = process.env
|
|
7
|
-
|
|
8
|
-
let config: IntlConfig<any>
|
|
9
|
-
|
|
10
|
-
let getDateTimeFormat: any
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
config = {
|
|
13
|
-
locale: 'en',
|
|
14
|
-
|
|
15
|
-
messages: {},
|
|
16
|
-
|
|
17
|
-
formats: {
|
|
18
|
-
date: {
|
|
19
|
-
'year-only': {
|
|
20
|
-
year: 'numeric',
|
|
21
|
-
},
|
|
22
|
-
missing: undefined,
|
|
23
|
-
},
|
|
24
|
-
} as any,
|
|
25
|
-
|
|
26
|
-
defaultLocale: 'en',
|
|
27
|
-
defaultFormats: {},
|
|
28
|
-
|
|
29
|
-
onError: jest.fn(),
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
getDateTimeFormat = jest
|
|
33
|
-
.fn()
|
|
34
|
-
.mockImplementation((...args) => new Intl.DateTimeFormat(...args))
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
afterEach(() => {
|
|
38
|
-
process.env.NODE_ENV = NODE_ENV
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
describe('formatDate()', () => {
|
|
42
|
-
let df: Intl.DateTimeFormat
|
|
43
|
-
let formatDate: IntlFormatters['formatDate']
|
|
44
|
-
|
|
45
|
-
beforeEach(() => {
|
|
46
|
-
df = new Intl.DateTimeFormat(config.locale)
|
|
47
|
-
|
|
48
|
-
// @ts-ignore
|
|
49
|
-
formatDate = formatDateFn.bind(null, config, getDateTimeFormat)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('no value should render today', () => {
|
|
53
|
-
// @ts-ignore
|
|
54
|
-
expect(formatDate()).toBe(df.format())
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('falls back and warns when a non-finite value is provided', () => {
|
|
58
|
-
expect(formatDate(NaN)).toBe('NaN')
|
|
59
|
-
expect(config.onError as jest.Mock).toHaveBeenCalledTimes(1)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('formats falsy finite values', () => {
|
|
63
|
-
// @ts-ignore
|
|
64
|
-
expect(formatDate(null)).toBe(df.format(null))
|
|
65
|
-
expect(formatDate(0)).toBe(df.format(0))
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
it('formats date instance values', () => {
|
|
69
|
-
expect(formatDate(new Date(0))).toBe(df.format(new Date(0)))
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('formats date string values', () => {
|
|
73
|
-
expect(formatDate(new Date(0).toString())).toBe(df.format(0))
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('formats date ms timestamp values', () => {
|
|
77
|
-
const timestamp = Date.now()
|
|
78
|
-
expect(formatDate(timestamp)).toBe(df.format(timestamp))
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('uses the time zone specified by the provider', () => {
|
|
82
|
-
const timestamp = Date.now()
|
|
83
|
-
config.timeZone = 'Pacific/Wake'
|
|
84
|
-
// @ts-ignore
|
|
85
|
-
formatDate = formatDateFn.bind(null, config, getDateTimeFormat)
|
|
86
|
-
const wakeDf = new Intl.DateTimeFormat(config.locale, {
|
|
87
|
-
timeZone: 'Pacific/Wake',
|
|
88
|
-
})
|
|
89
|
-
expect(formatDate(timestamp)).toBe(wakeDf.format(timestamp))
|
|
90
|
-
config.timeZone = 'Asia/Shanghai'
|
|
91
|
-
|
|
92
|
-
// @ts-ignore
|
|
93
|
-
formatDate = formatDateFn.bind(null, config, getDateTimeFormat)
|
|
94
|
-
const shanghaiDf = new Intl.DateTimeFormat(config.locale, {
|
|
95
|
-
timeZone: 'Asia/Shanghai',
|
|
96
|
-
})
|
|
97
|
-
expect(formatDate(timestamp)).toBe(shanghaiDf.format(timestamp))
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
describe('options', () => {
|
|
101
|
-
it('accepts empty options', () => {
|
|
102
|
-
expect(formatDate(0, {})).toBe(df.format(0))
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('accepts valid Intl.DateTimeFormat options', () => {
|
|
106
|
-
expect(() => formatDate(0, {year: 'numeric'})).not.toThrow()
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('falls back and warns on invalid Intl.DateTimeFormat options', () => {
|
|
110
|
-
// @ts-expect-error invalid year just for testing
|
|
111
|
-
expect(formatDate(0, {year: 'invalid'})).toBe('0')
|
|
112
|
-
expect(
|
|
113
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
114
|
-
).toMatchSnapshot()
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('uses configured named formats', () => {
|
|
118
|
-
const date = new Date()
|
|
119
|
-
const format = 'year-only'
|
|
120
|
-
|
|
121
|
-
const {locale, formats} = config
|
|
122
|
-
df = new Intl.DateTimeFormat(locale, formats!.date![format])
|
|
123
|
-
|
|
124
|
-
expect(formatDate(date, {format})).toBe(df.format(date))
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('uses named formats as defaults', () => {
|
|
128
|
-
const date = new Date()
|
|
129
|
-
const opts: Intl.DateTimeFormatOptions = {month: 'numeric'}
|
|
130
|
-
const format = 'year-only'
|
|
131
|
-
|
|
132
|
-
const {locale, formats} = config
|
|
133
|
-
df = new Intl.DateTimeFormat(locale, {
|
|
134
|
-
...opts,
|
|
135
|
-
...formats!.date![format],
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
expect(formatDate(date, {...opts, format})).toBe(df.format(date))
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
it('handles missing named formats and warns', () => {
|
|
142
|
-
const date = new Date()
|
|
143
|
-
const format = 'missing'
|
|
144
|
-
|
|
145
|
-
df = new Intl.DateTimeFormat(config.locale)
|
|
146
|
-
|
|
147
|
-
expect(formatDate(date, {format})).toBe(df.format(date))
|
|
148
|
-
expect(
|
|
149
|
-
(config.onError as jest.Mock).mock.calls.map(c => c[0].code)
|
|
150
|
-
).toMatchSnapshot()
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
it('uses time zone specified in options over the one passed through by the provider', () => {
|
|
154
|
-
const timestamp = Date.now()
|
|
155
|
-
config.timeZone = 'Pacific/Wake'
|
|
156
|
-
// @ts-ignore
|
|
157
|
-
formatDate = formatDateFn.bind(null, config, getDateTimeFormat)
|
|
158
|
-
const shanghaiDf = new Intl.DateTimeFormat(config.locale, {
|
|
159
|
-
timeZone: 'Asia/Shanghai',
|
|
160
|
-
})
|
|
161
|
-
expect(formatDate(timestamp, {timeZone: 'Asia/Shanghai'})).toBe(
|
|
162
|
-
shanghaiDf.format(timestamp)
|
|
163
|
-
)
|
|
164
|
-
})
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
})
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
2
|
-
import '@formatjs/intl-displaynames/polyfill'
|
|
3
|
-
import '@formatjs/intl-displaynames/locale-data/en'
|
|
4
|
-
import '@formatjs/intl-displaynames/locale-data/zh-Hans-SG'
|
|
5
|
-
import {formatDisplayName as formatDisplayNameFn} from '../src/displayName'
|
|
6
|
-
import {IntlConfig, IntlFormatters} from '../src/types'
|
|
7
|
-
|
|
8
|
-
describe('format API', () => {
|
|
9
|
-
const {NODE_ENV} = process.env
|
|
10
|
-
|
|
11
|
-
let config: IntlConfig<any>
|
|
12
|
-
let getDisplayNames: any
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
config = {
|
|
15
|
-
locale: 'en',
|
|
16
|
-
|
|
17
|
-
messages: {},
|
|
18
|
-
|
|
19
|
-
defaultLocale: 'en',
|
|
20
|
-
defaultFormats: {},
|
|
21
|
-
|
|
22
|
-
onError: jest.fn(),
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
getDisplayNames = jest
|
|
26
|
-
.fn()
|
|
27
|
-
.mockImplementation((...args) => new (Intl as any).DisplayNames(...args))
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
process.env.NODE_ENV = NODE_ENV
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
describe('formatDisplayNames()', function () {
|
|
35
|
-
let formatDisplayName!: IntlFormatters['formatDisplayName']
|
|
36
|
-
|
|
37
|
-
beforeEach(() => {
|
|
38
|
-
// @ts-ignore
|
|
39
|
-
formatDisplayName = formatDisplayNameFn.bind(
|
|
40
|
-
null,
|
|
41
|
-
config,
|
|
42
|
-
getDisplayNames
|
|
43
|
-
)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('should return locale display name as string', function () {
|
|
47
|
-
expect(formatDisplayName('zh-Hans-SG', {type: 'language'})).toBe(
|
|
48
|
-
'Simplified Chinese (Singapore)'
|
|
49
|
-
)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('will return undefined if Intl.DisplayName would return undefined', function () {
|
|
53
|
-
const displayName = new (Intl as any).DisplayNames('en', {
|
|
54
|
-
type: 'language',
|
|
55
|
-
fallback: 'none',
|
|
56
|
-
})
|
|
57
|
-
expect(displayName.of('xx-XX')).toBeUndefined()
|
|
58
|
-
expect(
|
|
59
|
-
formatDisplayName('xx-XX', {type: 'language', fallback: 'none'})
|
|
60
|
-
).toBeUndefined()
|
|
61
|
-
})
|
|
62
|
-
})
|
|
63
|
-
})
|
package/tests/formatList.test.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/camelcase */
|
|
2
|
-
import {formatList as formatListFn} from '../src/list'
|
|
3
|
-
|
|
4
|
-
import {IntlConfig, IntlFormatters} from '../src/types'
|
|
5
|
-
|
|
6
|
-
describe('format API', () => {
|
|
7
|
-
const {NODE_ENV} = process.env
|
|
8
|
-
|
|
9
|
-
let config: IntlConfig<any>
|
|
10
|
-
let getListFormat: any
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
config = {
|
|
13
|
-
locale: 'en',
|
|
14
|
-
|
|
15
|
-
messages: {},
|
|
16
|
-
|
|
17
|
-
defaultLocale: 'en',
|
|
18
|
-
defaultFormats: {},
|
|
19
|
-
|
|
20
|
-
onError: jest.fn(),
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
getListFormat = jest
|
|
24
|
-
.fn()
|
|
25
|
-
.mockImplementation((...args) => new Intl.ListFormat(...args))
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
afterEach(() => {
|
|
29
|
-
process.env.NODE_ENV = NODE_ENV
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
describe('formatList()', function () {
|
|
33
|
-
let formatList: IntlFormatters['formatList']
|
|
34
|
-
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
// @ts-ignore
|
|
37
|
-
formatList = formatListFn.bind(null, config, getListFormat)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('should handle regular element', function () {
|
|
41
|
-
expect(formatList(['me', 'myself', 'I'])).toBe('me, myself, and I')
|
|
42
|
-
})
|
|
43
|
-
it('should handle regular element', function () {
|
|
44
|
-
expect(formatList(['me', {foo: 'myself'}, 'I'])).toEqual([
|
|
45
|
-
'me, ',
|
|
46
|
-
{foo: 'myself'},
|
|
47
|
-
', and I',
|
|
48
|
-
])
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
})
|