From 436f899335d16a99edca6cb3bce1de6b68e8a0bf Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Wed, 13 Sep 2017 19:11:29 +0200 Subject: [PATCH 1/5] Normative: Add calendar and numberingSystem options This patch allows calendar and numberingSystem to be specified in the options bag of the DateTimeFormat and NumberFormat constructors. One use case for these options would be, when working with locales which have two numbering systems and calendars in use--the UA default may be the non-Western one, but in some contexts, it may be appropriate to use the Western one. Currently, without the patch, it would be necessary to parse the BCP 47 language tag in the application, but Intl provides no library to do so. For example, this all occurs in this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1370086 This patch validates the calendar and numbering system by comparing them to the grammar allowed for Unicode extension tags, per the resolution documented at https://github.com/tc39/ecma402/pull/175#issuecomment-367507610 Related bug: #105 . This patch leaves out "collation" because of a lack of clear use cases. --- spec/datetimeformat.html | 10 ++++++++++ spec/numberformat.html | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/spec/datetimeformat.html b/spec/datetimeformat.html index 9da0519d..fa299bc0 100644 --- a/spec/datetimeformat.html +++ b/spec/datetimeformat.html @@ -73,12 +73,22 @@

InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )

The abstract operation InitializeDateTimeFormat accepts the arguments _dateTimeFormat_ (which must be an object), _locales_, and _options_. It initializes _dateTimeFormat_ as a DateTimeFormat object. This abstract operation functions as follows:

+

+ The following algorithm refers to UTS 35's Unicode Locale Identifier grammar. +

+ 1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). 1. Let _options_ be ? ToDateTimeOptions(_options_, *"any"*, *"date"*). 1. Let _opt_ be a new Record. 1. Let _matcher_ be ? GetOption(_options_, *"localeMatcher"*, *"string"*, « *"lookup"*, *"best fit"* », *"best fit"*). 1. Set _opt_.[[localeMatcher]] to _matcher_. + 1. Let _calendar_ be ? GetOption(_options_, *"calendar"*, *"string"*, *undefined*, *undefined*). + 1. If _calendar_ does not match `type`, throw a *RangeError* exception. + 1. Set _opt_.[[ca]] to _calendar_. + 1. Let _numberingSystem_ be ? GetOption(_options_, *"numberingSystem"*, *"string"*, *undefined*, *undefined*). + 1. If _numberingSystem_ does not match `type`, throw a *RangeError* exception. + 1. Set _opt_.[[nu]] to _numberingSystem_. 1. Let _hour12_ be ? GetOption(_options_, *"hour12"*, *"boolean"*, *undefined*, *undefined*). 1. Let _hourCycle_ be ? GetOption(_options_, *"hourCycle"*, *"string"*, « *"h11"*, *"h12"*, *"h23"*, *"h24"* », *undefined*). 1. If _hour12_ is not *undefined*, then diff --git a/spec/numberformat.html b/spec/numberformat.html index e67c5aa3..4cfaea4c 100644 --- a/spec/numberformat.html +++ b/spec/numberformat.html @@ -40,6 +40,10 @@

InitializeNumberFormat ( _numberFormat_, _locales_, _options_ )

The abstract operation InitializeNumberFormat accepts the arguments _numberFormat_ (which must be an object), _locales_, and _options_. It initializes _numberFormat_ as a NumberFormat object. The following steps are taken:

+

+ The following algorithm refers to UTS 35's Unicode Locale Identifier grammar. +

+ 1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_). 1. If _options_ is *undefined*, then @@ -49,6 +53,9 @@

InitializeNumberFormat ( _numberFormat_, _locales_, _options_ )

1. Let _opt_ be a new Record. 1. Let _matcher_ be ? GetOption(_options_, *"localeMatcher"*, *"string"*, « *"lookup"*, *"best fit"* », *"best fit"*). 1. Set _opt_.[[localeMatcher]] to _matcher_. + 1. Let _numberingSystem_ be ? GetOption(_options_, `"numberingSystem"`, `"string"`, *undefined*, *undefined*). + 1. If _numberingSystem_ does not match `type`, throw a *RangeError* exception. + 1. Set _opt_.[[nu]] to _numberingSystem_. 1. Let _localeData_ be %NumberFormat%.[[LocaleData]]. 1. Let _r_ be ResolveLocale(%NumberFormat%.[[AvailableLocales]], _requestedLocales_, _opt_, %NumberFormat%.[[RelevantExtensionKeys]], _localeData_). 1. Set _numberFormat_.[[Locale]] to _r_.[[locale]]. From b8dde1f6102550c88057a2893bdc2d261d3d72d2 Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Tue, 23 Apr 2019 08:19:36 +0200 Subject: [PATCH 2/5] Normative: Fix validation of options, similar to Locale --- spec/datetimeformat.html | 5 ++++- spec/numberformat.html | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/datetimeformat.html b/spec/datetimeformat.html index fa299bc0..a9397c3a 100644 --- a/spec/datetimeformat.html +++ b/spec/datetimeformat.html @@ -84,10 +84,13 @@

InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )

1. Let _matcher_ be ? GetOption(_options_, *"localeMatcher"*, *"string"*, « *"lookup"*, *"best fit"* », *"best fit"*). 1. Set _opt_.[[localeMatcher]] to _matcher_. 1. Let _calendar_ be ? GetOption(_options_, *"calendar"*, *"string"*, *undefined*, *undefined*). - 1. If _calendar_ does not match `type`, throw a *RangeError* exception. + 1. If _calendar_ is not *undefined*, then + 1. If _calendar_ does not match the `(3*8alphanum) *("-" (3*8alphanum))` sequence, throw a *RangeError* exception. 1. Set _opt_.[[ca]] to _calendar_. 1. Let _numberingSystem_ be ? GetOption(_options_, *"numberingSystem"*, *"string"*, *undefined*, *undefined*). 1. If _numberingSystem_ does not match `type`, throw a *RangeError* exception. + 1. If _numberingSystem_ is not *undefined*, then + 1. If _numberingSystem_ does not match the `(3*8alphanum) *("-" (3*8alphanum))` sequence, throw a *RangeError* exception. 1. Set _opt_.[[nu]] to _numberingSystem_. 1. Let _hour12_ be ? GetOption(_options_, *"hour12"*, *"boolean"*, *undefined*, *undefined*). 1. Let _hourCycle_ be ? GetOption(_options_, *"hourCycle"*, *"string"*, « *"h11"*, *"h12"*, *"h23"*, *"h24"* », *undefined*). diff --git a/spec/numberformat.html b/spec/numberformat.html index 4cfaea4c..2cffe6a8 100644 --- a/spec/numberformat.html +++ b/spec/numberformat.html @@ -54,7 +54,8 @@

InitializeNumberFormat ( _numberFormat_, _locales_, _options_ )

1. Let _matcher_ be ? GetOption(_options_, *"localeMatcher"*, *"string"*, « *"lookup"*, *"best fit"* », *"best fit"*). 1. Set _opt_.[[localeMatcher]] to _matcher_. 1. Let _numberingSystem_ be ? GetOption(_options_, `"numberingSystem"`, `"string"`, *undefined*, *undefined*). - 1. If _numberingSystem_ does not match `type`, throw a *RangeError* exception. + 1. If _numberingSystem_ is not *undefined*, then + 1. If _numberingSystem_ does not match the `(3*8alphanum) *("-" (3*8alphanum))` sequence, throw a *RangeError* exception. 1. Set _opt_.[[nu]] to _numberingSystem_. 1. Let _localeData_ be %NumberFormat%.[[LocaleData]]. 1. Let _r_ be ResolveLocale(%NumberFormat%.[[AvailableLocales]], _requestedLocales_, _opt_, %NumberFormat%.[[RelevantExtensionKeys]], _localeData_). From 47d50c3aa0b2a6c45d94e233d3925d84e82caffd Mon Sep 17 00:00:00 2001 From: Daniel Ehrenberg Date: Thu, 9 Jan 2020 19:54:34 +0100 Subject: [PATCH 3/5] Normative: Apply fixes suggested by anba - Convert calendar and numbering system to lowercase, analogously with canonicalizing language tags - Reference the Unicode grammar, to avoid the need to keep up to date with notational changes from upstream --- spec/datetimeformat.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/datetimeformat.html b/spec/datetimeformat.html index a9397c3a..fe56b5c7 100644 --- a/spec/datetimeformat.html +++ b/spec/datetimeformat.html @@ -74,7 +74,7 @@

InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )

- The following algorithm refers to UTS 35's Unicode Locale Identifier grammar. + The following algorithm refers to the `type` nonterminal from UTS 35's Unicode Locale Identifier grammar.

@@ -85,12 +85,13 @@

InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )

1. Set _opt_.[[localeMatcher]] to _matcher_. 1. Let _calendar_ be ? GetOption(_options_, *"calendar"*, *"string"*, *undefined*, *undefined*). 1. If _calendar_ is not *undefined*, then - 1. If _calendar_ does not match the `(3*8alphanum) *("-" (3*8alphanum))` sequence, throw a *RangeError* exception. + 1. If _calendar_ does not match the Unicode Locale Identifier `type` nonterminal, throw a *RangeError* exception. + 1. Set _calendar_ to the result of mapping _calendar_ to lower case as as specified in . 1. Set _opt_.[[ca]] to _calendar_. 1. Let _numberingSystem_ be ? GetOption(_options_, *"numberingSystem"*, *"string"*, *undefined*, *undefined*). - 1. If _numberingSystem_ does not match `type`, throw a *RangeError* exception. 1. If _numberingSystem_ is not *undefined*, then - 1. If _numberingSystem_ does not match the `(3*8alphanum) *("-" (3*8alphanum))` sequence, throw a *RangeError* exception. + 1. If _numberingSystem_ does not match the Unicode Locale Identifier `type` nonterminal, throw a *RangeError* exception. + 1. Set _numberingSystem_ to the result of mapping _numberingSystem_ to lower case as as specified in . 1. Set _opt_.[[nu]] to _numberingSystem_. 1. Let _hour12_ be ? GetOption(_options_, *"hour12"*, *"boolean"*, *undefined*, *undefined*). 1. Let _hourCycle_ be ? GetOption(_options_, *"hourCycle"*, *"string"*, « *"h11"*, *"h12"*, *"h23"*, *"h24"* », *undefined*). From 04af32b7b8649ee7107e1e94dfdcaafca5f2eadb Mon Sep 17 00:00:00 2001 From: Caio Lima Date: Thu, 23 Jan 2020 16:36:28 -0300 Subject: [PATCH 4/5] Adjusting NumberFormat's numberingSystem validation --- spec/numberformat.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/numberformat.html b/spec/numberformat.html index 2cffe6a8..50d0a30d 100644 --- a/spec/numberformat.html +++ b/spec/numberformat.html @@ -41,7 +41,7 @@

InitializeNumberFormat ( _numberFormat_, _locales_, _options_ )

- The following algorithm refers to UTS 35's Unicode Locale Identifier grammar. + The following algorithm refers to the `type` nonterminal from UTS 35's Unicode Locale Identifier grammar.

@@ -55,7 +55,8 @@

InitializeNumberFormat ( _numberFormat_, _locales_, _options_ )

1. Set _opt_.[[localeMatcher]] to _matcher_. 1. Let _numberingSystem_ be ? GetOption(_options_, `"numberingSystem"`, `"string"`, *undefined*, *undefined*). 1. If _numberingSystem_ is not *undefined*, then - 1. If _numberingSystem_ does not match the `(3*8alphanum) *("-" (3*8alphanum))` sequence, throw a *RangeError* exception. + 1. If _numberingSystem_ does not match the Unicode Locale Identifier `type` nonterminal, throw a *RangeError* exception. + 1. Set _numberingSystem_ to the result of mapping _numberingSystem_ to lower case as as specified in . 1. Set _opt_.[[nu]] to _numberingSystem_. 1. Let _localeData_ be %NumberFormat%.[[LocaleData]]. 1. Let _r_ be ResolveLocale(%NumberFormat%.[[AvailableLocales]], _requestedLocales_, _opt_, %NumberFormat%.[[RelevantExtensionKeys]], _localeData_). From 497e253fa5628acf76e885a92515ec1abd0fc47d Mon Sep 17 00:00:00 2001 From: Caio Lima Date: Mon, 10 Feb 2020 16:10:30 -0300 Subject: [PATCH 5/5] Adding case to map values properly when mapping to lower case on #sec-case-sensitivity-and-case-mapping --- spec/locales-currencies-tz.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/locales-currencies-tz.html b/spec/locales-currencies-tz.html index d7eda591..f4d62dec 100644 --- a/spec/locales-currencies-tz.html +++ b/spec/locales-currencies-tz.html @@ -9,7 +9,7 @@

Identification of Locales, Currencies, and Time Zones

Case Sensitivity and Case Mapping

- The String values used to identify locales, currencies, and time zones are interpreted in a case-insensitive manner, treating the Unicode Basic Latin characters *"A"* to *"Z"* (U+0041 to U+005A) as equivalent to the corresponding Basic Latin characters *"a"* to *"z"* (U+0061 to U+007A). No other case folding equivalences are applied. When mapping to upper case, a mapping shall be used that maps characters in the range *"a"* to *"z"* (U+0061 to U+007A) to the corresponding characters in the range *"A"* to *"Z"* (U+0041 to U+005A) and maps no other characters to the latter range. + The String values used to identify locales, currencies, and time zones are interpreted in a case-insensitive manner, treating the Unicode Basic Latin characters *"A"* to *"Z"* (U+0041 to U+005A) as equivalent to the corresponding Basic Latin characters *"a"* to *"z"* (U+0061 to U+007A). No other case folding equivalences are applied. When mapping to upper case, a mapping shall be used that maps characters in the range *"a"* to *"z"* (U+0061 to U+007A) to the corresponding characters in the range *"A"* to *"Z"* (U+0041 to U+005A) and maps no other characters to the latter range. When mapping to lower case, a mapping shall be used that maps characters in the range *"A"* to *"Z"* (U+0041 to U+005A) to the corresponding characters in the range *"a"* to *"z"* (U+0061 to U+007A) and maps no other characters to the latter range.