diff --git a/spec/annexes.html b/spec/annexes.html
index 423580f0..4e18e1eb 100644
--- a/spec/annexes.html
+++ b/spec/annexes.html
@@ -19,10 +19,7 @@
Implementation Dependent Behaviour
The set of available locales for each constructor ()
- The BestFitMatcher algorithm ()
-
-
- The BestFitSupportedLocales algorithm ()
+ The LookupMatchingLocaleByBestFit algorithm ()
diff --git a/spec/collator.html b/spec/collator.html
index bbaffec5..f0e83ffc 100644
--- a/spec/collator.html
+++ b/spec/collator.html
@@ -118,7 +118,7 @@ Intl.Collator.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.Collator%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).
diff --git a/spec/datetimeformat.html b/spec/datetimeformat.html
index 53c623c1..73e35b1a 100644
--- a/spec/datetimeformat.html
+++ b/spec/datetimeformat.html
@@ -229,7 +229,7 @@ Intl.DateTimeFormat.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.DateTimeFormat%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).
diff --git a/spec/displaynames.html b/spec/displaynames.html
index 12b98187..27614738 100644
--- a/spec/displaynames.html
+++ b/spec/displaynames.html
@@ -79,7 +79,7 @@ Intl.DisplayNames.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.DisplayNames%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).
diff --git a/spec/listformat.html b/spec/listformat.html
index b6f7b18f..c0eb8e12 100644
--- a/spec/listformat.html
+++ b/spec/listformat.html
@@ -65,7 +65,7 @@ Intl.ListFormat.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.ListFormat%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).
diff --git a/spec/locale-sensitive-functions.html b/spec/locale-sensitive-functions.html
index dde042f1..0f81d2aa 100644
--- a/spec/locale-sensitive-functions.html
+++ b/spec/locale-sensitive-functions.html
@@ -80,9 +80,9 @@
1. Else,
1. Let _requestedLocale_ be DefaultLocale().
1. Let _noExtensionsLocale_ be the String value that is _requestedLocale_ with any Unicode locale extension sequences removed.
- 1. Let _availableLocales_ be a List with language tags that includes the languages for which the Unicode Character Database contains language sensitive case mappings. Implementations may add additional language tags if they support case mapping for additional locales.
- 1. Let _locale_ be BestAvailableLocale(_availableLocales_, _noExtensionsLocale_).
- 1. If _locale_ is *undefined*, set _locale_ to *"und"*.
+ 1. Let _availableLocales_ be an Available Locales List which includes the language tags for which the Unicode Character Database contains language-sensitive case mappings. If the implementation supports additional locale-sensitive case mappings, _availableLocales_ should also include their corresponding language tags.
+ 1. Let _match_ be LookupMatchingLocaleByPrefix(_availableLocales_, _noExtensionsLocale_).
+ 1. If _match_ is not *undefined*, let _locale_ be _match_.[[locale]]; else let _locale_ be *"und"*.
1. Let _codePoints_ be StringToCodePoints(_S_).
1. If _targetCase_ is ~lower~, then
1. Let _newCodePoints_ be a List whose elements are the result of a lowercase transformation of _codePoints_ according to an implementation-derived algorithm using _locale_ or the Unicode Default Case Conversion algorithm.
diff --git a/spec/negotiation.html b/spec/negotiation.html
index 6574b423..4963328d 100644
--- a/spec/negotiation.html
+++ b/spec/negotiation.html
@@ -2,7 +2,15 @@
Locale and Parameter Negotiation
- Service constructors use a common pattern to negotiate the requests represented by their _locales_ and _options_ arguments against the actual capabilities of their implementations. That common behaviour is explained here in terms of internal slots describing the capabilities and abstract operations using these internal slots.
+ Service constructors use common patterns to negotiate the requests represented by _locales_ and _options_ arguments against the actual capabilities of an implementation. That common behaviour is explained here in terms of internal slots describing the capabilities, abstract operations using these internal slots, and specialized data types defined below.
+
+
+
+ An Available Locales List is an arbitrarily-ordered duplicate-free List of language tags, each of which is structurally valid, canonicalized, and lacks a Unicode locale extension sequence. It represents all locales for which the implementation provides functionality within a particular context.
+
+
+
+ A language priority list is a List of structurally valid and canonicalized language tags representing a sequence of locale preferences by descending priority. It corresponds with the term of the same name defined in BCP 47 at RFC 4647 section 2.3 but prohibits *"\*"* elements and contains only canonicalized contents.
@@ -13,30 +21,31 @@ Internal slots of Service Constructors
- - [[AvailableLocales]] is a List that contains structurally valid () and canonicalized () language tags identifying the locales for which the implementation provides the functionality of the constructed objects. Language tags on the list must not have a Unicode locale extension sequence. The list must include the value returned by the DefaultLocale abstract operation (), and must not include duplicates. Implementations must include in [[AvailableLocales]] locales that can serve as fallbacks in the algorithm used to resolve locales (see ). For example, implementations that provide a *"de-DE"* locale must include a *"de"* locale that can serve as a fallback for requests such as *"de-AT"* and *"de-CH"*. For locales that include a script subtag in addition to language and region, the corresponding locale without a script subtag must also be supported; that is, if an implementation recognizes *"zh-Hant-TW"*, it is also expected to recognize *"zh-TW"*. The ordering of the locales within [[AvailableLocales]] is irrelevant.
+ - [[AvailableLocales]] is an Available Locales List. It must include the value returned by DefaultLocale. Additionally, for each element with more than one subtag, it must also include a less narrow language tag with the same language subtag and a strict subset of the same following subtags (i.e., omitting one or more) to serve as a potential fallback from ResolveLocale. In particular, each element with a language subtag and a script subtag and a region subtag must be accompanied by another element consisting of only the same language subtag and region subtag but missing the script subtag. For example,
+
+ - If [[AvailableLocales]] contains *"de-DE"*, then it must also contain *"de"* (which might be selected to satisfy requested locales such as *"de-AT"* and *"de-CH"*).
+ - If [[AvailableLocales]] contains *"az-Latn-AZ"*, then it must also contain *"az-AZ"* (which might be selected to satisfy requested locales such as *"az-Cyrl-AZ"* if *"az-Cyrl"* is unavailable).
+
+
- [[RelevantExtensionKeys]] is a List of Unicode locale extension sequence keys defined in Unicode Technical Standard #35 Part 1 Core, Section 3.6.1 Key and Type Definitions that are relevant for the functionality of the constructed objects.
- - [[SortLocaleData]] and [[SearchLocaleData]] (for Intl.Collator) and [[LocaleData]] (for every other service constructor) are Records that have fields for each locale contained in [[AvailableLocales]]. The value of each of these fields must be a Record in which each element of [[RelevantExtensionKeys]] identifies the name of a field whose value is a non-empty List of Strings representing the type values that are supported by the implementation in the relevant locale for the corresponding Unicode locale extension sequence key, with the first element providing the default value for that key in the locale.
+ - [[SortLocaleData]] and [[SearchLocaleData]] (for Intl.Collator) and [[LocaleData]] (for every other service constructor) are Records. In addition to fields specific to its service constructor, each such Record has a field for each locale contained in [[AvailableLocales]]. The value of each such locale-named field is a Record in which each element of [[RelevantExtensionKeys]] identifies the name of a field whose value is a non-empty List of Strings representing the type values that are supported by the implementation in the relevant locale for the corresponding Unicode locale extension sequence key, with the first element providing the default value for that key in the locale.
For example, an implementation of DateTimeFormat might include the language tag *"fa-IR"* in its [[AvailableLocales]] internal slot, and must (according to ) include the keys *"ca"*, *"hc"*, and *"nu"* in its [[RelevantExtensionKeys]] internal slot.
The default calendar for that locale is usually *"persian"*, but an implementation might also support *"gregory"*, *"islamic"*, and *"islamic-civil"*.
- The Record in the DateTimeFormat [[LocaleData]] internal slot would therefore include a [[fa-IR]] field whose value is a Record like { [[ca]]: « *"persian"*, *"gregory"*, *"islamic"*, *"islamic-civil"* », [[hc]]: « … », [[nu]]: « … » }, along with other locale-named fields having the same value shape but different elements in their Lists.
+ The Record in the DateTimeFormat [[LocaleData]] internal slot would therefore include a [[fa-IR]] field whose value is a Record like { [[ca]]: « *"persian"*, *"gregory"*, *"islamic"*, *"islamic-civil"* », [[hc]]: « … », [[nu]]: « … » }, along with other locale-named fields having the same value shape but different elements in their Lists.
Abstract Operations
-
- Where the following abstract operations take an _availableLocales_ argument, it must be an [[AvailableLocales]] List as specified in .
-
-
CanonicalizeLocaleList (
_locales_: an ECMAScript language value,
- ): either a normal completion containing a List of Unicode canonicalized locale identifiers or a throw completion
+ ): either a normal completion containing a language priority list or a throw completion
@@ -76,72 +85,48 @@
-
-
- BestAvailableLocale (
- _availableLocales_: a List of Unicode canonicalized locale identifiers,
- _locale_: a Unicode canonicalized locale identifier,
- ): a Unicode canonicalized locale identifier or *undefined*
-
-
-
- 1. Let _candidate_ be _locale_.
- 1. Repeat,
- 1. If _availableLocales_ contains _candidate_, return _candidate_.
- 1. Let _pos_ be the index into _candidate_ of the last occurrence of *"-"* (code unit 0x002D HYPHEN-MINUS). If that character does not occur, return *undefined*.
- 1. Repeat, while _pos_ ≥ 2 and the substring of _candidate_ from _pos_ - 2 to _pos_ - 1 is *"-"*,
- 1. Set _pos_ to _pos_ - 2.
- 1. Set _candidate_ to the substring of _candidate_ from 0 to _pos_.
-
-
-
- When _locale_ includes a Unicode Technical Standard #35 Part 1 Core BCP 47 T Extension subtag sequence, the truncation in this algorithm may temporarily generate invalid language tags. However, none of them will be returned because _availableLocales_ contains only valid language tags.
-
-
-
-
+
- LookupMatcher (
- _availableLocales_: a List of Unicode canonicalized locale identifiers,
- _requestedLocales_: a List of Unicode canonicalized locale identifiers,
- ): a Record with fields [[locale]] (a Unicode canonicalized locale identifier) and [[extension]] (a Unicode locale extension sequence or ~empty~)
+ LookupMatchingLocaleByPrefix (
+ _availableLocales_: an Available Locales List,
+ _requestedLocales_: a language priority list,
+ ): a Record with fields [[locale]] (a Unicode canonicalized locale identifier) and [[extension]] (a Unicode locale extension sequence or ~empty~) or *undefined*
1. For each element _locale_ of _requestedLocales_, do
- 1. Let _noExtensionsLocale_ be the String value that is _locale_ with any Unicode locale extension sequences removed.
- 1. Let _availableLocale_ be BestAvailableLocale(_availableLocales_, _noExtensionsLocale_).
- 1. If _availableLocale_ is not *undefined*, then
- 1. If _locale_ and _noExtensionsLocale_ are not the same String value, then
- 1. Let _extension_ be the String value consisting of the substring of the Unicode locale extension sequence within _locale_.
- 1. Else,
- 1. Let _extension_ be ~empty~.
- 1. Return the Record { [[locale]]: _availableLocale_, [[extension]]: _extension_ }.
- 1. Let _defLocale_ be DefaultLocale().
- 1. Return the Record { [[locale]]: _defLocale_, [[extension]]: ~empty~ }.
+ 1. Let _extension_ be ~empty~.
+ 1. If _locale_ contains a Unicode locale extension sequence, then
+ 1. Set _extension_ to the Unicode locale extension sequence of _locale_.
+ 1. Set _locale_ to the String value that is _locale_ with any Unicode locale extension sequences removed.
+ 1. Let _prefix_ be _locale_.
+ 1. Repeat, while _prefix_ is not the empty String,
+ 1. If _availableLocales_ contains _prefix_, return the Record { [[locale]]: _prefix_, [[extension]]: _extension_ }.
+ 1. If _prefix_ contains *"-"* (code unit 0x002D HYPHEN-MINUS), let _pos_ be the index into _prefix_ of the last occurrence of *"-"*; else let _pos_ be 0.
+ 1. Repeat, while _pos_ ≥ 2 and the substring of _prefix_ from _pos_ - 2 to _pos_ - 1 is *"-"*,
+ 1. Set _pos_ to _pos_ - 2.
+ 1. Set _prefix_ to the substring of _prefix_ from 0 to _pos_.
+ 1. Return *undefined*.
- The algorithm is based on the Lookup algorithm described in RFC 4647 section 3.4, but options specified through Unicode locale extension sequences are ignored in the lookup. Information about such subsequences is returned separately. The abstract operation returns a record with a [[locale]] field, whose value is the language tag of the selected locale, which must be an element of _availableLocales_. If the language tag of the request locale that led to the selected locale contained a Unicode locale extension sequence, then the returned record also contains an [[extension]] field whose value is the substring of the Unicode locale extension sequence within the request locale language tag.
+ When a requested locale includes a Unicode Technical Standard #35 Part 1 Core BCP 47 T Extension subtag sequence, the truncation in this algorithm may temporarily generate invalid language tags. However, none of them will be returned because _availableLocales_ contains only valid language tags.
-
+
- BestFitMatcher (
- _availableLocales_: a List of Unicode canonicalized locale identifiers,
- _requestedLocales_: a List of Unicode canonicalized locale identifiers,
- ): a Record with fields [[locale]] (a Unicode canonicalized locale identifier) and [[extension]] (a Unicode locale extension sequence or ~empty~)
+ LookupMatchingLocaleByBestFit (
+ _availableLocales_: an Available Locales List,
+ _requestedLocales_: a language priority list,
+ ): a Record with fields [[locale]] (a Unicode canonicalized locale identifier) and [[extension]] (a Unicode locale extension sequence or ~empty~), or *undefined*
@@ -211,8 +196,8 @@
ResolveLocale (
- _availableLocales_: a List of Unicode canonicalized locale identifiers,
- _requestedLocales_: a List of Unicode canonicalized locale identifiers,
+ _availableLocales_: an Available Locales List,
+ _requestedLocales_: a language priority list,
_options_: a Record,
_relevantExtensionKeys_: a List of Strings,
_localeData_: a Record,
@@ -220,14 +205,15 @@
1. Let _matcher_ be _options_.[[localeMatcher]].
1. If _matcher_ is *"lookup"*, then
- 1. Let _r_ be LookupMatcher(_availableLocales_, _requestedLocales_).
+ 1. Let _r_ be LookupMatchingLocaleByPrefix(_availableLocales_, _requestedLocales_).
1. Else,
- 1. Let _r_ be BestFitMatcher(_availableLocales_, _requestedLocales_).
+ 1. Let _r_ be LookupMatchingLocaleByBestFit(_availableLocales_, _requestedLocales_).
+ 1. If _r_ is *undefined*, set _r_ to the Record { [[locale]]: DefaultLocale(), [[extension]]: ~empty~ }.
1. Let _foundLocale_ be _r_.[[locale]].
1. Let _foundLocaleData_ be _localeData_.[[<_foundLocale_>]].
1. Assert: Type(_foundLocaleData_) is Record.
@@ -275,66 +261,32 @@
1. Set _result_.[[Locale]] to InsertUnicodeExtensionAndCanonicalize(_foundLocale_, _supportedExtension_).
1. Return _result_.
-
-
- Non-normative summary: Two algorithms are available to match the locales: the Lookup algorithm described in RFC 4647 section 3.4, and an implementation dependent best-fit algorithm. Independent of the locale matching algorithm, options specified through Unicode locale extension sequences are negotiated separately, taking the caller's relevant extension keys and locale data into consideration as well as the client-provided options. The abstract operation returns a Record with a field for each key in _relevantExtensionKeys_, containing the selected values for those keys. This Record also contains a [[locale]] field which stores the language tag of the selected locale with Unicode locale extension sequence key
subtags restricted to those in _relevantExtensionKeys_. If an extension's value is specified in the Unicode locale extension sequence and a different value for that extension is specified in an option, the value from the option is used to set the value of the corresponding field and the overridden extension keyword (the key
subtag along with any immediately following type
subtags and associated separators) is removed from the string stored in [[locale]].
-
-
-
-
-
- LookupSupportedLocales (
- _availableLocales_: a List of Unicode canonicalized locale identifiers,
- _requestedLocales_: a List of Unicode canonicalized locale identifiers,
- ): a List of Unicode canonicalized locale identifiers
-
-
-
- 1. Let _subset_ be a new empty List.
- 1. For each element _locale_ of _requestedLocales_, do
- 1. Let _noExtensionsLocale_ be the String value that is _locale_ with any Unicode locale extension sequences removed.
- 1. Let _availableLocale_ be BestAvailableLocale(_availableLocales_, _noExtensionsLocale_).
- 1. If _availableLocale_ is not *undefined*, append _locale_ to _subset_.
- 1. Return _subset_.
-
-
+
- BestFitSupportedLocales (
- _availableLocales_: a List of Unicode canonicalized locale identifiers,
- _requestedLocales_: a List of Unicode canonicalized locale identifiers,
- ): a List of Unicode canonicalized locale identifiers
-
-
-
-
-
-
- SupportedLocales (
- _availableLocales_: a List of Unicode canonicalized locale identifiers,
- _requestedLocales_: a List of Unicode canonicalized locale identifiers,
+ FilterLocales (
+ _availableLocales_: an Available Locales List,
+ _requestedLocales_: a language priority list,
_options_: an ECMAScript language value,
): either a normal completion containing a List of Unicode canonicalized locale identifiers or a throw completion
1. Set _options_ to ? CoerceOptionsToObject(_options_).
1. Let _matcher_ be ? GetOption(_options_, *"localeMatcher"*, ~string~, « *"lookup"*, *"best fit"* », *"best fit"*).
- 1. If _matcher_ is *"best fit"*, then
- 1. Let _supportedLocales_ be BestFitSupportedLocales(_availableLocales_, _requestedLocales_).
- 1. Else,
- 1. Let _supportedLocales_ be LookupSupportedLocales(_availableLocales_, _requestedLocales_).
- 1. Return CreateArrayFromList(_supportedLocales_).
+ 1. Let _subset_ be a new empty List.
+ 1. For each element _locale_ of _requestedLocales_, do
+ 1. Let _noExtensionsLocale_ be the String value that is _locale_ with any Unicode locale extension sequences removed.
+ 1. If _matcher_ is *"lookup"*, then
+ 1. Let _match_ be LookupMatchingLocaleByPrefix(_availableLocales_, _noExtensionsLocale_).
+ 1. Else,
+ 1. Let _match_ be LookupMatchingLocaleByBestFit(_availableLocales_, _noExtensionsLocale_).
+ 1. If _match_ is not *undefined*, append _locale_ to _subset_.
+ 1. Return CreateArrayFromList(_subset_).
diff --git a/spec/numberformat.html b/spec/numberformat.html
index 4a0d810a..65ff65da 100644
--- a/spec/numberformat.html
+++ b/spec/numberformat.html
@@ -255,7 +255,7 @@ Intl.NumberFormat.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.NumberFormat%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).
diff --git a/spec/pluralrules.html b/spec/pluralrules.html
index 7bd66cbc..f251629c 100644
--- a/spec/pluralrules.html
+++ b/spec/pluralrules.html
@@ -78,7 +78,7 @@ Intl.PluralRules.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.PluralRules%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).
diff --git a/spec/relativetimeformat.html b/spec/relativetimeformat.html
index cfba310b..ee3edf96 100644
--- a/spec/relativetimeformat.html
+++ b/spec/relativetimeformat.html
@@ -90,7 +90,7 @@ Intl.RelativeTimeFormat.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.RelativeTimeFormat%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).
diff --git a/spec/segmenter.html b/spec/segmenter.html
index 6cafb0e2..f16618c6 100644
--- a/spec/segmenter.html
+++ b/spec/segmenter.html
@@ -61,7 +61,7 @@ Intl.Segmenter.supportedLocalesOf ( _locales_ [ , _options_ ] )
1. Let _availableLocales_ be %Intl.Segmenter%.[[AvailableLocales]].
1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locales_).
- 1. Return ? SupportedLocales(_availableLocales_, _requestedLocales_, _options_).
+ 1. Return ? FilterLocales(_availableLocales_, _requestedLocales_, _options_).