Skip to content

Commit bc92dc4

Browse files
mauryapariParitosh Maurya
andauthored
Part options support $n - v11 (#2175)
* Back ported part option functionality for () * Added type safety --------- Co-authored-by: Paritosh Maurya <[email protected]>
1 parent c2ea6dd commit bc92dc4

File tree

4 files changed

+151
-30
lines changed

4 files changed

+151
-30
lines changed

packages/vue-i18n-core/src/composer.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,13 +1203,18 @@ export interface ComposerNumberFormatting<
12031203
*
12041204
* @returns Formatted value
12051205
*/
1206-
<Key extends string = string>(
1206+
<
1207+
Key extends string = string,
1208+
Return extends string | Intl.NumberFormatPart[] =
1209+
| string
1210+
| Intl.NumberFormatPart[]
1211+
>(
12071212
value: number,
12081213
keyOrOptions:
12091214
| Key
12101215
| ResourceKeys
12111216
| NumberOptions<Key | ResourceKeys, Locales>
1212-
): string
1217+
): Return
12131218
/**
12141219
* Number Formatting
12151220
*
@@ -1224,14 +1229,19 @@ export interface ComposerNumberFormatting<
12241229
*
12251230
* @returns Formatted value
12261231
*/
1227-
<Key extends string = string>(
1232+
<
1233+
Key extends string = string,
1234+
Return extends string | Intl.NumberFormatPart[] =
1235+
| string
1236+
| Intl.NumberFormatPart[]
1237+
>(
12281238
value: number,
12291239
keyOrOptions:
12301240
| Key
12311241
| ResourceKeys
12321242
| NumberOptions<Key | ResourceKeys, Locales>,
12331243
locale: Locales
1234-
): string
1244+
): Return
12351245
}
12361246

12371247
/**
@@ -2287,14 +2297,17 @@ export function createComposer(options: any = {}): any {
22872297
}
22882298

22892299
// n
2290-
function n(...args: unknown[]): string {
2291-
return wrapWithDeps<{}, string>(
2292-
context => Reflect.apply(number, null, [context, ...args]) as string,
2300+
function n(...args: unknown[]): string | Intl.NumberFormatPart[] {
2301+
return wrapWithDeps<{}, string | Intl.NumberFormatPart[]>(
2302+
context =>
2303+
Reflect.apply(number, null, [context, ...args]) as
2304+
| string
2305+
| Intl.NumberFormatPart[],
22932306
() => parseNumberArgs(...args),
22942307
'number format',
22952308
root => Reflect.apply(root.n, root, [...args]),
22962309
() => MISSING_RESOLVE_VALUE,
2297-
val => isString(val)
2310+
val => isString(val) || isArray(val)
22982311
)
22992312
}
23002313

packages/vue-i18n-core/test/composer.test-d.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,15 +353,34 @@ test('strict composer with direct options', () => {
353353
strictDirectComposer.d(new Date(), 'custom' as any)
354354
).toEqualTypeOf<string>()
355355
expectTypeOf(strictDirectComposer.n(1)).toEqualTypeOf<string>()
356+
expectTypeOf(strictDirectComposer.n(1, 'currency', 'zh')).toEqualTypeOf<
357+
string | Intl.NumberFormatPart[]
358+
>()
359+
expectTypeOf(
360+
strictDirectComposer.n<string, string>(1, 'currency', 'zh')
361+
).toEqualTypeOf<string>()
356362
expectTypeOf(
357-
strictDirectComposer.n(1, 'currency', 'zh')
363+
strictDirectComposer.n<string, string>(1, { key: 'currency', locale: 'en' })
358364
).toEqualTypeOf<string>()
359365
expectTypeOf(
360-
strictDirectComposer.n(1, { key: 'currency', locale: 'en' })
366+
strictDirectComposer.n<string, string>(1, { key: 'currency', locale: 'en' })
361367
).toEqualTypeOf<string>()
362368
expectTypeOf(
363-
strictDirectComposer.n(1, 'custom' as any)
369+
strictDirectComposer.n<string, Intl.NumberFormatPart[]>(1, {
370+
key: 'currency',
371+
locale: 'en',
372+
part: true
373+
})
374+
).toEqualTypeOf<Intl.NumberFormatPart[]>()
375+
expectTypeOf(strictDirectComposer.n(1, 'currency')).toEqualTypeOf<
376+
string | Intl.NumberFormatPart[]
377+
>()
378+
expectTypeOf(
379+
strictDirectComposer.n<string, string>(1, 'currency')
364380
).toEqualTypeOf<string>()
381+
expectTypeOf(strictDirectComposer.n(1, 'custom' as any)).toEqualTypeOf<
382+
string | Intl.NumberFormatPart[]
383+
>()
365384

366385
// const noOptionsComposer = createComposer({ missingWarn: true })
367386
const noOptionsComposer = createComposer({ locale: 'en' })

packages/vue-i18n-core/test/composer.test.ts

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,41 @@
55

66
// utils
77
import * as shared from '@intlify/shared'
8+
import { pluralRules as _pluralRules } from './helper'
89
vi.mock('@intlify/shared', async () => {
910
const actual = await vi.importActual<object>('@intlify/shared')
1011
return {
1112
...actual,
1213
warn: vi.fn()
1314
}
1415
})
15-
import { pluralRules as _pluralRules } from './helper'
1616

1717
import {
18+
compile,
19+
fallbackWithLocaleChain,
20+
Locale,
21+
MessageContext,
22+
MessageFunction,
23+
Path,
24+
PathValue,
25+
registerLocaleFallbacker,
26+
registerMessageCompiler,
27+
registerMessageResolver,
28+
resolveValue
29+
} from '@intlify/core-base'
30+
import { createVNode, nextTick, Text, watch, watchEffect } from 'vue'
31+
import {
32+
ComposerOptions,
1833
createComposer,
1934
MissingHandler,
20-
ComposerOptions,
2135
VueMessageType
2236
} from '../src/composer'
2337
import {
24-
TranslateVNodeSymbol,
38+
DatetimePartsSymbol,
2539
NumberPartsSymbol,
26-
DatetimePartsSymbol
40+
TranslateVNodeSymbol
2741
} from '../src/symbols'
2842
import { getWarnMessage, I18nWarnCodes } from '../src/warnings'
29-
import { watch, watchEffect, nextTick, Text, createVNode } from 'vue'
30-
import {
31-
Locale,
32-
compile,
33-
registerMessageCompiler,
34-
resolveValue,
35-
registerMessageResolver,
36-
fallbackWithLocaleChain,
37-
registerLocaleFallbacker,
38-
MessageContext,
39-
Path,
40-
PathValue,
41-
MessageFunction
42-
} from '@intlify/core-base'
4343

4444
beforeEach(() => {
4545
registerMessageCompiler(compile)
@@ -1202,6 +1202,79 @@ describe('n', () => {
12021202
})
12031203
expect(n(0.99, { key: 'percent' })).toEqual('')
12041204
})
1205+
1206+
test('part formatting with n', () => {
1207+
const { n } = createComposer({
1208+
locale: 'en-US',
1209+
fallbackLocale: ['ja-JP'],
1210+
numberFormats: {
1211+
'en-US': {
1212+
currency: {
1213+
style: 'currency',
1214+
currency: 'USD',
1215+
currencyDisplay: 'symbol'
1216+
},
1217+
decimal: {
1218+
style: 'decimal',
1219+
useGrouping: true
1220+
}
1221+
},
1222+
'ja-JP': {
1223+
currency: {
1224+
style: 'currency',
1225+
currency: 'JPY' /*, currencyDisplay: 'symbol'*/
1226+
},
1227+
numeric: {
1228+
style: 'decimal',
1229+
useGrouping: false
1230+
},
1231+
percent: {
1232+
style: 'percent',
1233+
useGrouping: true
1234+
}
1235+
}
1236+
}
1237+
})
1238+
expect(n(0.99, { key: 'currency', part: true })).toEqual([
1239+
{ type: 'currency', value: '$' },
1240+
{ type: 'integer', value: '0' },
1241+
{ type: 'decimal', value: '.' },
1242+
{ type: 'fraction', value: '99' }
1243+
])
1244+
expect(
1245+
n(10100, {
1246+
key: 'currency',
1247+
locale: 'ja-JP',
1248+
part: true
1249+
})
1250+
).toEqual([
1251+
{ type: 'currency', value: '¥' },
1252+
{ type: 'integer', value: '10' },
1253+
{ type: 'group', value: ',' },
1254+
{ type: 'integer', value: '100' }
1255+
])
1256+
expect(n(12145281000, { key: 'percent', part: true })).toEqual([
1257+
{ type: 'integer', value: '1' },
1258+
{ type: 'group', value: ',' },
1259+
{ type: 'integer', value: '214' },
1260+
{ type: 'group', value: ',' },
1261+
{ type: 'integer', value: '528' },
1262+
{ type: 'group', value: ',' },
1263+
{ type: 'integer', value: '100' },
1264+
{ type: 'group', value: ',' },
1265+
{ type: 'integer', value: '000' },
1266+
{ type: 'percentSign', value: '%' }
1267+
])
1268+
expect(n(12145281111, { key: 'decimal', part: true })).toEqual([
1269+
{ type: 'integer', value: '12' },
1270+
{ type: 'group', value: ',' },
1271+
{ type: 'integer', value: '145' },
1272+
{ type: 'group', value: ',' },
1273+
{ type: 'integer', value: '281' },
1274+
{ type: 'group', value: ',' },
1275+
{ type: 'integer', value: '111' }
1276+
])
1277+
})
12051278
})
12061279

12071280
describe('tm', () => {

packages/vue-i18n/src/vue.d.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,23 @@ declare module 'vue' {
865865
*
866866
* @returns formatted value
867867
*/
868-
$n(value: number, options: NumberOptions): string
868+
$n<
869+
Key extends string,
870+
Return extends string | Intl.NumberFormatPart[] =
871+
| string
872+
| Intl.NumberFormatPart[],
873+
DefinedNumberFormat extends
874+
RemovedIndexResources<DefineDateTimeFormat> = RemovedIndexResources<DefineDateTimeFormat>,
875+
Keys = IsEmptyObject<DefinedNumberFormat> extends false
876+
? PickupFormatPathKeys<{
877+
[K in keyof DefinedNumberFormat]: DefinedNumberFormat[K]
878+
}>
879+
: never,
880+
ResourceKeys extends Keys = IsNever<Keys> extends false ? Keys : never
881+
>(
882+
value: number,
883+
options: NumberOptions<Key, ResourceKeys>
884+
): Return
869885
/**
870886
* Locale messages getter
871887
*

0 commit comments

Comments
 (0)