Bug 1509583 - Refactor mozIntl.getRegions to mozIntl.getAvailableLocaleDisplayNames. r=jfkthame,MattN
authorZibi Braniecki <zbraniecki@mozilla.com>
Fri, 11 Jan 2019 00:25:52 +0000
changeset 453425 9d7f77b05ae7ed2a809e2ecf3d7c76974c9e62f7
parent 453424 f8e2d2010c07418ea0916bb6a5679e872958d6e9
child 453426 8d5e2931f526c53bf8ca86250c3caea6441b5614
push id35357
push usernerli@mozilla.com
push dateFri, 11 Jan 2019 21:54:07 +0000
treeherdermozilla-central@0ce024c91511 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame, MattN
bugs1509583
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1509583 - Refactor mozIntl.getRegions to mozIntl.getAvailableLocaleDisplayNames. r=jfkthame,MattN Differential Revision: https://phabricator.services.mozilla.com/D13188
browser/extensions/formautofill/FormAutofill.jsm
intl/docs/dataintl.rst
toolkit/components/mozintl/mozIMozIntl.idl
toolkit/components/mozintl/mozIntl.js
toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js
--- a/browser/extensions/formautofill/FormAutofill.jsm
+++ b/browser/extensions/formautofill/FormAutofill.jsm
@@ -70,11 +70,19 @@ XPCOMUtils.defineLazyPreferenceGetter(Fo
 XPCOMUtils.defineLazyPreferenceGetter(FormAutofill,
                                       "isAutofillAddressesFirstTimeUse", ADDRESSES_FIRST_TIME_USE_PREF);
 XPCOMUtils.defineLazyPreferenceGetter(FormAutofill,
                                       "AutofillCreditCardsUsedStatus", CREDITCARDS_USED_STATUS_PREF);
 XPCOMUtils.defineLazyPreferenceGetter(FormAutofill,
                                       "supportedCountries", SUPPORTED_COUNTRIES_PREF, null, null,
                                       val => val.split(","));
 
+// XXX: This should be invalidated on intl:app-locales-changed.
 XPCOMUtils.defineLazyGetter(FormAutofill, "countries", () => {
-  return Services.intl.getRegions(undefined);
+  let availableRegionCodes = Services.intl.getAvailableLocaleDisplayNames("region");
+  let displayNames = Services.intl.getRegionDisplayNames(undefined, availableRegionCodes);
+  let result = new Map();
+  for (let i = 0; i < availableRegionCodes.length; i++) {
+    result.set(availableRegionCodes[i].toUpperCase(), displayNames[i]);
+  }
+  return result;
 });
+
--- a/intl/docs/dataintl.rst
+++ b/intl/docs/dataintl.rst
@@ -310,16 +310,30 @@ API which returns a list of region names
 
 Example:
 
 .. code-block:: javascript
 
   let locs = getLanguageDisplayNames(["pl"], ["sr-RU", "es-MX", "fr-CA"]);
   locs === ["Serbski (Rosja)", "HiszpaƄski (Meksyk)", "Francuski (Kanada)"];
 
+mozIntl.getAvailableLocaleDisplayNames(type)
+---------------------------------------------------
+
+API which returns a list of locale display name codes available for a
+given type.
+Available types are: "region".
+
+Example:
+
+.. code-block:: javascript
+
+  let codes = getAvailableLocaleDisplayNames("region");
+  codes === ["au", "ae", "af", ...];
+
 Best Practices
 ==============
 
 The most important best practice when dealing with data internationalization is to
 perform it as close to the actual UI as possible; right before the UI is displayed.
 
 The reason for this practice is that internationalized data is considered *"opaque"*,
 which means that no code should ever attempt to operate on it. Late resolution also
--- a/toolkit/components/mozintl/mozIMozIntl.idl
+++ b/toolkit/components/mozintl/mozIMozIntl.idl
@@ -37,34 +37,35 @@
 [scriptable, uuid(7f63279a-1a29-4ae6-9e7a-dc9684a23530)]
 interface mozIMozIntl : nsISupports
 {
   jsval getCalendarInfo([optional] in jsval locales);
   jsval getDisplayNames([optional] in jsval locales, [optional] in jsval options);
   jsval getLocaleInfo([optional] in jsval locales);
 
   /**
+   * Returns a list of locale codes for a given type.
+   * At the moment only type="region" is supported.
+   *
+   * Example:
+   *   let codes = getAvailableLocaleDisplayNames("region");
+   *   codes === ["ar", "ae", "af", ...]
+   */
+  jsval getAvailableLocaleDisplayNames(in jsval type);
+
+  /**
    * Returns a list of language names formatted for display.
    *
    * Example:
    *   let langs = getLanguageDisplayNames(["pl"], ["fr", "de", "en"]);
    *   langs === ["Francuski", "Niemiecki", "Angielski"]
    */
   jsval getLanguageDisplayNames(in jsval locales, in jsval langCodes);
 
   /**
-   * Returns a list of region codes.
-   *
-   * Example:
-   *   let regs = getRegions(undefined);
-   *   regs === new Map([["US", "United States"], ["CA", "Canada"], ["MX", "Mexico"]])
-   */
-  jsval getRegions(in jsval locales);
-
-  /**
    * Returns a list of region names formatted for display.
    *
    * Example:
    *   let regs = getRegionDisplayNames(["pl"], ["US", "CA", "MX"]);
    *   regs === ["Stany Zjednoczone", "Kanada", "Meksyk"]
    */
   jsval getRegionDisplayNames(in jsval locales, in jsval regionCodes);
 
--- a/toolkit/components/mozintl/mozIntl.js
+++ b/toolkit/components/mozintl/mozIntl.js
@@ -146,18 +146,93 @@ const threshold = {
   month: 2, // at least 2 months before using year.
   // week: 4, // at least 4 weeks before using month.
   day: 6, // at least 6 days before using month.
   hour: 6, // at least 6 hours before using day.
   minute: 59, // at least 59 minutes before using hour.
   second: 59, // at least 59 seconds before using minute.
 };
 
+/**
+ * Notice: If you're updating this list, you should also
+ *         update the list in
+ *         languageNames.ftl and regionNames.ftl.
+ */
+const availableLocaleDisplayNames = {
+  region: new Set([
+    "ad", "ae", "af", "ag", "ai", "al", "am", "ao",
+    "aq", "ar", "as", "at", "au", "aw", "az", "ba",
+    "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj",
+    "bl", "bm", "bn", "bo", "bq", "br", "bs", "bt",
+    "bv", "bw", "by", "bz", "ca", "cc", "cd", "cf",
+    "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co",
+    "cp", "cr", "cu", "cv", "cw", "cx", "cy", "cz",
+    "de", "dg", "dj", "dk", "dm", "do", "dz", "ec",
+    "ee", "eg", "eh", "er", "es", "et", "fi", "fj",
+    "fk", "fm", "fo", "fr", "ga", "gb", "gd", "ge",
+    "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp",
+    "gq", "gr", "gs", "gt", "gu", "gw", "gy", "hk",
+    "hm", "hn", "hr", "ht", "hu", "id", "ie", "il",
+    "im", "in", "io", "iq", "ir", "is", "it", "je",
+    "jm", "jo", "jp", "ke", "kg", "kh", "ki", "km",
+    "kn", "kp", "kr", "kw", "ky", "kz", "la", "lb",
+    "lc", "li", "lk", "lr", "ls", "lt", "lu", "lv",
+    "ly", "ma", "mc", "md", "me", "mf", "mg", "mh",
+    "mk", "ml", "mm", "mn", "mo", "mp", "mq", "mr",
+    "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz",
+    "na", "nc", "ne", "nf", "ng", "ni", "nl", "no",
+    "np", "nr", "nu", "nz", "om", "pa", "pe", "pf",
+    "pg", "ph", "pk", "pl", "pm", "pn", "pr", "pt",
+    "pw", "py", "qa", "qm", "qs", "qu", "qw", "qx",
+    "qz", "re", "ro", "rs", "ru", "rw", "sa", "sb",
+    "sc", "sd", "se", "sg", "sh", "si", "sk", "sl",
+    "sm", "sn", "so", "sr", "ss", "st", "sv", "sx",
+    "sy", "sz", "tc", "td", "tf", "tg", "th", "tj",
+    "tk", "tl", "tm", "tn", "to", "tr", "tt", "tv",
+    "tw", "tz", "ua", "ug", "us", "uy", "uz", "va",
+    "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws",
+    "xa", "xb", "xc", "xd", "xe", "xg", "xh", "xj",
+    "xk", "xl", "xm", "xp", "xq", "xr", "xs", "xt",
+    "xu", "xv", "xw", "ye", "yt", "za", "zm", "zw",
+  ]),
+  "language": new Set([
+    "aa", "ab", "ach", "ae", "af", "ak", "am", "an",
+    "ar", "as", "ast", "av", "ay", "az", "ba", "be",
+    "bg", "bh", "bi", "bm", "bn", "bo", "br", "bs",
+    "ca", "cak", "ce", "ch", "co", "cr", "crh", "cs",
+    "csb", "cu", "cv", "cy", "da", "de", "dsb", "dv",
+    "dz", "ee", "el", "en", "eo", "es", "et", "eu",
+    "fa", "ff", "fi", "fj", "fo", "fr", "fur", "fy",
+    "ga", "gd", "gl", "gn", "gu", "gv", "ha", "haw",
+    "he", "hi", "hil", "ho", "hr", "hsb", "ht", "hu",
+    "hy", "hz", "ia", "id", "ie", "ig", "ii", "ik",
+    "io", "is", "it", "iu", "ja", "jv", "ka", "kab",
+    "kg", "ki", "kj", "kk", "kl", "km", "kn", "ko",
+    "kok", "kr", "ks", "ku", "kv", "kw", "ky", "la",
+    "lb", "lg", "li", "lij", "ln", "lo", "lt", "ltg",
+    "lu", "lv", "mai", "meh", "mg", "mh", "mi", "mix",
+    "mk", "ml", "mn", "mr", "ms", "mt", "my", "na",
+    "nb", "nd", "ne", "ng", "nl", "nn", "no", "nr",
+    "nso", "nv", "ny", "oc", "oj", "om", "or", "os",
+    "pa", "pi", "pl", "ps", "pt", "qu", "rm", "rn",
+    "ro", "ru", "rw", "sa", "sc", "sd", "se", "sg",
+    "si", "sk", "sl", "sm", "sn", "so", "son", "sq",
+    "sr", "ss", "st", "su", "sv", "sw", "ta", "te",
+    "tg", "th", "ti", "tig", "tk", "tl", "tlh", "tn",
+    "to", "tr", "ts", "tt", "tw", "ty", "ug", "uk",
+    "ur", "uz", "ve", "vi", "vo", "wa", "wen", "wo",
+    "xh", "yi", "yo", "za", "zam", "zh", "zu",
+  ]),
+};
+
 class MozIntl {
   constructor() {
+    // XXX: We should add an observer on
+    //      intl:app-locales-changed to invalidate
+    //      the cache.
     this._cache = {};
   }
 
   getCalendarInfo(locales, ...args) {
     if (!this._cache.hasOwnProperty("getCalendarInfo")) {
       mozIntlHelper.addGetCalendarInfo(this._cache);
     }
 
@@ -175,16 +250,24 @@ class MozIntl {
   getLocaleInfo(locales, ...args) {
     if (!this._cache.hasOwnProperty("getLocaleInfo")) {
       mozIntlHelper.addGetLocaleInfo(this._cache);
     }
 
     return this._cache.getLocaleInfo(getLocales(locales), ...args);
   }
 
+  getAvailableLocaleDisplayNames(type) {
+    if (availableLocaleDisplayNames.hasOwnProperty(type)) {
+      return Array.from(availableLocaleDisplayNames[type]);
+    }
+
+    return new Error("Unimplemented!");
+  }
+
   getLanguageDisplayNames(locales, langCodes) {
     if (locales !== undefined) {
       throw new Error("First argument support not implemented yet");
     }
     const languageBundle = Services.strings.createBundle(
           "chrome://global/locale/languageNames.properties");
 
     return langCodes.map(langCode => {
@@ -194,37 +277,16 @@ class MozIntl {
       try {
         return languageBundle.GetStringFromName(langCode.toLowerCase());
       } catch (e) {
         return langCode.toLowerCase(); // Fall back to raw language subtag.
       }
     });
   }
 
-  getRegions(locales) {
-    if (locales !== undefined) {
-      throw new Error("First argument support not implemented yet");
-    }
-
-    if (!this._cache.hasOwnProperty("regionBundle")) {
-      const regionBundle = Services.strings.createBundle(
-        "chrome://global/locale/regionNames.properties");
-      this._cache.regionBundle = regionBundle;
-    }
-
-    if (!this._cache.hasOwnProperty("regionMap")) {
-      this._cache.regionMap = new Map([...this._cache.regionBundle.getSimpleEnumeration()].map(prop => {
-        prop.QueryInterface(Ci.nsIPropertyElement);
-        return [prop.key.toUpperCase(), prop.value];
-      }));
-    }
-
-    return this._cache.regionMap;
-  }
-
   getRegionDisplayNames(locales, regionCodes) {
     if (locales !== undefined) {
       throw new Error("First argument support not implemented yet");
     }
 
     if (!this._cache.hasOwnProperty("regionBundle")) {
       const regionBundle = Services.strings.createBundle(
         "chrome://global/locale/regionNames.properties");
--- a/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js
+++ b/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js
@@ -1,16 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 
 const gLangDN = Services.intl.getLanguageDisplayNames.bind(Services.intl, undefined);
-const gReg = Services.intl.getRegions.bind(Services.intl, undefined);
+const gAvLocDN = Services.intl.getAvailableLocaleDisplayNames.bind(Services.intl);
 const gRegDN = Services.intl.getRegionDisplayNames.bind(Services.intl, undefined);
 const gLocDN = Services.intl.getLocaleDisplayNames.bind(Services.intl, undefined);
 
 add_test(function test_valid_language_tag() {
   deepEqual(gLocDN([]), []);
   deepEqual(gLocDN(["en"]), ["English"]);
   deepEqual(gLocDN(["und"]), ["und"]);
   run_next_test();