@@ -16,43 +16,149 @@ import {NumberFieldProps} from '@react-types/numberfield';
16
16
import { NumberFormatter , NumberParser } from '@internationalized/number' ;
17
17
import { useCallback , useMemo , useState } from 'react' ;
18
18
19
- let supportedLocales : string [ ] = [
20
- 'ar-AE' , // Arabic (United Arab Emirates)
21
- 'bg-BG' , // Bulgarian (Bulgaria)
22
- 'zh-CN' , // Chinese (Simplified)
23
- 'zh-TW' , // Chinese (Traditional)
24
- 'hr-HR' , // Croatian (Croatia)
25
- 'cs-CZ' , // Czech (Czech Republic)
26
- 'da-DK' , // Danish (Denmark)
27
- 'nl-NL' , // Dutch (Netherlands)
28
- 'en-GB' , // English (Great Britain)
29
- 'en-US' , // English (United States)
30
- 'et-EE' , // Estonian (Estonia)
31
- 'fi-FI' , // Finnish (Finland)
32
- 'fr-CA' , // French (Canada)
33
- 'fr-FR' , // French (France)
34
- 'de-DE' , // German (Germany)
35
- 'el-GR' , // Greek (Greece)
36
- 'he-IL' , // Hebrew (Israel)
37
- 'hu-HU' , // Hungarian (Hungary)
38
- 'it-IT' , // Italian (Italy)
39
- 'ja-JP' , // Japanese (Japan)
40
- 'ko-KR' , // Korean (Korea)
41
- 'lv-LV' , // Latvian (Latvia)
42
- 'lt-LT' , // Lithuanian (Lithuania)
43
- 'no-NO' , // Norwegian (Norway)
44
- 'pl-PL' , // Polish (Poland)
45
- 'pt-BR' , // Portuguese (Brazil)
46
- 'ro-RO' , // Romanian (Romania)
47
- 'ru-RU' , // Russian (Russia)
48
- 'sr-RS' , // Serbian (Serbia)
49
- 'sk-SK' , // Slovakian (Slovakia)
50
- 'sl-SI' , // Slovenian (Slovenia)
51
- 'es-ES' , // Spanish (Spain)
52
- 'sv-SE' , // Swedish (Sweden)
53
- 'tr-TR' , // Turkish (Turkey)
54
- 'uk-UA' // Ukrainian (Ukraine)
55
- ] ;
19
+
20
+ let supportedLocales = new Map < string , { groupSeparator : string , decimalSeparator : string } > ( [
21
+ [
22
+ 'ar-AE' , // Arabic (United Arab Emirates)
23
+ { groupSeparator : ',' , decimalSeparator : '.' }
24
+ ] ,
25
+ [
26
+ 'bg-BG' , // Bulgarian (Bulgaria)
27
+ { groupSeparator : '' , decimalSeparator : ',' }
28
+ ] ,
29
+ [
30
+ 'zh-CN' , // Chinese (Simplified)
31
+ { groupSeparator : ',' , decimalSeparator : '.' }
32
+ ] ,
33
+ [
34
+ 'zh-TW' , // Chinese (Traditional)
35
+ { groupSeparator : ',' , decimalSeparator : '.' }
36
+ ] ,
37
+ [
38
+ 'hr-HR' , // Croatian (Croatia)
39
+ { groupSeparator : '.' , decimalSeparator : ',' }
40
+ ] ,
41
+ [
42
+ 'cs-CZ' , // Czech (Czech Republic)
43
+ { groupSeparator : ' ' , decimalSeparator : ',' }
44
+ ] ,
45
+ [
46
+ 'da-DK' , // Danish (Denmark)
47
+ { groupSeparator : '.' , decimalSeparator : ',' }
48
+ ] ,
49
+ [
50
+ 'nl-NL' , // Dutch (Netherlands)
51
+ { groupSeparator : '.' , decimalSeparator : ',' }
52
+ ] ,
53
+ [
54
+ 'en-GB' , // English (Great Britain)
55
+ { groupSeparator : ',' , decimalSeparator : '.' }
56
+ ] ,
57
+ [
58
+ 'en-US' , // English (United States)
59
+ { groupSeparator : ',' , decimalSeparator : '.' }
60
+ ] ,
61
+ [
62
+ 'et-EE' , // Estonian (Estonia)
63
+ { groupSeparator : '' , decimalSeparator : ',' }
64
+ ] ,
65
+ [
66
+ 'fi-FI' , // Finnish (Finland)
67
+ { groupSeparator : ' ' , decimalSeparator : ',' }
68
+ ] ,
69
+ [
70
+ 'fr-CA' , // French (Canada)
71
+ { groupSeparator : ' ' , decimalSeparator : ',' }
72
+ ] ,
73
+ [
74
+ 'fr-FR' , // French (France)
75
+ { groupSeparator : ' ' , decimalSeparator : ',' }
76
+ ] ,
77
+ [
78
+ 'de-DE' , // German (Germany)
79
+ { groupSeparator : '.' , decimalSeparator : ',' }
80
+ ] ,
81
+ [
82
+ 'el-GR' , // Greek (Greece)
83
+ { groupSeparator : '.' , decimalSeparator : ',' }
84
+ ] ,
85
+ [
86
+ 'he-IL' , // Hebrew (Israel)
87
+ { groupSeparator : ',' , decimalSeparator : '.' }
88
+ ] ,
89
+ [
90
+ 'hu-HU' , // Hungarian (Hungary)
91
+ { groupSeparator : ' ' , decimalSeparator : ',' }
92
+ ] ,
93
+ [
94
+ 'it-IT' , // Italian (Italy)
95
+ { groupSeparator : '.' , decimalSeparator : ',' }
96
+ ] ,
97
+ [
98
+ 'ja-JP' , // Japanese (Japan)
99
+ { groupSeparator : ',' , decimalSeparator : '.' }
100
+ ] ,
101
+ [
102
+ 'ko-KR' , // Korean (Korea)
103
+ { groupSeparator : ',' , decimalSeparator : '.' }
104
+ ] ,
105
+ [
106
+ 'lv-LV' , // Latvian (Latvia)
107
+ { groupSeparator : '' , decimalSeparator : ',' }
108
+ ] ,
109
+ [
110
+ 'lt-LT' , // Lithuanian (Lithuania)
111
+ { groupSeparator : ' ' , decimalSeparator : ',' }
112
+ ] ,
113
+ [
114
+ 'no-NO' , // Norwegian (Norway)
115
+ { groupSeparator : ' ' , decimalSeparator : ',' }
116
+ ] ,
117
+ [
118
+ 'pl-PL' , // Polish (Poland)
119
+ { groupSeparator : '' , decimalSeparator : ',' }
120
+ ] ,
121
+ [
122
+ 'pt-BR' , // Portuguese (Brazil)
123
+ { groupSeparator : '.' , decimalSeparator : ',' }
124
+ ] ,
125
+ [
126
+ 'ro-RO' , // Romanian (Romania)
127
+ { groupSeparator : '.' , decimalSeparator : ',' }
128
+ ] ,
129
+ [
130
+ 'ru-RU' , // Russian (Russia)
131
+ { groupSeparator : ' ' , decimalSeparator : ',' }
132
+ ] ,
133
+ [
134
+ 'sr-RS' , // Serbian (Serbia)
135
+ { groupSeparator : '.' , decimalSeparator : ',' }
136
+ ] ,
137
+ [
138
+ 'sk-SK' , // Slovakian (Slovakia)
139
+ { groupSeparator : ' ' , decimalSeparator : ',' }
140
+ ] ,
141
+ [
142
+ 'sl-SI' , // Slovenian (Slovenia)
143
+ { groupSeparator : '.' , decimalSeparator : ',' }
144
+ ] ,
145
+ [
146
+ 'es-ES' , // Spanish (Spain)
147
+ { groupSeparator : '' , decimalSeparator : ',' }
148
+ ] ,
149
+ [
150
+ 'sv-SE' , // Swedish (Sweden)
151
+ { groupSeparator : ' ' , decimalSeparator : ',' }
152
+ ] ,
153
+ [
154
+ 'tr-TR' , // Turkish (Turkey)
155
+ { groupSeparator : '.' , decimalSeparator : ',' }
156
+ ] ,
157
+ [
158
+ 'uk-UA' , // Ukrainian (Ukraine)
159
+ { groupSeparator : ' ' , decimalSeparator : ',' }
160
+ ]
161
+ ] ) ;
56
162
57
163
export interface NumberFieldState extends FormValidationState {
58
164
/**
@@ -305,36 +411,34 @@ export function useNumberFieldState(
305
411
let validate = ( value : string ) => numberParser . isValidPartialNumber ( value , minValue , maxValue ) ;
306
412
307
413
let parseValueInAnySupportedLocale = ( value : string ) => {
308
- let locales = supportedLocales . filter ( localeCode => localeCode !== locale ) ;
309
- locales . unshift ( locale ) ;
310
- let localeCodes = locales . map ( localeCode => {
311
- let numberFormatter = new NumberFormatter ( localeCode , formatOptions ) ;
312
- return {
313
- locale : localeCode ,
314
- groupSeparator : numberFormatter . formatToParts ( 1111 ) . find ( part => part . type === 'group' ) ?. value ,
315
- decimalSeparator : numberFormatter . formatToParts ( 1.1 ) . find ( part => part . type === 'decimal' ) ?. value
316
- } ;
317
- } ) ;
414
+ let currentLocaleCode = [ ...supportedLocales ] . find ( ( [ localeCode ] ) => localeCode === locale ) || [ 'en-US' , { groupSeparator : ',' , decimalSeparator : '.' } ] ;
415
+ let localesWithDifferentSeparators = [ ...supportedLocales ] . filter ( ( [ , separators ] ) => separators . groupSeparator !== currentLocaleCode ?. [ 1 ] . groupSeparator && separators . decimalSeparator !== currentLocaleCode ?. [ 1 ] . decimalSeparator ) ;
416
+ let locales = new Map (
417
+ [
418
+ currentLocaleCode ,
419
+ ...localesWithDifferentSeparators
420
+ ]
421
+ ) ;
318
422
319
423
let _parsedValue = NaN ;
320
- for ( let localeCode of localeCodes ) {
321
- let _numberParser = new NumberParser ( localeCode . locale , formatOptions ) ;
424
+ for ( let [ localeCode , separators ] of locales ) {
425
+ let _numberParser = new NumberParser ( localeCode , formatOptions ) ;
322
426
if (
323
427
(
324
- ( localeCode . groupSeparator && value . includes ( localeCode . groupSeparator ) ) ||
325
- ( localeCode . decimalSeparator && value . includes ( localeCode . decimalSeparator ) )
428
+ value . includes ( separators . groupSeparator ) ||
429
+ value . includes ( separators . decimalSeparator )
326
430
) &&
327
- value . lastIndexOf ( localeCode . groupSeparator ?? '' ) > value . lastIndexOf ( localeCode . decimalSeparator ?? '' )
431
+ value . lastIndexOf ( separators . groupSeparator ) > value . lastIndexOf ( separators . decimalSeparator )
328
432
) {
329
- if ( value . lastIndexOf ( localeCode . decimalSeparator ?? '' ) === - 1 ) {
330
- let pv = _numberParser . parse ( value . replaceAll ( localeCode . groupSeparator ?? '' , '' ) ) ;
331
- if ( ! isNaN ( pv ) && parseFloat ( value . replaceAll ( localeCode . groupSeparator ?? '' , '' ) ) === pv ) {
433
+ if ( value . lastIndexOf ( separators . decimalSeparator ) === - 1 ) {
434
+ let pv = _numberParser . parse ( value . replaceAll ( separators . groupSeparator , '' ) ) ;
435
+ if ( ! isNaN ( pv ) && parseFloat ( value . replaceAll ( separators . groupSeparator , '' ) ) === pv ) {
332
436
return pv ;
333
437
}
334
438
}
335
439
continue ;
336
440
}
337
- _parsedValue = _numberParser . parse ( value . replaceAll ( localeCode . groupSeparator ?? '' , '' ) ) ;
441
+ _parsedValue = _numberParser . parse ( value . replaceAll ( separators . groupSeparator , '' ) ) ;
338
442
if ( ! isNaN ( _parsedValue ) ) {
339
443
return _parsedValue ;
340
444
}
0 commit comments