@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/message.ts
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import {invariant} from '@formatjs/ecma402-abstract'
|
|
2
|
-
|
|
3
|
-
import {Formatters, MessageDescriptor, CustomFormats, OnErrorFn} from './types'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
IntlMessageFormat,
|
|
7
|
-
FormatXMLElementFn,
|
|
8
|
-
PrimitiveType,
|
|
9
|
-
Formatters as IntlMessageFormatFormatters,
|
|
10
|
-
Options,
|
|
11
|
-
} from 'intl-messageformat'
|
|
12
|
-
import {MissingTranslationError, MessageFormatError} from './error'
|
|
13
|
-
import {TYPE, MessageFormatElement} from '@formatjs/icu-messageformat-parser'
|
|
14
|
-
|
|
15
|
-
function setTimeZoneInOptions(
|
|
16
|
-
opts: Record<string, Intl.DateTimeFormatOptions>,
|
|
17
|
-
timeZone: string
|
|
18
|
-
): Record<string, Intl.DateTimeFormatOptions> {
|
|
19
|
-
return Object.keys(opts).reduce(
|
|
20
|
-
(all: Record<string, Intl.DateTimeFormatOptions>, k) => {
|
|
21
|
-
all[k] = {
|
|
22
|
-
timeZone,
|
|
23
|
-
...opts[k],
|
|
24
|
-
}
|
|
25
|
-
return all
|
|
26
|
-
},
|
|
27
|
-
{}
|
|
28
|
-
)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function deepMergeOptions(
|
|
32
|
-
opts1: Record<string, Intl.DateTimeFormatOptions>,
|
|
33
|
-
opts2: Record<string, Intl.DateTimeFormatOptions>
|
|
34
|
-
): Record<string, Intl.DateTimeFormatOptions> {
|
|
35
|
-
const keys = Object.keys({...opts1, ...opts2})
|
|
36
|
-
return keys.reduce((all: Record<string, Intl.DateTimeFormatOptions>, k) => {
|
|
37
|
-
all[k] = {
|
|
38
|
-
...(opts1[k] || {}),
|
|
39
|
-
...(opts2[k] || {}),
|
|
40
|
-
}
|
|
41
|
-
return all
|
|
42
|
-
}, {})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function deepMergeFormatsAndSetTimeZone(
|
|
46
|
-
f1: CustomFormats,
|
|
47
|
-
timeZone?: string
|
|
48
|
-
): CustomFormats {
|
|
49
|
-
if (!timeZone) {
|
|
50
|
-
return f1
|
|
51
|
-
}
|
|
52
|
-
const mfFormats = IntlMessageFormat.formats
|
|
53
|
-
return {
|
|
54
|
-
...mfFormats,
|
|
55
|
-
...f1,
|
|
56
|
-
date: deepMergeOptions(
|
|
57
|
-
setTimeZoneInOptions(mfFormats.date, timeZone),
|
|
58
|
-
setTimeZoneInOptions(f1.date || {}, timeZone)
|
|
59
|
-
),
|
|
60
|
-
time: deepMergeOptions(
|
|
61
|
-
setTimeZoneInOptions(mfFormats.time, timeZone),
|
|
62
|
-
setTimeZoneInOptions(f1.time || {}, timeZone)
|
|
63
|
-
),
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export type FormatMessageFn<T> = (
|
|
68
|
-
{
|
|
69
|
-
locale,
|
|
70
|
-
formats,
|
|
71
|
-
messages,
|
|
72
|
-
defaultLocale,
|
|
73
|
-
defaultFormats,
|
|
74
|
-
fallbackOnEmptyString,
|
|
75
|
-
onError,
|
|
76
|
-
timeZone,
|
|
77
|
-
defaultRichTextElements,
|
|
78
|
-
}: {
|
|
79
|
-
locale: string
|
|
80
|
-
timeZone?: string
|
|
81
|
-
formats: CustomFormats
|
|
82
|
-
messages: Record<string, string> | Record<string, MessageFormatElement[]>
|
|
83
|
-
defaultLocale: string
|
|
84
|
-
defaultFormats: CustomFormats
|
|
85
|
-
defaultRichTextElements?: Record<string, FormatXMLElementFn<T>>
|
|
86
|
-
fallbackOnEmptyString?: boolean
|
|
87
|
-
onError: OnErrorFn
|
|
88
|
-
},
|
|
89
|
-
state: IntlMessageFormatFormatters & Pick<Formatters, 'getMessageFormat'>,
|
|
90
|
-
messageDescriptor: MessageDescriptor,
|
|
91
|
-
values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T>>,
|
|
92
|
-
opts?: Options
|
|
93
|
-
) => T extends string ? string : Array<T | string> | string | T
|
|
94
|
-
|
|
95
|
-
export const formatMessage: FormatMessageFn<any> = (
|
|
96
|
-
{
|
|
97
|
-
locale,
|
|
98
|
-
formats,
|
|
99
|
-
messages,
|
|
100
|
-
defaultLocale,
|
|
101
|
-
defaultFormats,
|
|
102
|
-
fallbackOnEmptyString,
|
|
103
|
-
onError,
|
|
104
|
-
timeZone,
|
|
105
|
-
defaultRichTextElements,
|
|
106
|
-
},
|
|
107
|
-
state,
|
|
108
|
-
messageDescriptor = {id: ''},
|
|
109
|
-
values,
|
|
110
|
-
opts
|
|
111
|
-
) => {
|
|
112
|
-
const {id: msgId, defaultMessage} = messageDescriptor
|
|
113
|
-
|
|
114
|
-
// `id` is a required field of a Message Descriptor.
|
|
115
|
-
invariant(
|
|
116
|
-
!!msgId,
|
|
117
|
-
`[@formatjs/intl] An \`id\` must be provided to format a message. You can either:
|
|
118
|
-
1. Configure your build toolchain with [babel-plugin-formatjs](https://formatjs.io/docs/tooling/babel-plugin)
|
|
119
|
-
or [@formatjs/ts-transformer](https://formatjs.io/docs/tooling/ts-transformer) OR
|
|
120
|
-
2. Configure your \`eslint\` config to include [eslint-plugin-formatjs](https://formatjs.io/docs/tooling/linter#enforce-id)
|
|
121
|
-
to autofix this issue`
|
|
122
|
-
)
|
|
123
|
-
const id = String(msgId)
|
|
124
|
-
const message =
|
|
125
|
-
// In case messages is Object.create(null)
|
|
126
|
-
// e.g import('foo.json') from webpack)
|
|
127
|
-
// See https://github.com/formatjs/formatjs/issues/1914
|
|
128
|
-
messages &&
|
|
129
|
-
Object.prototype.hasOwnProperty.call(messages, id) &&
|
|
130
|
-
messages[id]
|
|
131
|
-
|
|
132
|
-
// IMPORTANT: Hot path if `message` is AST with a single literal node
|
|
133
|
-
if (
|
|
134
|
-
Array.isArray(message) &&
|
|
135
|
-
message.length === 1 &&
|
|
136
|
-
message[0].type === TYPE.literal
|
|
137
|
-
) {
|
|
138
|
-
return message[0].value
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// IMPORTANT: Hot path straight lookup for performance
|
|
142
|
-
if (
|
|
143
|
-
!values &&
|
|
144
|
-
message &&
|
|
145
|
-
typeof message === 'string' &&
|
|
146
|
-
!defaultRichTextElements
|
|
147
|
-
) {
|
|
148
|
-
return message.replace(/'\{(.*?)\}'/gi, `{$1}`)
|
|
149
|
-
}
|
|
150
|
-
values = {
|
|
151
|
-
...defaultRichTextElements,
|
|
152
|
-
...(values || {}),
|
|
153
|
-
}
|
|
154
|
-
formats = deepMergeFormatsAndSetTimeZone(formats, timeZone)
|
|
155
|
-
defaultFormats = deepMergeFormatsAndSetTimeZone(defaultFormats, timeZone)
|
|
156
|
-
|
|
157
|
-
if (!message) {
|
|
158
|
-
if (fallbackOnEmptyString === false && message === '') {
|
|
159
|
-
return message
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (
|
|
163
|
-
!defaultMessage ||
|
|
164
|
-
(locale && locale.toLowerCase() !== defaultLocale.toLowerCase())
|
|
165
|
-
) {
|
|
166
|
-
// This prevents warnings from littering the console in development
|
|
167
|
-
// when no `messages` are passed into the <IntlProvider> for the
|
|
168
|
-
// default locale.
|
|
169
|
-
onError(new MissingTranslationError(messageDescriptor, locale))
|
|
170
|
-
}
|
|
171
|
-
if (defaultMessage) {
|
|
172
|
-
try {
|
|
173
|
-
const formatter = state.getMessageFormat(
|
|
174
|
-
defaultMessage,
|
|
175
|
-
defaultLocale,
|
|
176
|
-
defaultFormats,
|
|
177
|
-
opts
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
return formatter.format(values)
|
|
181
|
-
} catch (e) {
|
|
182
|
-
onError(
|
|
183
|
-
new MessageFormatError(
|
|
184
|
-
`Error formatting default message for: "${id}", rendering default message verbatim`,
|
|
185
|
-
locale,
|
|
186
|
-
messageDescriptor,
|
|
187
|
-
e
|
|
188
|
-
)
|
|
189
|
-
)
|
|
190
|
-
return typeof defaultMessage === 'string' ? defaultMessage : id
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return id
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// We have the translated message
|
|
197
|
-
try {
|
|
198
|
-
const formatter = state.getMessageFormat(message, locale, formats, {
|
|
199
|
-
formatters: state,
|
|
200
|
-
...(opts || {}),
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
return formatter.format<any>(values)
|
|
204
|
-
} catch (e) {
|
|
205
|
-
onError(
|
|
206
|
-
new MessageFormatError(
|
|
207
|
-
`Error formatting message: "${id}", using ${
|
|
208
|
-
defaultMessage ? 'default message' : 'id'
|
|
209
|
-
} as fallback.`,
|
|
210
|
-
locale,
|
|
211
|
-
messageDescriptor,
|
|
212
|
-
e
|
|
213
|
-
)
|
|
214
|
-
)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (defaultMessage) {
|
|
218
|
-
try {
|
|
219
|
-
const formatter = state.getMessageFormat(
|
|
220
|
-
defaultMessage,
|
|
221
|
-
defaultLocale,
|
|
222
|
-
defaultFormats,
|
|
223
|
-
opts
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
return formatter.format(values)
|
|
227
|
-
} catch (e) {
|
|
228
|
-
onError(
|
|
229
|
-
new MessageFormatError(
|
|
230
|
-
`Error formatting the default message for: "${id}", rendering message verbatim`,
|
|
231
|
-
locale,
|
|
232
|
-
messageDescriptor,
|
|
233
|
-
e
|
|
234
|
-
)
|
|
235
|
-
)
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (typeof message === 'string') {
|
|
240
|
-
return message
|
|
241
|
-
}
|
|
242
|
-
if (typeof defaultMessage === 'string') {
|
|
243
|
-
return defaultMessage
|
|
244
|
-
}
|
|
245
|
-
return id
|
|
246
|
-
}
|
package/src/number.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import {Formatters, IntlFormatters, CustomFormats, OnErrorFn} from './types'
|
|
2
|
-
import {getNamedFormat, filterProps} from './utils'
|
|
3
|
-
import {IntlError, IntlErrorCode} from './error'
|
|
4
|
-
import {NumberFormatOptions} from '@formatjs/ecma402-abstract'
|
|
5
|
-
|
|
6
|
-
const NUMBER_FORMAT_OPTIONS: Array<keyof NumberFormatOptions> = [
|
|
7
|
-
'style',
|
|
8
|
-
'currency',
|
|
9
|
-
'currencyDisplay',
|
|
10
|
-
'unit',
|
|
11
|
-
'unitDisplay',
|
|
12
|
-
'useGrouping',
|
|
13
|
-
|
|
14
|
-
'minimumIntegerDigits',
|
|
15
|
-
'minimumFractionDigits',
|
|
16
|
-
'maximumFractionDigits',
|
|
17
|
-
'minimumSignificantDigits',
|
|
18
|
-
'maximumSignificantDigits',
|
|
19
|
-
|
|
20
|
-
// ES2020 NumberFormat
|
|
21
|
-
'compactDisplay',
|
|
22
|
-
'currencyDisplay',
|
|
23
|
-
'currencySign',
|
|
24
|
-
'notation',
|
|
25
|
-
'signDisplay',
|
|
26
|
-
'unit',
|
|
27
|
-
'unitDisplay',
|
|
28
|
-
'numberingSystem',
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
export function getFormatter(
|
|
32
|
-
{
|
|
33
|
-
locale,
|
|
34
|
-
formats,
|
|
35
|
-
onError,
|
|
36
|
-
}: {
|
|
37
|
-
locale: string
|
|
38
|
-
|
|
39
|
-
formats: CustomFormats
|
|
40
|
-
onError: OnErrorFn
|
|
41
|
-
},
|
|
42
|
-
getNumberFormat: Formatters['getNumberFormat'],
|
|
43
|
-
options: Parameters<IntlFormatters['formatNumber']>[1] = {}
|
|
44
|
-
): Intl.NumberFormat {
|
|
45
|
-
const {format} = options
|
|
46
|
-
const defaults = ((format &&
|
|
47
|
-
getNamedFormat(formats!, 'number', format, onError)) ||
|
|
48
|
-
{}) as NumberFormatOptions
|
|
49
|
-
const filteredOptions = filterProps(
|
|
50
|
-
options,
|
|
51
|
-
NUMBER_FORMAT_OPTIONS,
|
|
52
|
-
defaults
|
|
53
|
-
) as NumberFormatOptions
|
|
54
|
-
|
|
55
|
-
return getNumberFormat(locale, filteredOptions)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function formatNumber(
|
|
59
|
-
config: {
|
|
60
|
-
locale: string
|
|
61
|
-
|
|
62
|
-
formats: CustomFormats
|
|
63
|
-
onError: OnErrorFn
|
|
64
|
-
},
|
|
65
|
-
getNumberFormat: Formatters['getNumberFormat'],
|
|
66
|
-
value: Parameters<IntlFormatters['formatNumber']>[0],
|
|
67
|
-
options: Parameters<IntlFormatters['formatNumber']>[1] = {}
|
|
68
|
-
): string {
|
|
69
|
-
try {
|
|
70
|
-
return getFormatter(config, getNumberFormat, options).format(value)
|
|
71
|
-
} catch (e) {
|
|
72
|
-
config.onError(
|
|
73
|
-
new IntlError(IntlErrorCode.FORMAT_ERROR, 'Error formatting number.', e)
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return String(value)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function formatNumberToParts(
|
|
81
|
-
config: {
|
|
82
|
-
locale: string
|
|
83
|
-
formats: CustomFormats
|
|
84
|
-
onError: OnErrorFn
|
|
85
|
-
},
|
|
86
|
-
getNumberFormat: Formatters['getNumberFormat'],
|
|
87
|
-
value: Parameters<IntlFormatters['formatNumber']>[0],
|
|
88
|
-
options: Parameters<IntlFormatters['formatNumber']>[1] = {}
|
|
89
|
-
): Intl.NumberFormatPart[] {
|
|
90
|
-
try {
|
|
91
|
-
return getFormatter(config, getNumberFormat, options).formatToParts(
|
|
92
|
-
value as number
|
|
93
|
-
)
|
|
94
|
-
} catch (e) {
|
|
95
|
-
config.onError(
|
|
96
|
-
new IntlError(IntlErrorCode.FORMAT_ERROR, 'Error formatting number.', e)
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return []
|
|
101
|
-
}
|
package/src/plural.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {Formatters, IntlFormatters, OnErrorFn} from './types'
|
|
2
|
-
import {filterProps} from './utils'
|
|
3
|
-
import {IntlFormatError} from './error'
|
|
4
|
-
import {ErrorCode, FormatError} from 'intl-messageformat'
|
|
5
|
-
import {LDMLPluralRule} from '@formatjs/ecma402-abstract'
|
|
6
|
-
|
|
7
|
-
const PLURAL_FORMAT_OPTIONS: Array<keyof Intl.PluralRulesOptions> = ['type']
|
|
8
|
-
|
|
9
|
-
export function formatPlural(
|
|
10
|
-
{
|
|
11
|
-
locale,
|
|
12
|
-
onError,
|
|
13
|
-
}: {
|
|
14
|
-
locale: string
|
|
15
|
-
onError: OnErrorFn
|
|
16
|
-
},
|
|
17
|
-
getPluralRules: Formatters['getPluralRules'],
|
|
18
|
-
value: Parameters<IntlFormatters['formatPlural']>[0],
|
|
19
|
-
options: Parameters<IntlFormatters['formatPlural']>[1] = {}
|
|
20
|
-
): LDMLPluralRule {
|
|
21
|
-
if (!Intl.PluralRules) {
|
|
22
|
-
onError(
|
|
23
|
-
new FormatError(
|
|
24
|
-
`Intl.PluralRules is not available in this environment.
|
|
25
|
-
Try polyfilling it using "@formatjs/intl-pluralrules"
|
|
26
|
-
`,
|
|
27
|
-
ErrorCode.MISSING_INTL_API
|
|
28
|
-
)
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
const filteredOptions = filterProps(
|
|
32
|
-
options,
|
|
33
|
-
PLURAL_FORMAT_OPTIONS
|
|
34
|
-
) as Intl.PluralRulesOptions
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
return getPluralRules(locale, filteredOptions).select(
|
|
38
|
-
value
|
|
39
|
-
) as LDMLPluralRule
|
|
40
|
-
} catch (e) {
|
|
41
|
-
onError(new IntlFormatError('Error formatting plural.', locale, e))
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return 'other'
|
|
45
|
-
}
|
package/src/relativeTime.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {IntlFormatters, Formatters, CustomFormats, OnErrorFn} from './types'
|
|
2
|
-
|
|
3
|
-
import {getNamedFormat, filterProps} from './utils'
|
|
4
|
-
import {FormatError, ErrorCode} from 'intl-messageformat'
|
|
5
|
-
import {IntlFormatError} from './error'
|
|
6
|
-
|
|
7
|
-
const RELATIVE_TIME_FORMAT_OPTIONS: Array<
|
|
8
|
-
keyof Intl.RelativeTimeFormatOptions
|
|
9
|
-
> = ['numeric', 'style']
|
|
10
|
-
|
|
11
|
-
function getFormatter(
|
|
12
|
-
{
|
|
13
|
-
locale,
|
|
14
|
-
formats,
|
|
15
|
-
onError,
|
|
16
|
-
}: {
|
|
17
|
-
locale: string
|
|
18
|
-
formats: CustomFormats
|
|
19
|
-
onError: OnErrorFn
|
|
20
|
-
},
|
|
21
|
-
getRelativeTimeFormat: Formatters['getRelativeTimeFormat'],
|
|
22
|
-
options: Parameters<IntlFormatters['formatRelativeTime']>[2] = {}
|
|
23
|
-
): Intl.RelativeTimeFormat {
|
|
24
|
-
const {format} = options
|
|
25
|
-
|
|
26
|
-
const defaults =
|
|
27
|
-
(!!format && getNamedFormat(formats, 'relative', format, onError)) || {}
|
|
28
|
-
const filteredOptions = filterProps(
|
|
29
|
-
options,
|
|
30
|
-
RELATIVE_TIME_FORMAT_OPTIONS,
|
|
31
|
-
defaults as Intl.RelativeTimeFormatOptions
|
|
32
|
-
) as Intl.RelativeTimeFormatOptions
|
|
33
|
-
|
|
34
|
-
return getRelativeTimeFormat(locale, filteredOptions)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function formatRelativeTime(
|
|
38
|
-
config: {
|
|
39
|
-
locale: string
|
|
40
|
-
formats: CustomFormats
|
|
41
|
-
onError: OnErrorFn
|
|
42
|
-
},
|
|
43
|
-
getRelativeTimeFormat: Formatters['getRelativeTimeFormat'],
|
|
44
|
-
value: Parameters<IntlFormatters['formatRelativeTime']>[0],
|
|
45
|
-
unit?: Parameters<IntlFormatters['formatRelativeTime']>[1],
|
|
46
|
-
options: Parameters<IntlFormatters['formatRelativeTime']>[2] = {}
|
|
47
|
-
): string {
|
|
48
|
-
if (!unit) {
|
|
49
|
-
unit = 'second'
|
|
50
|
-
}
|
|
51
|
-
const RelativeTimeFormat = Intl.RelativeTimeFormat
|
|
52
|
-
if (!RelativeTimeFormat) {
|
|
53
|
-
config.onError(
|
|
54
|
-
new FormatError(
|
|
55
|
-
`Intl.RelativeTimeFormat is not available in this environment.
|
|
56
|
-
Try polyfilling it using "@formatjs/intl-relativetimeformat"
|
|
57
|
-
`,
|
|
58
|
-
ErrorCode.MISSING_INTL_API
|
|
59
|
-
)
|
|
60
|
-
)
|
|
61
|
-
}
|
|
62
|
-
try {
|
|
63
|
-
return getFormatter(config, getRelativeTimeFormat, options).format(
|
|
64
|
-
value,
|
|
65
|
-
unit
|
|
66
|
-
)
|
|
67
|
-
} catch (e) {
|
|
68
|
-
config.onError(
|
|
69
|
-
new IntlFormatError('Error formatting relative time.', config.locale, e)
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return String(value)
|
|
74
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IntlMessageFormat,
|
|
3
|
-
Formats,
|
|
4
|
-
FormatXMLElementFn,
|
|
5
|
-
FormatError,
|
|
6
|
-
PrimitiveType,
|
|
7
|
-
Options as IntlMessageFormatOptions,
|
|
8
|
-
} from 'intl-messageformat'
|
|
9
|
-
import {DateTimeFormat} from '@formatjs/ecma402-abstract'
|
|
10
|
-
import {MessageFormatElement} from '@formatjs/icu-messageformat-parser'
|
|
11
|
-
import IntlListFormat, {
|
|
12
|
-
IntlListFormatOptions,
|
|
13
|
-
Part,
|
|
14
|
-
} from '@formatjs/intl-listformat'
|
|
15
|
-
import {DisplayNames, DisplayNamesOptions} from '@formatjs/intl-displaynames'
|
|
16
|
-
import {
|
|
17
|
-
MissingTranslationError,
|
|
18
|
-
MessageFormatError,
|
|
19
|
-
MissingDataError,
|
|
20
|
-
InvalidConfigError,
|
|
21
|
-
UnsupportedFormatterError,
|
|
22
|
-
} from './error'
|
|
23
|
-
import {DEFAULT_INTL_CONFIG} from './utils'
|
|
24
|
-
import {NumberFormatOptions} from '@formatjs/ecma402-abstract'
|
|
25
|
-
|
|
26
|
-
declare global {
|
|
27
|
-
namespace FormatjsIntl {
|
|
28
|
-
interface Message {}
|
|
29
|
-
interface IntlConfig {}
|
|
30
|
-
interface Formats {}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type MessageIds = FormatjsIntl.Message extends {ids: string}
|
|
35
|
-
? FormatjsIntl.Message['ids']
|
|
36
|
-
: string
|
|
37
|
-
|
|
38
|
-
type Locale = FormatjsIntl.IntlConfig extends {locale: string}
|
|
39
|
-
? FormatjsIntl.IntlConfig['locale']
|
|
40
|
-
: string
|
|
41
|
-
|
|
42
|
-
export type OnErrorFn = (
|
|
43
|
-
err:
|
|
44
|
-
| MissingTranslationError
|
|
45
|
-
| MessageFormatError
|
|
46
|
-
| MissingDataError
|
|
47
|
-
| InvalidConfigError
|
|
48
|
-
| UnsupportedFormatterError
|
|
49
|
-
| FormatError
|
|
50
|
-
) => void
|
|
51
|
-
|
|
52
|
-
export type OnWarnFn = (warning: string) => void
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Config for intl object.
|
|
56
|
-
* Generic type T is the type of potential rich text element. For example:
|
|
57
|
-
* With React, T would be React.ReactNode
|
|
58
|
-
*/
|
|
59
|
-
export interface ResolvedIntlConfig<T = string> {
|
|
60
|
-
locale: Locale
|
|
61
|
-
timeZone?: string
|
|
62
|
-
fallbackOnEmptyString?: boolean
|
|
63
|
-
formats: CustomFormats
|
|
64
|
-
messages:
|
|
65
|
-
| Record<MessageIds, string>
|
|
66
|
-
| Record<MessageIds, MessageFormatElement[]>
|
|
67
|
-
defaultLocale: string
|
|
68
|
-
defaultFormats: CustomFormats
|
|
69
|
-
defaultRichTextElements?: Record<string, FormatXMLElementFn<T>>
|
|
70
|
-
onError: OnErrorFn
|
|
71
|
-
onWarn?: OnWarnFn
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface CustomFormats extends Partial<Formats> {
|
|
75
|
-
relative?: Record<string, Intl.RelativeTimeFormatOptions>
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface CustomFormatConfig<Source = string> {
|
|
79
|
-
format?: Source extends keyof FormatjsIntl.Formats
|
|
80
|
-
? FormatjsIntl.Formats[Source]
|
|
81
|
-
: string
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export type FormatDateOptions = Omit<
|
|
85
|
-
Intl.DateTimeFormatOptions,
|
|
86
|
-
'localeMatcher'
|
|
87
|
-
> &
|
|
88
|
-
CustomFormatConfig<'date'>
|
|
89
|
-
export type FormatNumberOptions = Omit<NumberFormatOptions, 'localeMatcher'> &
|
|
90
|
-
CustomFormatConfig<'number'>
|
|
91
|
-
export type FormatRelativeTimeOptions = Omit<
|
|
92
|
-
Intl.RelativeTimeFormatOptions,
|
|
93
|
-
'localeMatcher'
|
|
94
|
-
> &
|
|
95
|
-
CustomFormatConfig<'time'>
|
|
96
|
-
export type FormatPluralOptions = Omit<
|
|
97
|
-
Intl.PluralRulesOptions,
|
|
98
|
-
'localeMatcher'
|
|
99
|
-
> &
|
|
100
|
-
CustomFormatConfig
|
|
101
|
-
|
|
102
|
-
export type FormatListOptions = Omit<IntlListFormatOptions, 'localeMatcher'>
|
|
103
|
-
|
|
104
|
-
export type FormatDisplayNameOptions = Omit<
|
|
105
|
-
DisplayNamesOptions,
|
|
106
|
-
'localeMatcher'
|
|
107
|
-
>
|
|
108
|
-
|
|
109
|
-
export interface IntlFormatters<T = any, R = T> {
|
|
110
|
-
formatDateTimeRange(
|
|
111
|
-
from: Parameters<DateTimeFormat['formatRange']>[0],
|
|
112
|
-
to: Parameters<DateTimeFormat['formatRange']>[1],
|
|
113
|
-
opts?: FormatDateOptions
|
|
114
|
-
): string
|
|
115
|
-
formatDate(
|
|
116
|
-
value: Parameters<Intl.DateTimeFormat['format']>[0] | string,
|
|
117
|
-
opts?: FormatDateOptions
|
|
118
|
-
): string
|
|
119
|
-
formatTime(
|
|
120
|
-
value: Parameters<Intl.DateTimeFormat['format']>[0] | string,
|
|
121
|
-
opts?: FormatDateOptions
|
|
122
|
-
): string
|
|
123
|
-
formatDateToParts(
|
|
124
|
-
value: Parameters<Intl.DateTimeFormat['format']>[0] | string,
|
|
125
|
-
opts?: FormatDateOptions
|
|
126
|
-
): Intl.DateTimeFormatPart[]
|
|
127
|
-
formatTimeToParts(
|
|
128
|
-
value: Parameters<Intl.DateTimeFormat['format']>[0] | string,
|
|
129
|
-
opts?: FormatDateOptions
|
|
130
|
-
): Intl.DateTimeFormatPart[]
|
|
131
|
-
formatRelativeTime(
|
|
132
|
-
value: Parameters<Intl.RelativeTimeFormat['format']>[0],
|
|
133
|
-
unit?: Parameters<Intl.RelativeTimeFormat['format']>[1],
|
|
134
|
-
opts?: FormatRelativeTimeOptions
|
|
135
|
-
): string
|
|
136
|
-
formatNumber(
|
|
137
|
-
value: Parameters<Intl.NumberFormat['format']>[0],
|
|
138
|
-
opts?: FormatNumberOptions
|
|
139
|
-
): string
|
|
140
|
-
formatNumberToParts(
|
|
141
|
-
value: Parameters<Intl.NumberFormat['format']>[0],
|
|
142
|
-
opts?: FormatNumberOptions
|
|
143
|
-
): Intl.NumberFormatPart[]
|
|
144
|
-
formatPlural(
|
|
145
|
-
value: Parameters<Intl.PluralRules['select']>[0],
|
|
146
|
-
opts?: FormatPluralOptions
|
|
147
|
-
): ReturnType<Intl.PluralRules['select']>
|
|
148
|
-
formatMessage(
|
|
149
|
-
descriptor: MessageDescriptor,
|
|
150
|
-
values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>,
|
|
151
|
-
opts?: IntlMessageFormatOptions
|
|
152
|
-
): string
|
|
153
|
-
formatMessage(
|
|
154
|
-
descriptor: MessageDescriptor,
|
|
155
|
-
values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T, R>>,
|
|
156
|
-
opts?: IntlMessageFormatOptions
|
|
157
|
-
): R
|
|
158
|
-
$t(
|
|
159
|
-
descriptor: MessageDescriptor,
|
|
160
|
-
values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>,
|
|
161
|
-
opts?: IntlMessageFormatOptions
|
|
162
|
-
): string
|
|
163
|
-
$t(
|
|
164
|
-
descriptor: MessageDescriptor,
|
|
165
|
-
values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T, R>>,
|
|
166
|
-
opts?: IntlMessageFormatOptions
|
|
167
|
-
): R
|
|
168
|
-
formatList(values: ReadonlyArray<string>, opts?: FormatListOptions): string
|
|
169
|
-
formatList(
|
|
170
|
-
values: ReadonlyArray<string | T>,
|
|
171
|
-
opts?: FormatListOptions
|
|
172
|
-
): T | string | Array<string | T>
|
|
173
|
-
formatListToParts(
|
|
174
|
-
values: ReadonlyArray<string | T>,
|
|
175
|
-
opts?: FormatListOptions
|
|
176
|
-
): Part[]
|
|
177
|
-
formatDisplayName(
|
|
178
|
-
value: Parameters<DisplayNames['of']>[0],
|
|
179
|
-
opts: FormatDisplayNameOptions
|
|
180
|
-
): string | undefined
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export interface Formatters {
|
|
184
|
-
getDateTimeFormat(
|
|
185
|
-
...args: ConstructorParameters<typeof Intl.DateTimeFormat>
|
|
186
|
-
): DateTimeFormat
|
|
187
|
-
getNumberFormat(
|
|
188
|
-
locales?: string | string[],
|
|
189
|
-
opts?: NumberFormatOptions
|
|
190
|
-
): Intl.NumberFormat
|
|
191
|
-
getMessageFormat(
|
|
192
|
-
...args: ConstructorParameters<typeof IntlMessageFormat>
|
|
193
|
-
): IntlMessageFormat
|
|
194
|
-
getRelativeTimeFormat(
|
|
195
|
-
...args: ConstructorParameters<typeof Intl.RelativeTimeFormat>
|
|
196
|
-
): Intl.RelativeTimeFormat
|
|
197
|
-
getPluralRules(
|
|
198
|
-
...args: ConstructorParameters<typeof Intl.PluralRules>
|
|
199
|
-
): Intl.PluralRules
|
|
200
|
-
getListFormat(
|
|
201
|
-
...args: ConstructorParameters<typeof IntlListFormat>
|
|
202
|
-
): IntlListFormat
|
|
203
|
-
getDisplayNames(
|
|
204
|
-
...args: ConstructorParameters<typeof DisplayNames>
|
|
205
|
-
): DisplayNames
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export interface IntlShape<T = string>
|
|
209
|
-
extends ResolvedIntlConfig<T>,
|
|
210
|
-
IntlFormatters {
|
|
211
|
-
formatters: Formatters
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export interface IntlCache {
|
|
215
|
-
dateTime: Record<string, DateTimeFormat>
|
|
216
|
-
number: Record<string, Intl.NumberFormat>
|
|
217
|
-
message: Record<string, IntlMessageFormat>
|
|
218
|
-
relativeTime: Record<string, Intl.RelativeTimeFormat>
|
|
219
|
-
pluralRules: Record<string, Intl.PluralRules>
|
|
220
|
-
list: Record<string, IntlListFormat>
|
|
221
|
-
displayNames: Record<string, DisplayNames>
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export interface MessageDescriptor {
|
|
225
|
-
id?: MessageIds
|
|
226
|
-
description?: string | object
|
|
227
|
-
defaultMessage?: string | MessageFormatElement[]
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export type IntlConfig<T = string> = Omit<
|
|
231
|
-
ResolvedIntlConfig<T>,
|
|
232
|
-
keyof typeof DEFAULT_INTL_CONFIG
|
|
233
|
-
> &
|
|
234
|
-
Partial<typeof DEFAULT_INTL_CONFIG>
|