@formatjs/intl 2.3.2 → 2.3.4
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 +9 -9
- 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/create-intl.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import {IntlCache, IntlShape, IntlConfig, ResolvedIntlConfig} from './types'
|
|
2
|
-
import {createFormatters, DEFAULT_INTL_CONFIG} from './utils'
|
|
3
|
-
import {InvalidConfigError, MissingDataError} from './error'
|
|
4
|
-
import {formatNumber, formatNumberToParts} from './number'
|
|
5
|
-
import {formatRelativeTime} from './relativeTime'
|
|
6
|
-
import {
|
|
7
|
-
formatDate,
|
|
8
|
-
formatDateToParts,
|
|
9
|
-
formatTime,
|
|
10
|
-
formatTimeToParts,
|
|
11
|
-
formatDateTimeRange,
|
|
12
|
-
} from './dateTime'
|
|
13
|
-
import {formatPlural} from './plural'
|
|
14
|
-
import {formatMessage} from './message'
|
|
15
|
-
import {formatList, formatListToParts} from './list'
|
|
16
|
-
import {formatDisplayName} from './displayName'
|
|
17
|
-
import {MessageFormatElement} from '@formatjs/icu-messageformat-parser'
|
|
18
|
-
|
|
19
|
-
export interface CreateIntlFn<
|
|
20
|
-
T = string,
|
|
21
|
-
C extends IntlConfig<T> = IntlConfig<T>,
|
|
22
|
-
S extends IntlShape<T> = IntlShape<T>
|
|
23
|
-
> {
|
|
24
|
-
(config: C, cache?: IntlCache): S
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function messagesContainString(
|
|
28
|
-
messages: Record<string, string> | Record<string, MessageFormatElement[]>
|
|
29
|
-
): messages is Record<string, MessageFormatElement[]> {
|
|
30
|
-
const firstMessage = messages ? messages[Object.keys(messages)[0]] : undefined
|
|
31
|
-
|
|
32
|
-
return typeof firstMessage === 'string'
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function verifyConfigMessages<T = string>(config: IntlConfig<T>) {
|
|
36
|
-
if (
|
|
37
|
-
config.onWarn &&
|
|
38
|
-
config.defaultRichTextElements &&
|
|
39
|
-
messagesContainString(config.messages || {})
|
|
40
|
-
) {
|
|
41
|
-
config.onWarn(`[@formatjs/intl] "defaultRichTextElements" was specified but "message" was not pre-compiled.
|
|
42
|
-
Please consider using "@formatjs/cli" to pre-compile your messages for performance.
|
|
43
|
-
For more details see https://formatjs.io/docs/getting-started/message-distribution`)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Create intl object
|
|
49
|
-
* @param config intl config
|
|
50
|
-
* @param cache cache for formatter instances to prevent memory leak
|
|
51
|
-
*/
|
|
52
|
-
export function createIntl<T = string>(
|
|
53
|
-
config: IntlConfig<T>,
|
|
54
|
-
cache?: IntlCache
|
|
55
|
-
): IntlShape<T> {
|
|
56
|
-
const formatters = createFormatters(cache)
|
|
57
|
-
const resolvedConfig: ResolvedIntlConfig<T> = {
|
|
58
|
-
...DEFAULT_INTL_CONFIG,
|
|
59
|
-
...config,
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const {locale, defaultLocale, onError} = resolvedConfig
|
|
63
|
-
if (!locale) {
|
|
64
|
-
if (onError) {
|
|
65
|
-
onError(
|
|
66
|
-
new InvalidConfigError(
|
|
67
|
-
`"locale" was not configured, using "${defaultLocale}" as fallback. See https://formatjs.io/docs/react-intl/api#intlshape for more details`
|
|
68
|
-
)
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
// Since there's no registered locale data for `locale`, this will
|
|
72
|
-
// fallback to the `defaultLocale` to make sure things can render.
|
|
73
|
-
// The `messages` are overridden to the `defaultProps` empty object
|
|
74
|
-
// to maintain referential equality across re-renders. It's assumed
|
|
75
|
-
// each <FormattedMessage> contains a `defaultMessage` prop.
|
|
76
|
-
resolvedConfig.locale = resolvedConfig.defaultLocale || 'en'
|
|
77
|
-
} else if (!Intl.NumberFormat.supportedLocalesOf(locale).length && onError) {
|
|
78
|
-
onError(
|
|
79
|
-
new MissingDataError(
|
|
80
|
-
`Missing locale data for locale: "${locale}" in Intl.NumberFormat. Using default locale: "${defaultLocale}" as fallback. See https://formatjs.io/docs/react-intl#runtime-requirements for more details`
|
|
81
|
-
)
|
|
82
|
-
)
|
|
83
|
-
} else if (
|
|
84
|
-
!Intl.DateTimeFormat.supportedLocalesOf(locale).length &&
|
|
85
|
-
onError
|
|
86
|
-
) {
|
|
87
|
-
onError(
|
|
88
|
-
new MissingDataError(
|
|
89
|
-
`Missing locale data for locale: "${locale}" in Intl.DateTimeFormat. Using default locale: "${defaultLocale}" as fallback. See https://formatjs.io/docs/react-intl#runtime-requirements for more details`
|
|
90
|
-
)
|
|
91
|
-
)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
verifyConfigMessages(resolvedConfig)
|
|
95
|
-
return {
|
|
96
|
-
...resolvedConfig,
|
|
97
|
-
formatters,
|
|
98
|
-
formatNumber: formatNumber.bind(
|
|
99
|
-
null,
|
|
100
|
-
resolvedConfig,
|
|
101
|
-
formatters.getNumberFormat
|
|
102
|
-
),
|
|
103
|
-
formatNumberToParts: formatNumberToParts.bind(
|
|
104
|
-
null,
|
|
105
|
-
resolvedConfig,
|
|
106
|
-
formatters.getNumberFormat
|
|
107
|
-
),
|
|
108
|
-
formatRelativeTime: formatRelativeTime.bind(
|
|
109
|
-
null,
|
|
110
|
-
resolvedConfig,
|
|
111
|
-
formatters.getRelativeTimeFormat
|
|
112
|
-
),
|
|
113
|
-
formatDate: formatDate.bind(
|
|
114
|
-
null,
|
|
115
|
-
resolvedConfig,
|
|
116
|
-
formatters.getDateTimeFormat
|
|
117
|
-
),
|
|
118
|
-
formatDateToParts: formatDateToParts.bind(
|
|
119
|
-
null,
|
|
120
|
-
resolvedConfig,
|
|
121
|
-
formatters.getDateTimeFormat
|
|
122
|
-
),
|
|
123
|
-
formatTime: formatTime.bind(
|
|
124
|
-
null,
|
|
125
|
-
resolvedConfig,
|
|
126
|
-
formatters.getDateTimeFormat
|
|
127
|
-
),
|
|
128
|
-
formatDateTimeRange: formatDateTimeRange.bind(
|
|
129
|
-
null,
|
|
130
|
-
resolvedConfig,
|
|
131
|
-
formatters.getDateTimeFormat
|
|
132
|
-
),
|
|
133
|
-
formatTimeToParts: formatTimeToParts.bind(
|
|
134
|
-
null,
|
|
135
|
-
resolvedConfig,
|
|
136
|
-
formatters.getDateTimeFormat
|
|
137
|
-
),
|
|
138
|
-
formatPlural: formatPlural.bind(
|
|
139
|
-
null,
|
|
140
|
-
resolvedConfig,
|
|
141
|
-
formatters.getPluralRules
|
|
142
|
-
),
|
|
143
|
-
// @ts-expect-error TODO: will get to this later
|
|
144
|
-
formatMessage: formatMessage.bind(null, resolvedConfig, formatters),
|
|
145
|
-
// @ts-expect-error TODO: will get to this later
|
|
146
|
-
$t: formatMessage.bind(null, resolvedConfig, formatters),
|
|
147
|
-
formatList: formatList.bind(null, resolvedConfig, formatters.getListFormat),
|
|
148
|
-
formatListToParts: formatListToParts.bind(
|
|
149
|
-
null,
|
|
150
|
-
resolvedConfig,
|
|
151
|
-
formatters.getListFormat
|
|
152
|
-
),
|
|
153
|
-
formatDisplayName: formatDisplayName.bind(
|
|
154
|
-
null,
|
|
155
|
-
resolvedConfig,
|
|
156
|
-
formatters.getDisplayNames
|
|
157
|
-
),
|
|
158
|
-
}
|
|
159
|
-
}
|
package/src/dateTime.ts
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import {Formatters, IntlFormatters, CustomFormats, OnErrorFn} from './types'
|
|
2
|
-
|
|
3
|
-
import {filterProps, getNamedFormat} from './utils'
|
|
4
|
-
import {IntlError, IntlErrorCode} from './error'
|
|
5
|
-
import {DateTimeFormat} from '@formatjs/ecma402-abstract'
|
|
6
|
-
|
|
7
|
-
const DATE_TIME_FORMAT_OPTIONS: Array<keyof Intl.DateTimeFormatOptions> = [
|
|
8
|
-
'formatMatcher',
|
|
9
|
-
|
|
10
|
-
'timeZone',
|
|
11
|
-
'hour12',
|
|
12
|
-
|
|
13
|
-
'weekday',
|
|
14
|
-
'era',
|
|
15
|
-
'year',
|
|
16
|
-
'month',
|
|
17
|
-
'day',
|
|
18
|
-
'hour',
|
|
19
|
-
'minute',
|
|
20
|
-
'second',
|
|
21
|
-
'timeZoneName',
|
|
22
|
-
'hourCycle',
|
|
23
|
-
'dateStyle',
|
|
24
|
-
'timeStyle',
|
|
25
|
-
'calendar',
|
|
26
|
-
// 'dayPeriod',
|
|
27
|
-
'numberingSystem',
|
|
28
|
-
'fractionalSecondDigits',
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
export function getFormatter(
|
|
32
|
-
{
|
|
33
|
-
locale,
|
|
34
|
-
formats,
|
|
35
|
-
onError,
|
|
36
|
-
timeZone,
|
|
37
|
-
}: {
|
|
38
|
-
locale: string
|
|
39
|
-
timeZone?: string
|
|
40
|
-
formats: CustomFormats
|
|
41
|
-
onError: OnErrorFn
|
|
42
|
-
},
|
|
43
|
-
type: 'date' | 'time',
|
|
44
|
-
getDateTimeFormat: Formatters['getDateTimeFormat'],
|
|
45
|
-
options: Parameters<IntlFormatters['formatDate']>[1] = {}
|
|
46
|
-
): DateTimeFormat {
|
|
47
|
-
const {format} = options
|
|
48
|
-
const defaults = {
|
|
49
|
-
...(timeZone && {timeZone}),
|
|
50
|
-
...(format && getNamedFormat(formats!, type, format, onError)),
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let filteredOptions = filterProps(
|
|
54
|
-
options,
|
|
55
|
-
DATE_TIME_FORMAT_OPTIONS,
|
|
56
|
-
defaults
|
|
57
|
-
) as Intl.DateTimeFormatOptions
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
type === 'time' &&
|
|
61
|
-
!filteredOptions.hour &&
|
|
62
|
-
!filteredOptions.minute &&
|
|
63
|
-
!filteredOptions.second &&
|
|
64
|
-
!filteredOptions.timeStyle &&
|
|
65
|
-
!filteredOptions.dateStyle
|
|
66
|
-
) {
|
|
67
|
-
// Add default formatting options if hour, minute, or second isn't defined.
|
|
68
|
-
filteredOptions = {...filteredOptions, hour: 'numeric', minute: 'numeric'}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return getDateTimeFormat(locale, filteredOptions)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function formatDate(
|
|
75
|
-
config: {
|
|
76
|
-
locale: string
|
|
77
|
-
timeZone?: string
|
|
78
|
-
formats: CustomFormats
|
|
79
|
-
onError: OnErrorFn
|
|
80
|
-
},
|
|
81
|
-
getDateTimeFormat: Formatters['getDateTimeFormat'],
|
|
82
|
-
...[value, options = {}]: Parameters<IntlFormatters['formatDate']>
|
|
83
|
-
): string {
|
|
84
|
-
const date = typeof value === 'string' ? new Date(value || 0) : value
|
|
85
|
-
try {
|
|
86
|
-
return getFormatter(config, 'date', getDateTimeFormat, options).format(date)
|
|
87
|
-
} catch (e) {
|
|
88
|
-
config.onError(
|
|
89
|
-
new IntlError(IntlErrorCode.FORMAT_ERROR, 'Error formatting date.', e)
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return String(date)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export function formatTime(
|
|
97
|
-
config: {
|
|
98
|
-
locale: string
|
|
99
|
-
timeZone?: string
|
|
100
|
-
formats: CustomFormats
|
|
101
|
-
onError: OnErrorFn
|
|
102
|
-
},
|
|
103
|
-
getDateTimeFormat: Formatters['getDateTimeFormat'],
|
|
104
|
-
...[value, options = {}]: Parameters<IntlFormatters['formatTime']>
|
|
105
|
-
): string {
|
|
106
|
-
const date = typeof value === 'string' ? new Date(value || 0) : value
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
return getFormatter(config, 'time', getDateTimeFormat, options).format(date)
|
|
110
|
-
} catch (e) {
|
|
111
|
-
config.onError(
|
|
112
|
-
new IntlError(IntlErrorCode.FORMAT_ERROR, 'Error formatting time.', e)
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return String(date)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function formatDateTimeRange(
|
|
120
|
-
config: {
|
|
121
|
-
locale: string
|
|
122
|
-
timeZone?: string
|
|
123
|
-
onError: OnErrorFn
|
|
124
|
-
},
|
|
125
|
-
getDateTimeFormat: Formatters['getDateTimeFormat'],
|
|
126
|
-
...[from, to, options = {}]: Parameters<IntlFormatters['formatDateTimeRange']>
|
|
127
|
-
): string {
|
|
128
|
-
const {timeZone, locale, onError} = config
|
|
129
|
-
|
|
130
|
-
const filteredOptions = filterProps(
|
|
131
|
-
options,
|
|
132
|
-
DATE_TIME_FORMAT_OPTIONS,
|
|
133
|
-
timeZone ? {timeZone} : {}
|
|
134
|
-
) as Intl.DateTimeFormatOptions
|
|
135
|
-
|
|
136
|
-
try {
|
|
137
|
-
return getDateTimeFormat(locale, filteredOptions).formatRange(from, to)
|
|
138
|
-
} catch (e) {
|
|
139
|
-
onError(
|
|
140
|
-
new IntlError(
|
|
141
|
-
IntlErrorCode.FORMAT_ERROR,
|
|
142
|
-
'Error formatting date time range.',
|
|
143
|
-
e
|
|
144
|
-
)
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return String(from)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export function formatDateToParts(
|
|
152
|
-
config: {
|
|
153
|
-
locale: string
|
|
154
|
-
timeZone?: string
|
|
155
|
-
formats: CustomFormats
|
|
156
|
-
onError: OnErrorFn
|
|
157
|
-
},
|
|
158
|
-
getDateTimeFormat: Formatters['getDateTimeFormat'],
|
|
159
|
-
...[value, options = {}]: Parameters<IntlFormatters['formatDate']>
|
|
160
|
-
): Intl.DateTimeFormatPart[] {
|
|
161
|
-
const date = typeof value === 'string' ? new Date(value || 0) : value
|
|
162
|
-
try {
|
|
163
|
-
return getFormatter(
|
|
164
|
-
config,
|
|
165
|
-
'date',
|
|
166
|
-
getDateTimeFormat,
|
|
167
|
-
options
|
|
168
|
-
).formatToParts(date)
|
|
169
|
-
} catch (e) {
|
|
170
|
-
config.onError(
|
|
171
|
-
new IntlError(IntlErrorCode.FORMAT_ERROR, 'Error formatting date.', e)
|
|
172
|
-
)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return []
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export function formatTimeToParts(
|
|
179
|
-
config: {
|
|
180
|
-
locale: string
|
|
181
|
-
timeZone?: string
|
|
182
|
-
formats: CustomFormats
|
|
183
|
-
onError: OnErrorFn
|
|
184
|
-
},
|
|
185
|
-
getDateTimeFormat: Formatters['getDateTimeFormat'],
|
|
186
|
-
...[value, options = {}]: Parameters<IntlFormatters['formatTimeToParts']>
|
|
187
|
-
): Intl.DateTimeFormatPart[] {
|
|
188
|
-
const date = typeof value === 'string' ? new Date(value || 0) : value
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
return getFormatter(
|
|
192
|
-
config,
|
|
193
|
-
'time',
|
|
194
|
-
getDateTimeFormat,
|
|
195
|
-
options
|
|
196
|
-
).formatToParts(date)
|
|
197
|
-
} catch (e) {
|
|
198
|
-
config.onError(
|
|
199
|
-
new IntlError(IntlErrorCode.FORMAT_ERROR, 'Error formatting time.', e)
|
|
200
|
-
)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return []
|
|
204
|
-
}
|
package/src/displayName.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import {Formatters, IntlFormatters, OnErrorFn} from './types'
|
|
2
|
-
import {filterProps} from './utils'
|
|
3
|
-
import {
|
|
4
|
-
DisplayNamesOptions,
|
|
5
|
-
DisplayNames as IntlDisplayNames,
|
|
6
|
-
} from '@formatjs/intl-displaynames'
|
|
7
|
-
import {FormatError, ErrorCode} from 'intl-messageformat'
|
|
8
|
-
import {IntlErrorCode, IntlError} from './error'
|
|
9
|
-
|
|
10
|
-
const DISPLAY_NAMES_OPTONS: Array<keyof DisplayNamesOptions> = [
|
|
11
|
-
'style',
|
|
12
|
-
'type',
|
|
13
|
-
'fallback',
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
export function formatDisplayName(
|
|
17
|
-
{
|
|
18
|
-
locale,
|
|
19
|
-
onError,
|
|
20
|
-
}: {
|
|
21
|
-
locale: string
|
|
22
|
-
onError: OnErrorFn
|
|
23
|
-
},
|
|
24
|
-
getDisplayNames: Formatters['getDisplayNames'],
|
|
25
|
-
value: Parameters<IntlFormatters['formatDisplayName']>[0],
|
|
26
|
-
options: Parameters<IntlFormatters['formatDisplayName']>[1]
|
|
27
|
-
): string | undefined {
|
|
28
|
-
const DisplayNames: typeof IntlDisplayNames = (Intl as any).DisplayNames
|
|
29
|
-
if (!DisplayNames) {
|
|
30
|
-
onError(
|
|
31
|
-
new FormatError(
|
|
32
|
-
`Intl.DisplayNames is not available in this environment.
|
|
33
|
-
Try polyfilling it using "@formatjs/intl-displaynames"
|
|
34
|
-
`,
|
|
35
|
-
ErrorCode.MISSING_INTL_API
|
|
36
|
-
)
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
const filteredOptions = filterProps(
|
|
40
|
-
options,
|
|
41
|
-
DISPLAY_NAMES_OPTONS
|
|
42
|
-
) as DisplayNamesOptions
|
|
43
|
-
try {
|
|
44
|
-
return getDisplayNames(locale, filteredOptions).of(value)
|
|
45
|
-
} catch (e) {
|
|
46
|
-
onError(
|
|
47
|
-
new IntlError(
|
|
48
|
-
IntlErrorCode.FORMAT_ERROR,
|
|
49
|
-
'Error formatting display name.',
|
|
50
|
-
e
|
|
51
|
-
)
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
}
|
package/src/error.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import {MessageDescriptor} from './types'
|
|
2
|
-
|
|
3
|
-
export enum IntlErrorCode {
|
|
4
|
-
FORMAT_ERROR = 'FORMAT_ERROR',
|
|
5
|
-
UNSUPPORTED_FORMATTER = 'UNSUPPORTED_FORMATTER',
|
|
6
|
-
INVALID_CONFIG = 'INVALID_CONFIG',
|
|
7
|
-
MISSING_DATA = 'MISSING_DATA',
|
|
8
|
-
MISSING_TRANSLATION = 'MISSING_TRANSLATION',
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class IntlError<
|
|
12
|
-
T extends IntlErrorCode = IntlErrorCode.FORMAT_ERROR
|
|
13
|
-
> extends Error {
|
|
14
|
-
public readonly code: T
|
|
15
|
-
|
|
16
|
-
constructor(code: T, message: string, exception?: Error | unknown) {
|
|
17
|
-
const err = exception
|
|
18
|
-
? exception instanceof Error
|
|
19
|
-
? exception
|
|
20
|
-
: new Error(String(exception))
|
|
21
|
-
: undefined
|
|
22
|
-
super(
|
|
23
|
-
`[@formatjs/intl Error ${code}] ${message}
|
|
24
|
-
${err ? `\n${err.message}\n${err.stack}` : ''}`
|
|
25
|
-
)
|
|
26
|
-
this.code = code
|
|
27
|
-
// @ts-ignore just so we don't need to declare dep on @types/node
|
|
28
|
-
if (typeof Error.captureStackTrace === 'function') {
|
|
29
|
-
// @ts-ignore just so we don't need to declare dep on @types/node
|
|
30
|
-
Error.captureStackTrace(this, IntlError)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class UnsupportedFormatterError extends IntlError<IntlErrorCode.UNSUPPORTED_FORMATTER> {
|
|
36
|
-
constructor(message: string, exception?: Error | unknown) {
|
|
37
|
-
super(IntlErrorCode.UNSUPPORTED_FORMATTER, message, exception)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export class InvalidConfigError extends IntlError<IntlErrorCode.INVALID_CONFIG> {
|
|
42
|
-
constructor(message: string, exception?: Error | unknown) {
|
|
43
|
-
super(IntlErrorCode.INVALID_CONFIG, message, exception)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export class MissingDataError extends IntlError<IntlErrorCode.MISSING_DATA> {
|
|
48
|
-
constructor(message: string, exception?: Error | unknown) {
|
|
49
|
-
super(IntlErrorCode.MISSING_DATA, message, exception)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export class IntlFormatError extends IntlError<IntlErrorCode.FORMAT_ERROR> {
|
|
54
|
-
public readonly descriptor?: MessageDescriptor
|
|
55
|
-
constructor(message: string, locale: string, exception?: Error | unknown) {
|
|
56
|
-
super(
|
|
57
|
-
IntlErrorCode.FORMAT_ERROR,
|
|
58
|
-
`${message}
|
|
59
|
-
Locale: ${locale}
|
|
60
|
-
`,
|
|
61
|
-
exception
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export class MessageFormatError extends IntlFormatError {
|
|
67
|
-
public readonly descriptor?: MessageDescriptor
|
|
68
|
-
constructor(
|
|
69
|
-
message: string,
|
|
70
|
-
locale: string,
|
|
71
|
-
descriptor?: MessageDescriptor,
|
|
72
|
-
exception?: Error | unknown
|
|
73
|
-
) {
|
|
74
|
-
super(
|
|
75
|
-
`${message}
|
|
76
|
-
MessageID: ${descriptor?.id}
|
|
77
|
-
Default Message: ${descriptor?.defaultMessage}
|
|
78
|
-
Description: ${descriptor?.description}
|
|
79
|
-
`,
|
|
80
|
-
locale,
|
|
81
|
-
exception
|
|
82
|
-
)
|
|
83
|
-
this.descriptor = descriptor
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export class MissingTranslationError extends IntlError<IntlErrorCode.MISSING_TRANSLATION> {
|
|
88
|
-
public readonly descriptor?: MessageDescriptor
|
|
89
|
-
constructor(descriptor: MessageDescriptor, locale: string) {
|
|
90
|
-
super(
|
|
91
|
-
IntlErrorCode.MISSING_TRANSLATION,
|
|
92
|
-
`Missing message: "${descriptor.id}" for locale "${locale}", using ${
|
|
93
|
-
descriptor.defaultMessage
|
|
94
|
-
? `default message (${
|
|
95
|
-
typeof descriptor.defaultMessage === 'string'
|
|
96
|
-
? descriptor.defaultMessage
|
|
97
|
-
: descriptor.defaultMessage
|
|
98
|
-
.map((e: any) => e.value ?? JSON.stringify(e))
|
|
99
|
-
.join()
|
|
100
|
-
})`
|
|
101
|
-
: 'id'
|
|
102
|
-
} as fallback.`
|
|
103
|
-
)
|
|
104
|
-
this.descriptor = descriptor
|
|
105
|
-
}
|
|
106
|
-
}
|
package/src/list.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import {Formatters, IntlFormatters, OnErrorFn} from './types'
|
|
2
|
-
import {filterProps} from './utils'
|
|
3
|
-
import type IntlListFormat from '@formatjs/intl-listformat'
|
|
4
|
-
import type {Part} from '@formatjs/intl-listformat'
|
|
5
|
-
import type {IntlListFormatOptions} from '@formatjs/intl-listformat'
|
|
6
|
-
import {FormatError, ErrorCode} from 'intl-messageformat'
|
|
7
|
-
import {IntlError, IntlErrorCode} from './error'
|
|
8
|
-
|
|
9
|
-
const LIST_FORMAT_OPTIONS: Array<keyof IntlListFormatOptions> = [
|
|
10
|
-
'type',
|
|
11
|
-
'style',
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
const now = Date.now()
|
|
15
|
-
|
|
16
|
-
function generateToken(i: number): string {
|
|
17
|
-
return `${now}_${i}_${now}`
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function formatList(
|
|
21
|
-
opts: {
|
|
22
|
-
locale: string
|
|
23
|
-
onError: OnErrorFn
|
|
24
|
-
},
|
|
25
|
-
getListFormat: Formatters['getListFormat'],
|
|
26
|
-
values: ReadonlyArray<string>,
|
|
27
|
-
options: Parameters<IntlFormatters['formatList']>[1]
|
|
28
|
-
): string
|
|
29
|
-
export function formatList<T>(
|
|
30
|
-
opts: {
|
|
31
|
-
locale: string
|
|
32
|
-
onError: OnErrorFn
|
|
33
|
-
},
|
|
34
|
-
getListFormat: Formatters['getListFormat'],
|
|
35
|
-
values: Parameters<IntlFormatters['formatList']>[0],
|
|
36
|
-
options: Parameters<IntlFormatters['formatList']>[1] = {}
|
|
37
|
-
): Array<T | string> | T | string {
|
|
38
|
-
const results = formatListToParts(
|
|
39
|
-
opts,
|
|
40
|
-
getListFormat,
|
|
41
|
-
values,
|
|
42
|
-
options
|
|
43
|
-
).reduce((all: Array<string | T>, el) => {
|
|
44
|
-
const val = el.value
|
|
45
|
-
if (typeof val !== 'string') {
|
|
46
|
-
all.push(val)
|
|
47
|
-
} else if (typeof all[all.length - 1] === 'string') {
|
|
48
|
-
all[all.length - 1] += val
|
|
49
|
-
} else {
|
|
50
|
-
all.push(val)
|
|
51
|
-
}
|
|
52
|
-
return all
|
|
53
|
-
}, [])
|
|
54
|
-
return results.length === 1 ? results[0] : results
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function formatListToParts<T>(
|
|
58
|
-
opts: {
|
|
59
|
-
locale: string
|
|
60
|
-
onError: OnErrorFn
|
|
61
|
-
},
|
|
62
|
-
getListFormat: Formatters['getListFormat'],
|
|
63
|
-
values: ReadonlyArray<string>,
|
|
64
|
-
options: Parameters<IntlFormatters['formatList']>[1]
|
|
65
|
-
): Part[]
|
|
66
|
-
export function formatListToParts<T>(
|
|
67
|
-
{
|
|
68
|
-
locale,
|
|
69
|
-
onError,
|
|
70
|
-
}: {
|
|
71
|
-
locale: string
|
|
72
|
-
onError: OnErrorFn
|
|
73
|
-
},
|
|
74
|
-
getListFormat: Formatters['getListFormat'],
|
|
75
|
-
values: Parameters<IntlFormatters['formatList']>[0],
|
|
76
|
-
options: Parameters<IntlFormatters['formatList']>[1] = {}
|
|
77
|
-
): Part<T | string>[] {
|
|
78
|
-
const ListFormat: typeof IntlListFormat = (Intl as any).ListFormat
|
|
79
|
-
if (!ListFormat) {
|
|
80
|
-
onError(
|
|
81
|
-
new FormatError(
|
|
82
|
-
`Intl.ListFormat is not available in this environment.
|
|
83
|
-
Try polyfilling it using "@formatjs/intl-listformat"
|
|
84
|
-
`,
|
|
85
|
-
ErrorCode.MISSING_INTL_API
|
|
86
|
-
)
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
const filteredOptions = filterProps(
|
|
90
|
-
options,
|
|
91
|
-
LIST_FORMAT_OPTIONS
|
|
92
|
-
) as IntlListFormatOptions
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
const richValues: Record<string, T> = {}
|
|
96
|
-
const serializedValues = values.map((v, i) => {
|
|
97
|
-
if (typeof v === 'object') {
|
|
98
|
-
const id = generateToken(i)
|
|
99
|
-
richValues[id] = v as any
|
|
100
|
-
return id
|
|
101
|
-
}
|
|
102
|
-
return String(v)
|
|
103
|
-
})
|
|
104
|
-
return getListFormat(locale, filteredOptions)
|
|
105
|
-
.formatToParts(serializedValues)
|
|
106
|
-
.map(part =>
|
|
107
|
-
part.type === 'literal'
|
|
108
|
-
? part
|
|
109
|
-
: {...part, value: richValues[part.value] || part.value}
|
|
110
|
-
)
|
|
111
|
-
} catch (e) {
|
|
112
|
-
onError(
|
|
113
|
-
new IntlError(IntlErrorCode.FORMAT_ERROR, 'Error formatting list.', e)
|
|
114
|
-
)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// @ts-ignore
|
|
118
|
-
return values
|
|
119
|
-
}
|