tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

best-available-locale-from-default-locale.js (5023B)


      1 // |reftest| skip-if(!this.hasOwnProperty('Intl'))
      2 
      3 if (typeof getDefaultLocale === "undefined") {
      4    var getDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().getDefaultLocale;
      5 }
      6 if (typeof setDefaultLocale === "undefined") {
      7    var setDefaultLocale = SpecialPowers.Cu.getJSTestingFunctions().setDefaultLocale;
      8 }
      9 
     10 let defaultLocale = null;
     11 
     12 function withLocale(locale, fn) {
     13    if (defaultLocale === null)
     14        defaultLocale = getDefaultLocale();
     15 
     16    setDefaultLocale(locale);
     17    try {
     18        fn();
     19    } finally {
     20        setDefaultLocale(defaultLocale);
     21    }
     22 }
     23 
     24 // This test assumes Azerbaijani ("az") is a supported locale.
     25 const supported = Intl.Collator.supportedLocalesOf("az");
     26 assertEq(supported.length, 1);
     27 assertEq(supported[0], "az");
     28 
     29 withLocale("az", () => {
     30    // Ensure the new default locale is now active.
     31    assertEq(new Intl.Collator().resolvedOptions().locale, "az");
     32 
     33    // "az" is the active default locale, so explicitly requesting "az" should succeed.
     34    assertEq(new Intl.Collator("az").resolvedOptions().locale, "az");
     35 
     36    // ICU doesn't provide a specialised "az-Cyrl" locale, so we fallback to "az".
     37    assertEq(new Intl.Collator("az-Cyrl").resolvedOptions().locale, "az");
     38 
     39    // ICU doesn't provide a specialised "az-Cyrl-AZ" locale, so we fallback to "az".
     40    assertEq(new Intl.Collator("az-Cyrl-AZ").resolvedOptions().locale, "az");
     41 });
     42 
     43 // As demonstrated above, "az-Cyrl-AZ" normally isn't a supported Intl.Collator locale. But when
     44 // used as the default locale, it gets promoted to being supported, because its parent locale "az"
     45 // is supported and can act as a fallback.
     46 //
     47 // This works as follows:
     48 // We accept any default locale as long as it can be supported either explicitly or implicitly
     49 // through a fallback. But when we claim a default locale is supported, we also need to make sure
     50 // we report any parent locale as being supported. So when "az-Cyrl-AZ" is accepted as the
     51 // default locale, we also need to report its parent locale "az-Cyrl" as a supported locale.
     52 //
     53 // The reason we're doing this, is to make sure we aren't limiting the supported default locale to
     54 // the intersection of the sets of supported locales for each Intl service constructor. Also see
     55 // the requirements in <https://tc39.es/ecma402/#sec-internal-slots>, which state that the default
     56 // locale must be a member of [[AvailableLocales]] for every Intl service constructor.
     57 //
     58 // So the following statement must hold:
     59 //
     60 // ∀ Constructor ∈ IntlConstructors: DefaultLocale ∈ Constructor.[[AvailableLocales]]
     61 //
     62 // This can trivially be achieved when we restrict the default locale to:
     63 //
     64 //                 { RequestedLocale            if RequestedLocale ∈ (∩ C.[[AvailableLocales]])
     65 //                 {                                                  C ∈ IntlConstructors
     66 //                 {
     67 // DefaultLocale = { Fallback(RequestedLocale)  if Fallback(RequestedLocale) ∈ (∩ C.[[AvailableLocales]])
     68 //                 {                                                            C ∈ IntlConstructors
     69 //                 {
     70 //                 { LastDitchLocale            otherwise
     71 //
     72 // But that severely restricts the possible default locales. For example, "az-Cyrl-AZ" is supported
     73 // by all Intl constructors except Intl.Collator. Intl.Collator itself only provides explicit
     74 // support for the parent locale "az". So with the trivial solution we'd need to mark "az-Cyrl-AZ"
     75 // as an invalid default locale and instead use its fallback locale "az".
     76 //
     77 // So instead of that we're using the following approach:
     78 //
     79 //                 { RequestedLocale    if RequestedLocale ∈ (∩ C.[[AvailableLocales]])
     80 //                 {                                          C ∈ IntlConstructors
     81 //                 {
     82 // DefaultLocale = { RequestedLocale    if Fallback(RequestedLocale) ∈ (∩ C.[[AvailableLocales]])
     83 //                 {                                                    C ∈ IntlConstructors
     84 //                 {
     85 //                 { LastDitchLocale    otherwise
     86 //
     87 // So even when the requested default locale is only implicitly supported through a fallback, we
     88 // still accept it as a valid default locale.
     89 withLocale("az-Cyrl-AZ", () => {
     90    // Ensure the new default locale is now active.
     91    assertEq(new Intl.Collator().resolvedOptions().locale, "az-Cyrl-AZ");
     92 
     93    // "az-Cyrl-AZ" is the active default locale, so explicitly requesting the parent locale
     94    // "az" should succeed.
     95    assertEq(new Intl.Collator("az").resolvedOptions().locale, "az");
     96 
     97    // "az-Cyrl-AZ" is the active default locale, so explicitly requesting the parent locale
     98    // "az-Cyrl" should succeed.
     99    assertEq(new Intl.Collator("az-Cyrl").resolvedOptions().locale, "az-Cyrl");
    100 
    101    // "az-Cyrl-AZ" is the active default locale, so explicitly requesting "az-Cyrl-AZ"
    102    // should succeed.
    103    assertEq(new Intl.Collator("az-Cyrl-AZ").resolvedOptions().locale, "az-Cyrl-AZ");
    104 });
    105 
    106 if (typeof reportCompare === "function")
    107    reportCompare(0, 0);