Merge inbound to mozilla-central a=merge
authorCoroiu Cristina <ccoroiu@mozilla.com>
Mon, 24 Sep 2018 12:48:00 +0300
changeset 493587 095ec59a8800
parent 493575 def8d4c0a39f (current diff)
parent 493586 29e7b5d5f5e4 (diff)
child 493594 5bd44d836cbf
child 493629 6bdeee726a7e
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.0a1
first release with
nightly linux32
095ec59a8800 / 64.0a1 / 20180924100354 / files
nightly linux64
095ec59a8800 / 64.0a1 / 20180924100354 / files
nightly mac
095ec59a8800 / 64.0a1 / 20180924100354 / files
nightly win32
095ec59a8800 / 64.0a1 / 20180924100354 / files
nightly win64
095ec59a8800 / 64.0a1 / 20180924100354 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central a=merge
--- a/accessible/tests/mochitest/states/test_tree.xul
+++ b/accessible/tests/mochitest/states/test_tree.xul
@@ -90,23 +90,18 @@
       gQueue = new eventQueue(EVENT_REORDER);
       gQueue.push(new statesChecker("tree", new nsTreeTreeView()));
       gQueue.push(new statesChecker("treesingle", new nsTreeTreeView()));
       gQueue.push(new statesChecker("tabletree", new nsTreeTreeView()));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
-    if (MAC && (navigator.userAgent.includes("Mac OS X 10.6"))) {
-      todo(false,
-           "Re-enable on Mac OS 10.6 after fixing bug 845095 - intermittent orange");
-    } else {
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
-    }
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
     <body xmlns="http://www.w3.org/1999/xhtml">
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=503727"
          title="Reorganize implementation of XUL tree accessibility">
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1679,18 +1679,17 @@ pref("extensions.formautofill.creditCard
 // 3: submitted an autofill'ed credit card form
 pref("extensions.formautofill.creditCards.used", 0);
 pref("extensions.formautofill.firstTimeUse", true);
 pref("extensions.formautofill.heuristics.enabled", true);
 pref("extensions.formautofill.section.enabled", true);
 pref("extensions.formautofill.loglevel", "Warn");
 
 #ifdef NIGHTLY_BUILD
-// Comma separated list of countries Form Autofill supports.
-// This affects feature availability and the address edit form country picker.
+// Comma separated list of countries Form Autofill is available in.
 pref("extensions.formautofill.supportedCountries", "US,CA,DE");
 pref("extensions.formautofill.supportRTL", true);
 #else
 pref("extensions.formautofill.supportedCountries", "US");
 pref("extensions.formautofill.supportRTL", false);
 #endif
 
 // Whether or not to restore a session with lazy-browser tabs.
--- a/browser/components/payments/content/paymentDialogFrameScript.js
+++ b/browser/components/payments/content/paymentDialogFrameScript.js
@@ -69,17 +69,17 @@ let PaymentFrameScript = {
 
   /**
    * Expose privileged utility functions to the unprivileged page.
    */
   exposeUtilityFunctions() {
     let waivedContent = Cu.waiveXrays(content);
     let PaymentDialogUtils = {
       DEFAULT_REGION: FormAutofill.DEFAULT_REGION,
-      supportedCountries: FormAutofill.supportedCountries,
+      countries: FormAutofill.countries,
 
       getAddressLabel(address, addressFields = null) {
         return FormAutofillUtils.getAddressLabel(address, addressFields);
       },
 
       getCreditCardNetworks() {
         let networks = FormAutofillUtils.getCreditCardNetworks();
         return Cu.cloneInto(networks, waivedContent);
--- a/browser/components/payments/content/paymentDialogWrapper.js
+++ b/browser/components/payments/content/paymentDialogWrapper.js
@@ -131,16 +131,17 @@ var paymentDialogWrapper = {
       throw new Error(`Shipping address not found: ${guid}`);
     }
 
     let address = this.createPaymentAddress({
       country: addressData.country,
       addressLines: addressData["street-address"].split("\n"),
       region: addressData["address-level1"],
       city: addressData["address-level2"],
+      dependentLocality: addressData["address-level3"],
       postalCode: addressData["postal-code"],
       organization: addressData.organization,
       recipient: addressData.name,
       phone: addressData.tel,
     });
 
     return address;
   },
--- a/browser/components/payments/res/containers/address-form.js
+++ b/browser/components/payments/res/containers/address-form.js
@@ -83,17 +83,17 @@ export default class AddressForm extends
       this.body.appendChild(form);
 
       let record = {};
       this.formHandler = new EditAddress({
         form,
       }, record, {
         DEFAULT_REGION: PaymentDialogUtils.DEFAULT_REGION,
         getFormFormat: PaymentDialogUtils.getFormFormat,
-        supportedCountries: PaymentDialogUtils.supportedCountries,
+        countries: PaymentDialogUtils.countries,
       });
 
       // The EditAddress constructor adds `input` event listeners on the same element,
       // which update field validity. By adding our event listeners after this constructor,
       // validity will be updated before our handlers get the event
       this.form.addEventListener("input", this);
       this.form.addEventListener("invalid", this);
       this.form.addEventListener("change", this);
--- a/browser/components/payments/res/unprivileged-fallbacks.js
+++ b/browser/components/payments/res/unprivileged-fallbacks.js
@@ -45,20 +45,22 @@ var PaymentDialogUtils = {
       "unionpay",
       "visa",
     ];
   },
   isCCNumber(str) {
     return !!str.replace(/[-\s]/g, "").match(/^\d{9,}$/);
   },
   DEFAULT_REGION: "US",
-  supportedCountries: ["US", "CA", "DE"],
+  countries: new Map([["US", "United States"], ["CA", "Canada"], ["DE", "Germany"]]),
   getFormFormat(country) {
     if (country == "DE") {
       return {
+        addressLevel3Label: "",
+        addressLevel2Label: "city",
         addressLevel1Label: "province",
         postalCodeLabel: "postalCode",
         fieldsOrder: [
           {
             fieldId: "name",
             newLine: true,
           },
           {
@@ -72,29 +74,31 @@ var PaymentDialogUtils = {
           {fieldId: "postal-code"},
           {fieldId: "address-level2"},
         ],
         postalCodePattern: "\\d{5}",
       };
     }
 
     return {
-      "addressLevel1Label": country == "US" ? "state" : "province",
-      "postalCodeLabel": country == "US" ? "zip" : "postalCode",
-      "fieldsOrder": [
+      addressLevel3Label: "",
+      addressLevel2Label: "city",
+      addressLevel1Label: country == "US" ? "state" : "province",
+      postalCodeLabel: country == "US" ? "zip" : "postalCode",
+      fieldsOrder: [
         {fieldId: "name", newLine: true},
         {fieldId: "street-address", newLine: true},
         {fieldId: "address-level2"},
         {fieldId: "address-level1"},
         {fieldId: "postal-code"},
         {fieldId: "organization"},
       ],
       // The following values come from addressReferences.js and should not be changed.
       /* eslint-disable-next-line max-len */
-      "postalCodePattern": country == "US" ? "(\\d{5})(?:[ \\-](\\d{4}))?" : "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d",
+      postalCodePattern: country == "US" ? "(\\d{5})(?:[ \\-](\\d{4}))?" : "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d",
     };
   },
   getDefaultPreferences() {
     let prefValues = {
       saveCreditCardDefaultChecked: false,
       saveAddressDefaultChecked: true,
     };
     return prefValues;
--- a/browser/components/payments/test/browser/head.js
+++ b/browser/components/payments/test/browser/head.js
@@ -382,17 +382,17 @@ async function navigateToAddAddressPage(
   addLinkSelector: "address-picker[selected-state-key=\"selectedShippingAddress\"] a.add-link",
   initialPageId: "payment-summary",
 }) {
   await spawnPaymentDialogTask(frame, async (options) => {
     let {
       PaymentTestUtils,
     } = ChromeUtils.import("resource://testing-common/PaymentTestUtils.jsm", {});
 
-    info("navigateToAddAddressPage: check were on the expected page first");
+    info("navigateToAddAddressPage: check we're on the expected page first");
     await PaymentTestUtils.DialogContentUtils.waitForState(content, (state) => {
       info("current page state: " + state.page.id + " waiting for: " + options.initialPageId);
       return state.page.id == options.initialPageId;
     }, "Check summary page state");
 
     // click through to add/edit address page
     info("navigateToAddAddressPage: click the link");
     let addLink = content.document.querySelector(options.addLinkSelector);
--- a/browser/extensions/formautofill/FormAutofill.jsm
+++ b/browser/extensions/formautofill/FormAutofill.jsm
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["FormAutofill"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 const ADDRESSES_FIRST_TIME_USE_PREF = "extensions.formautofill.firstTimeUse";
 const AUTOFILL_CREDITCARDS_AVAILABLE_PREF = "extensions.formautofill.creditCards.available";
 const CREDITCARDS_USED_STATUS_PREF = "extensions.formautofill.creditCards.used";
 const DEFAULT_REGION_PREF = "browser.search.region";
 const ENABLED_AUTOFILL_ADDRESSES_PREF = "extensions.formautofill.addresses.enabled";
 const ENABLED_AUTOFILL_CREDITCARDS_PREF = "extensions.formautofill.creditCards.enabled";
 const SUPPORTED_COUNTRIES_PREF = "extensions.formautofill.supportedCountries";
@@ -68,8 +69,12 @@ XPCOMUtils.defineLazyPreferenceGetter(Fo
                                       "_isAutofillCreditCardsEnabled", ENABLED_AUTOFILL_CREDITCARDS_PREF);
 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(","));
+
+XPCOMUtils.defineLazyGetter(FormAutofill, "countries", () => {
+  return Services.intl.getRegions(undefined);
+});
--- a/browser/extensions/formautofill/FormAutofillHandler.jsm
+++ b/browser/extensions/formautofill/FormAutofillHandler.jsm
@@ -550,16 +550,23 @@ class FormAutofillAddressSection extends
     return this.fieldDetails.length >= FormAutofillUtils.AUTOFILL_FIELDS_THRESHOLD;
   }
 
   isEnabled() {
     return FormAutofill.isAutofillAddressesEnabled;
   }
 
   isRecordCreatable(record) {
+    if (record.country && !FormAutofill.supportedCountries.includes(record.country)) {
+      // We don't want to save data in the wrong fields due to not having proper
+      // heuristic regexes in countries we don't yet support.
+      log.warn("isRecordCreatable: Country not supported:", record.country);
+      return false;
+    }
+
     let hasName = 0;
     let length = 0;
     for (let key of Object.keys(record)) {
       if (!record[key]) {
         continue;
       }
       if (FormAutofillUtils.getCategoryFromFieldName(key) == "name") {
         hasName = 1;
--- a/browser/extensions/formautofill/FormAutofillParent.jsm
+++ b/browser/extensions/formautofill/FormAutofillParent.jsm
@@ -49,16 +49,17 @@ this.log = null;
 FormAutofill.defineLazyLogGetter(this, EXPORTED_SYMBOLS[0]);
 
 const {
   ENABLED_AUTOFILL_ADDRESSES_PREF,
   ENABLED_AUTOFILL_CREDITCARDS_PREF,
 } = FormAutofill;
 
 const {
+  ADDRESSES_COLLECTION_NAME,
   CREDITCARDS_COLLECTION_NAME,
 } = FormAutofillUtils;
 
 function FormAutofillParent() {
   // Lazily load the storage JSM to avoid disk I/O until absolutely needed.
   // Once storage is loaded we need to update saved field names and inform content processes.
   XPCOMUtils.defineLazyGetter(this, "formAutofillStorage", () => {
     let {formAutofillStorage} = ChromeUtils.import("resource://formautofill/FormAutofillStorage.jsm", {});
@@ -340,19 +341,27 @@ FormAutofillParent.prototype = {
         record["cc-number-decrypted"] = await MasterPassword.decrypt(record["cc-number-encrypted"]);
       }
 
       // Filter "cc-number" based on the decrypted one.
       if (info.fieldName == "cc-number") {
         fieldValue = record["cc-number-decrypted"];
       }
 
-      if (!lcSearchString || String(fieldValue).toLowerCase().startsWith(lcSearchString)) {
-        records.push(record);
+      if (collectionName == ADDRESSES_COLLECTION_NAME && record.country
+          && !FormAutofill.supportedCountries.includes(record.country)) {
+        // Address autofill isn't supported for the record's country so we don't
+        // want to attempt to potentially incorrectly fill the address fields.
+        continue;
       }
+
+      if (lcSearchString && !String(fieldValue).toLowerCase().startsWith(lcSearchString)) {
+        continue;
+      }
+      records.push(record);
     }
 
     target.sendAsyncMessage("FormAutofill:Records", records);
   },
 
   _updateSavedFieldNames() {
     log.debug("_updateSavedFieldNames");
 
--- a/browser/extensions/formautofill/FormAutofillStorage.jsm
+++ b/browser/extensions/formautofill/FormAutofillStorage.jsm
@@ -17,16 +17,17 @@
  *       version,              // schema version in integer
  *
  *       // address fields
  *       given-name,
  *       additional-name,
  *       family-name,
  *       organization,         // Company
  *       street-address,       // (Multiline)
+ *       address-level3,       // Suburb/Sublocality
  *       address-level2,       // City/Town
  *       address-level1,       // Province (Standardized code if possible)
  *       postal-code,
  *       country,              // ISO 3166
  *       tel,                  // Stored in E.164 format
  *       email,
  *
  *       // computed fields (These fields are computed based on the above fields
@@ -160,16 +161,17 @@ const ADDRESS_SCHEMA_VERSION = 1;
 const CREDIT_CARD_SCHEMA_VERSION = 1;
 
 const VALID_ADDRESS_FIELDS = [
   "given-name",
   "additional-name",
   "family-name",
   "organization",
   "street-address",
+  "address-level3",
   "address-level2",
   "address-level1",
   "postal-code",
   "country",
   "tel",
   "email",
 ];
 
@@ -1292,17 +1294,17 @@ class AutofillRecords {
 }
 
 class Addresses extends AutofillRecords {
   constructor(store) {
     super(store, "addresses", VALID_ADDRESS_FIELDS, VALID_ADDRESS_COMPUTED_FIELDS, ADDRESS_SCHEMA_VERSION);
   }
 
   _recordReadProcessor(address) {
-    if (address.country && !FormAutofill.supportedCountries.includes(address.country)) {
+    if (address.country && !FormAutofill.countries.has(address.country)) {
       delete address.country;
       delete address["country-name"];
     }
   }
 
   async computeFields(address) {
     // NOTE: Remember to bump the schema version number if any of the existing
     //       computing algorithm changes. (No need to bump when just adding new
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -67,17 +67,22 @@ let AddressDataLoader = {
     } catch (e) {
       // Will return only address references if extension loading failed or empty sandbox if
       // address references loading failed.
       return sandbox;
     }
 
     if (extSandbox.addressDataExt) {
       for (let key in extSandbox.addressDataExt) {
-        Object.assign(sandbox.addressData[key], extSandbox.addressDataExt[key]);
+        let addressDataForKey = sandbox.addressData[key];
+        if (!addressDataForKey) {
+          addressDataForKey = sandbox.addressData[key] = {};
+        }
+
+        Object.assign(addressDataForKey, extSandbox.addressDataExt[key]);
       }
     }
     return sandbox;
   },
 
   /**
    * Convert certain properties' string value into array. We should make sure
    * the cached data is parsed.
@@ -265,16 +270,17 @@ this.FormAutofillUtils = {
    */
   getAddressLabel(address, addressFields = null) {
     // TODO: Implement a smarter way for deciding what to display
     //       as option text. Possibly improve the algorithm in
     //       ProfileAutoCompleteResult.jsm and reuse it here.
     let fieldOrder = [
       "name",
       "-moz-street-address-one-line",  // Street address
+      "address-level3",  // Townland / Neighborhood / Village
       "address-level2",  // City/Town
       "organization",    // Company or organization name
       "address-level1",  // Province/State (Standardized code if possible)
       "country-name",    // Country name
       "postal-code",     // Postal code
       "tel",             // Phone number
       "email",           // Email address
     ];
@@ -366,20 +372,20 @@ this.FormAutofillUtils = {
 
   /**
    * Get country address data and fallback to US if not found.
    * See AddressDataLoader._loadData for more details of addressData structure.
    * @param {string} [country=FormAutofill.DEFAULT_REGION]
    *        The country code for requesting specific country's metadata. It'll be
    *        default region if parameter is not set.
    * @param {string} [level1=null]
-   *        Retrun address level 1/level 2 metadata if parameter is set.
+   *        Return address level 1/level 2 metadata if parameter is set.
    * @returns {object|null}
    *          Return metadata of specific region with default locale and other supported
-   *          locales. We need to return a deafult country metadata for layout format
+   *          locales. We need to return a default country metadata for layout format
    *          and collator, but for sub-region metadata we'll just return null if not found.
    */
   getCountryAddressRawData(country = FormAutofill.DEFAULT_REGION, level1 = null) {
     let metadata = AddressDataLoader.getData(country, level1);
     if (!metadata) {
       if (level1) {
         return null;
       }
@@ -397,28 +403,34 @@ this.FormAutofillUtils = {
     return metadata;
   },
 
   /**
    * Get country address data with default locale.
    * @param {string} country
    * @param {string} level1
    * @returns {object|null} Return metadata of specific region with default locale.
+   *          NOTE: The returned data may be for a default region if the
+   *          specified one cannot be found. Callers who only want the specific
+   *          region should check the returned country code.
    */
   getCountryAddressData(country, level1) {
     let metadata = this.getCountryAddressRawData(country, level1);
     return metadata && metadata.defaultLocale;
   },
 
   /**
    * Get country address data with all locales.
    * @param {string} country
    * @param {string} level1
    * @returns {array<object>|null}
    *          Return metadata of specific region with all the locales.
+   *          NOTE: The returned data may be for a default region if the
+   *          specified one cannot be found. Callers who only want the specific
+   *          region should check the returned country code.
    */
   getCountryAddressDataWithLocales(country, level1) {
     let metadata = this.getCountryAddressRawData(country, level1);
     return metadata && [metadata.defaultLocale, ...metadata.locales];
   },
 
   /**
    * Get the collators based on the specified country.
@@ -459,16 +471,17 @@ this.FormAutofillUtils = {
     // Based on the list of fields abbreviations in
     // https://github.com/googlei18n/libaddressinput/wiki/AddressValidationMetadata
     const fieldsLookup = {
       N: "name",
       O: "organization",
       A: "street-address",
       S: "address-level1",
       C: "address-level2",
+      D: "address-level3",
       Z: "postal-code",
       n: "newLine",
     };
 
     return fmt.match(/%[^%]/g).reduce((parsed, part) => {
       // Take the first letter of each segment and try to identify it
       let fieldId = fieldsLookup[part[1]];
       // Early return if cannot identify part.
@@ -491,22 +504,30 @@ this.FormAutofillUtils = {
    * Use alternative country name list to identify a country code from a
    * specified country name.
    * @param   {string} countryName A country name to be identified
    * @param   {string} [countrySpecified] A country code indicating that we only
    *                                      search its alternative names if specified.
    * @returns {string} The matching country code.
    */
   identifyCountryCode(countryName, countrySpecified) {
-    let countries = countrySpecified ? [countrySpecified] : FormAutofill.supportedCountries;
+    let countries = countrySpecified ? [countrySpecified] : [...FormAutofill.countries.keys()];
 
     for (let country of countries) {
       let collators = this.getCollators(country);
-
       let metadata = this.getCountryAddressData(country);
+      if (country != metadata.key) {
+        // We hit the fallback logic in getCountryAddressRawData so ignore it as
+        // it's not related to `country` and use the name from l10n instead.
+        metadata = {
+          id: `data/${country}`,
+          key: country,
+          name: FormAutofill.countries.get(country),
+        };
+      }
       let alternativeCountryNames = metadata.alternative_names || [metadata.name];
       let reAlternativeCountryNames = this._reAlternativeCountryNames[country];
       if (!reAlternativeCountryNames) {
         reAlternativeCountryNames = this._reAlternativeCountryNames[country] = [];
       }
 
       for (let i = 0; i < alternativeCountryNames.length; i++) {
         let name = alternativeCountryNames[i];
@@ -771,28 +792,37 @@ this.FormAutofillUtils = {
     return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
   },
 
   /**
    * Get formatting information of a given country
    * @param   {string} country
    * @returns {object}
    *         {
+   *           {string} addressLevel3Label
+   *           {string} addressLevel2Label
    *           {string} addressLevel1Label
    *           {string} postalCodeLabel
    *           {object} fieldsOrder
+   *           {string} postalCodePattern
    *         }
    */
   getFormFormat(country) {
     const dataset = this.getCountryAddressData(country);
     return {
-      "addressLevel1Label": dataset.state_name_type || "province",
-      "postalCodeLabel": dataset.zip_name_type || "postalCode",
-      "fieldsOrder": this.parseAddressFormat(dataset.fmt || "%N%n%O%n%A%n%C, %S %Z"),
-      "postalCodePattern": dataset.zip,
+      // Phillipines doesn't specify a sublocality_name_type but
+      // has one referenced in their fmt value.
+      addressLevel3Label: dataset.sublocality_name_type || "suburb",
+      // Many locales don't specify a locality_name_type but
+      // have one referenced in their fmt value.
+      addressLevel2Label: dataset.locality_name_type || "city",
+      addressLevel1Label: dataset.state_name_type || "province",
+      postalCodeLabel: dataset.zip_name_type || "postalCode",
+      fieldsOrder: this.parseAddressFormat(dataset.fmt || "%N%n%O%n%A%n%C, %S %Z"),
+      postalCodePattern: dataset.zip,
     };
   },
 
   /**
    * Localize "data-localization" or "data-localization-region" attributes.
    * @param {Element} element
    * @param {string} attributeName
    */
--- a/browser/extensions/formautofill/ProfileAutoCompleteResult.jsm
+++ b/browser/extensions/formautofill/ProfileAutoCompleteResult.jsm
@@ -215,16 +215,17 @@ class AddressResult extends ProfileAutoC
         "tel-local-prefix",
         "tel-local-suffix",
       ],
     };
 
     const secondaryLabelOrder = [
       "street-address",  // Street address
       "name",            // Full name
+      "address-level3",  // Townland / Neighborhood / Village
       "address-level2",  // City/Town
       "organization",    // Company or organization name
       "address-level1",  // Province/State (Standardized code if possible)
       "country-name",    // Country name
       "postal-code",     // Postal code
       "tel",             // Phone number
       "email",           // Email address
     ];
--- a/browser/extensions/formautofill/addressmetadata/addressReferences.js
+++ b/browser/extensions/formautofill/addressmetadata/addressReferences.js
@@ -5,19 +5,270 @@
 /* exported addressData */
 /* eslint max-len: 0 */
 
 "use strict";
 
 // The data below is initially copied from
 // https://chromium-i18n.appspot.com/ssl-aggregate-address
 
+// See https://github.com/googlei18n/libaddressinput/wiki/AddressValidationMetadata for
+// documentation on how to use the data.
+
 // WARNING: DO NOT change any value or add additional properties in addressData.
 // We only accept the metadata of the supported countries that is copied from libaddressinput directly.
 // Please edit addressReferencesExt.js instead if you want to add new property as complement
 // or overwrite the existing properties.
 
 var addressData = {
-  "data/CA": {"lang": "en", "upper": "ACNOSZ", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1", "name": "CANADA", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/CA", "languages": "en~fr", "sub_keys": "AB~BC~MB~NB~NL~NT~NS~NU~ON~PE~QC~SK~YT", "key": "CA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "require": "ACSZ", "sub_names": "Alberta~British Columbia~Manitoba~New Brunswick~Newfoundland and Labrador~Northwest Territories~Nova Scotia~Nunavut~Ontario~Prince Edward Island~Quebec~Saskatchewan~Yukon", "sub_zips": "T~V~R~E~A~X0E|X0G|X1A~B~X0A|X0B|X0C~K|L|M|N|P~C~G|H|J|K1A~S|R8A~Y"},
-  "data/CA--fr": {"lang": "fr", "upper": "ACNOSZ", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1", "name": "CANADA", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "fmt": "%N%n%O%n%A%n%C %S %Z", "require": "ACSZ", "sub_keys": "AB~BC~PE~MB~NB~NS~NU~ON~QC~SK~NL~NT~YT", "key": "CA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "id": "data/CA--fr", "sub_names": "Alberta~Colombie-Britannique~Île-du-Prince-Édouard~Manitoba~Nouveau-Brunswick~Nouvelle-Écosse~Nunavut~Ontario~Québec~Saskatchewan~Terre-Neuve-et-Labrador~Territoires du Nord-Ouest~Yukon", "sub_zips": "T~V~C~R~E~B~X0A|X0B|X0C~K|L|M|N|P~G|H|J|K1A~S|R8A~A~X0E|X0G|X1A~Y"},
-  "data/DE": {"zipex": "26133,53225", "name": "GERMANY", "zip": "\\d{5}", "fmt": "%N%n%O%n%A%n%Z %C", "id": "data/DE", "key": "DE", "posturl": "http://www.postdirekt.de/plzserver/", "require": "ACZ"},
-  "data/US": {"lang": "en", "upper": "CS", "sub_zipexs": "35000,36999~99500,99999~96799~85000,86999~71600,72999~34000,34099~09000,09999~96200,96699~90000,96199~80000,81999~06000,06999~19700,19999~20000,56999~32000,34999~30000,39901~96910,96932~96700,96899~83200,83999~60000,62999~46000,47999~50000,52999~66000,67999~40000,42799~70000,71599~03900,04999~96960,96979~20600,21999~01000,05544~48000,49999~96941,96944~55000,56799~38600,39799~63000,65999~59000,59999~68000,69999~88900,89999~03000,03899~07000,08999~87000,88499~10000,00544~27000,28999~58000,58999~96950,96952~43000,45999~73000,74999~97000,97999~96940~15000,19699~00600,00999~02800,02999~29000,29999~57000,57999~37000,38599~75000,73344~84000,84999~05000,05999~00800,00899~20100,24699~98000,99499~24700,26999~53000,54999~82000,83414", "zipex": "95014,22162-1010", "name": "UNITED STATES", "zip": "(\\d{5})(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "fmt": "%N%n%O%n%A%n%C, %S %Z", "state_name_type": "state", "id": "data/US", "languages": "en", "sub_keys": "AL~AK~AS~AZ~AR~AA~AE~AP~CA~CO~CT~DE~DC~FL~GA~GU~HI~ID~IL~IN~IA~KS~KY~LA~ME~MH~MD~MA~MI~FM~MN~MS~MO~MT~NE~NV~NH~NJ~NM~NY~NC~ND~MP~OH~OK~OR~PW~PA~PR~RI~SC~SD~TN~TX~UT~VT~VI~VA~WA~WV~WI~WY", "key": "US", "posturl": "https://tools.usps.com/go/ZipLookupAction!input.action", "require": "ACSZ", "sub_names": "Alabama~Alaska~American Samoa~Arizona~Arkansas~Armed Forces (AA)~Armed Forces (AE)~Armed Forces (AP)~California~Colorado~Connecticut~Delaware~District of Columbia~Florida~Georgia~Guam~Hawaii~Idaho~Illinois~Indiana~Iowa~Kansas~Kentucky~Louisiana~Maine~Marshall Islands~Maryland~Massachusetts~Michigan~Micronesia~Minnesota~Mississippi~Missouri~Montana~Nebraska~Nevada~New Hampshire~New Jersey~New Mexico~New York~North Carolina~North Dakota~Northern Mariana Islands~Ohio~Oklahoma~Oregon~Palau~Pennsylvania~Puerto Rico~Rhode Island~South Carolina~South Dakota~Tennessee~Texas~Utah~Vermont~Virgin Islands~Virginia~Washington~West Virginia~Wisconsin~Wyoming", "sub_zips": "3[56]~99[5-9]~96799~8[56]~71[6-9]|72~340~09~96[2-6]~9[0-5]|96[01]~8[01]~06~19[7-9]~20[02-5]|569~3[23]|34[1-9]~3[01]|398|39901~969([1-2]\\d|3[12])~967[0-8]|9679[0-8]|968~83[2-9]~6[0-2]~4[67]~5[0-2]~6[67]~4[01]|42[0-7]~70|71[0-5]~039|04~969[67]~20[6-9]|21~01|02[0-7]|05501|05544~4[89]~9694[1-4]~55|56[0-7]~38[6-9]|39[0-7]~6[3-5]~59~6[89]~889|89~03[0-8]~0[78]~87|88[0-4]~1[0-4]|06390|00501|00544~2[78]~58~9695[0-2]~4[3-5]~7[34]~97~969(39|40)~1[5-8]|19[0-6]~00[679]~02[89]~29~57~37|38[0-5]~7[5-9]|885|73301|73344~84~05~008~201|2[23]|24[0-6]~98|99[0-4]~24[7-9]|2[56]~5[34]~82|83[01]|83414"},
+  "data/AD": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/AD", "key": "AD", "lang": "ca", "languages": "ca", "name": "ANDORRA", "posturl": "http://www.correos.es/comun/CodigosPostales/1010_s-CodPostal.asp?Provincia=", "sub_isoids": "07~02~03~08~04~05~06", "sub_keys": "Parròquia d'Andorra la Vella~Canillo~Encamp~Escaldes-Engordany~La Massana~Ordino~Sant Julià de Lòria", "sub_names": "Andorra la Vella~Canillo~Encamp~Escaldes-Engordany~La Massana~Ordino~Sant Julià de Lòria", "sub_zipexs": "AD500~AD100~AD200~AD700~AD400~AD300~AD600", "sub_zips": "AD50[01]~AD10[01]~AD20[01]~AD70[01]~AD40[01]~AD30[01]~AD60[01]", "zip": "AD[1-7]0\\d", "zipex": "AD100,AD501,AD700"},
+  "data/AE": {"fmt": "%N%n%O%n%A%n%S", "id": "data/AE", "key": "AE", "lang": "ar", "languages": "ar", "lfmt": "%N%n%O%n%A%n%S", "name": "UNITED ARAB EMIRATES", "require": "AS", "state_name_type": "emirate", "sub_isoids": "AZ~SH~FU~UQ~DU~RK~AJ", "sub_keys": "أبو ظبي~إمارة الشارقةّ~الفجيرة~ام القيوين~إمارة دبيّ~إمارة رأس الخيمة~عجمان", "sub_lnames": "Abu Dhabi~Sharjah~Fujairah~Umm Al Quwain~Dubai~Ras al Khaimah~Ajman", "sub_names": "أبو ظبي~الشارقة~الفجيرة~ام القيوين~دبي~رأس الخيمة~عجمان"},
+  "data/AF": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/AF", "key": "AF", "name": "AFGHANISTAN", "zip": "\\d{4}", "zipex": "1001,2601,3801"},
+  "data/AG": {"id": "data/AG", "key": "AG", "name": "ANTIGUA AND BARBUDA", "require": "A"},
+  "data/AI": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/AI", "key": "AI", "name": "ANGUILLA", "zip": "(?:AI-)?2640", "zipex": "2640"},
+  "data/AL": {"fmt": "%N%n%O%n%A%n%Z%n%C", "id": "data/AL", "key": "AL", "name": "ALBANIA", "zip": "\\d{4}", "zipex": "1001,1017,3501"},
+  "data/AM": {"fmt": "%N%n%O%n%A%n%Z%n%C%n%S", "id": "data/AM", "key": "AM", "lang": "hy", "languages": "hy", "lfmt": "%N%n%O%n%A%n%Z%n%C%n%S", "name": "ARMENIA", "sub_isoids": "AG~AR~AV~GR~ER~LO~KT~SH~SU~VD~TV", "sub_keys": "Արագածոտն~Արարատ~Արմավիր~Գեղարքունիք~Երևան~Լոռի~Կոտայք~Շիրակ~Սյունիք~Վայոց ձոր~Տավուշ", "sub_lnames": "Aragatsotn~Ararat~Armavir~Gegharkunik~Yerevan~Lori~Kotayk~Shirak~Syunik~Vayots Dzor~Tavush", "sub_zipexs": "0201,0514~0601,0823~0901,1149~1201,1626~0000,0099~1701,2117~2201,2506~2601,3126~3201,3519~3601,3810~3901,4216", "sub_zips": "0[2-5]~0[6-8]~09|1[01]~1[2-6]~00~1[7-9]|2[01]~2[2-5]~2[6-9]|3[01]~3[2-5]~3[6-8]~39|4[0-2]", "zip": "(?:37)?\\d{4}", "zipex": "375010,0002,0010"},
+  "data/AO": {"id": "data/AO", "key": "AO", "name": "ANGOLA"},
+  "data/AQ": {"id": "data/AQ", "key": "AQ", "name": "ANTARCTICA"},
+  "data/AR": {"fmt": "%N%n%O%n%A%n%Z %C%n%S", "id": "data/AR", "key": "AR", "lang": "es", "languages": "es", "name": "ARGENTINA", "posturl": "http://www.correoargentino.com.ar/formularios/cpa", "sub_isoids": "B~K~H~U~C~X~W~E~P~Y~L~F~M~N~Q~R~A~J~D~Z~S~G~V~T", "sub_keys": "Buenos Aires~Catamarca~Chaco~Chubut~Ciudad Autónoma de Buenos Aires~Córdoba~Corrientes~Entre Ríos~Formosa~Jujuy~La Pampa~La Rioja~Mendoza~Misiones~Neuquén~Río Negro~Salta~San Juan~San Luis~Santa Cruz~Santa Fe~Santiago del Estero~Tierra del Fuego~Tucumán", "sub_names": "Buenos Aires~Catamarca~Chaco~Chubut~Ciudad Autónoma de Buenos Aires~Córdoba~Corrientes~Entre Ríos~Formosa~Jujuy~La Pampa~La Rioja~Mendoza~Misiones~Neuquén~Río Negro~Salta~San Juan~San Luis~Santa Cruz~Santa Fe~Santiago del Estero~Tierra del Fuego~Tucumán", "sub_zips": "B?[1-36-8]~K?[45]~H?3~U?[89]~C?1~X?[235-8]~W?3~E?[1-3]~P?[37]~Y?4~L?[3568]~F?5~M?[56]~N?3~Q?[38]~R?[89]~A?[34]~J?5~D?[4-6]~Z?[89]~S?[2368]~G?[2-5]~V?9~T?[45]", "upper": "ACZ", "zip": "((?:[A-HJ-NP-Z])?\\d{4})([A-Z]{3})?", "zipex": "C1070AAM,C1000WAM,B1000TBU,X5187XAB"},
+  "data/AS": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/AS", "key": "AS", "name": "AMERICAN SAMOA", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACSZ", "state_name_type": "state", "upper": "ACNOS", "zip": "(96799)(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "96799"},
+  "data/AT": {"fmt": "%O%n%N%n%A%n%Z %C", "id": "data/AT", "key": "AT", "name": "AUSTRIA", "posturl": "http://www.post.at/post_subsite_postleitzahlfinder.php", "require": "ACZ", "zip": "\\d{4}", "zipex": "1010,3741"},
+  "data/AU": {"fmt": "%O%n%N%n%A%n%C %S %Z", "id": "data/AU", "key": "AU", "lang": "en", "languages": "en", "locality_name_type": "suburb", "name": "AUSTRALIA", "posturl": "http://www1.auspost.com.au/postcodes/", "require": "ACSZ", "state_name_type": "state", "sub_isoids": "ACT~NSW~NT~QLD~SA~TAS~VIC~WA", "sub_keys": "ACT~NSW~NT~QLD~SA~TAS~VIC~WA", "sub_names": "Australian Capital Territory~New South Wales~Northern Territory~Queensland~South Australia~Tasmania~Victoria~Western Australia", "sub_zipexs": "0200,2540,2618,2999~1000,2888,3585,3707~0800,0999~4000,9999~5000~7000,7999~3000,8000~6000,0872", "sub_zips": "29|2540|260|261[0-8]|02|2620~1|2[0-57-8]|26[2-9]|261[189]|3500|358[56]|3644|3707~0[89]~[49]~5|0872~7~[38]~6|0872", "upper": "CS", "zip": "\\d{4}", "zipex": "2060,3171,6430,4000,4006,3001"},
+  "data/AW": {"id": "data/AW", "key": "AW", "name": "ARUBA"},
+  "data/AZ": {"fmt": "%N%n%O%n%A%nAZ %Z %C", "id": "data/AZ", "key": "AZ", "name": "AZERBAIJAN", "postprefix": "AZ ", "zip": "\\d{4}", "zipex": "1000"},
+  "data/BA": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/BA", "key": "BA", "name": "BOSNIA AND HERZEGOVINA", "zip": "\\d{5}", "zipex": "71000"},
+  "data/BB": {"fmt": "%N%n%O%n%A%n%C, %S %Z", "id": "data/BB", "key": "BB", "name": "BARBADOS", "state_name_type": "parish", "zip": "BB\\d{5}", "zipex": "BB23026,BB22025"},
+  "data/BD": {"fmt": "%N%n%O%n%A%n%C - %Z", "id": "data/BD", "key": "BD", "name": "BANGLADESH", "posturl": "http://www.bangladeshpost.gov.bd/PostCode.asp", "zip": "\\d{4}", "zipex": "1340,1000"},
+  "data/BE": {"fmt": "%O%n%N%n%A%n%Z %C", "id": "data/BE", "key": "BE", "name": "BELGIUM", "posturl": "http://www.post.be/site/nl/residential/customerservice/search/postal_codes.html", "require": "ACZ", "zip": "\\d{4}", "zipex": "4000,1000"},
+  "data/BF": {"fmt": "%N%n%O%n%A%n%C %X", "id": "data/BF", "key": "BF", "name": "BURKINA FASO"},
+  "data/BG": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/BG", "key": "BG", "name": "BULGARIA (REP.)", "posturl": "http://www.bgpost.bg/?cid=5", "zip": "\\d{4}", "zipex": "1000,1700"},
+  "data/BH": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/BH", "key": "BH", "name": "BAHRAIN", "zip": "(?:\\d|1[0-2])\\d{2}", "zipex": "317"},
+  "data/BI": {"id": "data/BI", "key": "BI", "name": "BURUNDI"},
+  "data/BJ": {"id": "data/BJ", "key": "BJ", "name": "BENIN", "upper": "AC"},
+  "data/BL": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/BL", "key": "BL", "name": "SAINT BARTHELEMY", "posturl": "http://www.laposte.fr/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal", "require": "ACZ", "upper": "ACX", "zip": "9[78][01]\\d{2}", "zipex": "97100"},
+  "data/BM": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/BM", "key": "BM", "name": "BERMUDA", "posturl": "http://www.landvaluation.bm/", "zip": "[A-Z]{2} ?[A-Z0-9]{2}", "zipex": "FL 07,HM GX,HM 12"},
+  "data/BN": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/BN", "key": "BN", "name": "BRUNEI DARUSSALAM", "posturl": "http://www.post.gov.bn/SitePages/postcodes.aspx", "zip": "[A-Z]{2} ?\\d{4}", "zipex": "BT2328,KA1131,BA1511"},
+  "data/BO": {"id": "data/BO", "key": "BO", "name": "BOLIVIA", "upper": "AC"},
+  "data/BQ": {"id": "data/BQ", "key": "BQ", "name": "BONAIRE, SINT EUSTATIUS, AND SABA"},
+  "data/BR": {"fmt": "%O%n%N%n%A%n%D%n%C-%S%n%Z", "id": "data/BR", "key": "BR", "lang": "pt", "languages": "pt", "name": "BRAZIL", "posturl": "http://www.buscacep.correios.com.br/", "require": "ASCZ", "state_name_type": "state", "sub_isoids": "AC~AL~AP~AM~BA~CE~DF~ES~GO~MA~MT~MS~MG~PA~PB~PR~PE~PI~RJ~RN~RS~RO~RR~SC~SP~SE~TO", "sub_keys": "AC~AL~AP~AM~BA~CE~DF~ES~GO~MA~MT~MS~MG~PA~PB~PR~PE~PI~RJ~RN~RS~RO~RR~SC~SP~SE~TO", "sub_mores": "true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true", "sub_names": "Acre~Alagoas~Amapá~Amazonas~Bahia~Ceará~Distrito Federal~Espírito Santo~Goiás~Maranhão~Mato Grosso~Mato Grosso do Sul~Minas Gerais~Pará~Paraíba~Paraná~Pernambuco~Piauí~Rio de Janeiro~Rio Grande do Norte~Rio Grande do Sul~Rondônia~Roraima~Santa Catarina~São Paulo~Sergipe~Tocantins", "sub_zipexs": "69900-000,69999-999~57000-000,57999-999~68900-000,68999-999~69000-000,69400-123~40000-000,48999-999~60000-000,63999-999~70000-000,73500-123~29000-000,29999-999~72800-000,73700-123~65000-000,65999-999~78000-000,78899-999~79000-000,79999-999~30000-000,39999-999~66000-000,68899-999~58000-000,58999-999~80000-000,87999-999~50000-000,56999-999~64000-000,64999-999~20000-000,28999-999~59000-000,59999-999~90000-000,99999-999~76800-000,78900-000,78999-999~69300-000,69399-999~88000-000,89999-999~01000-000,13000-123~49000-000,49999-999~77000-000,77999-999", "sub_zips": "699~57~689~69[0-24-8]~4[0-8]~6[0-3]~7[0-1]|72[0-7]|73[0-6]~29~72[89]|73[7-9]|7[4-6]~65~78[0-8]~79~3~6[6-7]|68[0-8]~58~8[0-7]~5[0-6]~64~2[0-8]~59~9~76[89]|789~693~8[89]~[01][1-9]~49~77", "sublocality_name_type": "neighborhood", "upper": "CS", "zip": "\\d{5}-?\\d{3}", "zipex": "40301-110,70002-900"},
+  "data/BS": {"fmt": "%N%n%O%n%A%n%C, %S", "id": "data/BS", "key": "BS", "lang": "en", "languages": "en", "name": "BAHAMAS", "state_name_type": "island", "sub_isoids": "~AK~~BY~BI~CI~~~EX~~HI~IN~LI~MG~~RI~RC~SS~SW", "sub_keys": "Abaco~Acklins~Andros~Berry Islands~Bimini~Cat Island~Crooked Island~Eleuthera~Exuma~Grand Bahama~Harbour Island~Inagua~Long Island~Mayaguana~N.P.~Ragged Island~Rum Cay~San Salvador~Spanish Wells", "sub_names": "Abaco Islands~Acklins~Andros Island~Berry Islands~Bimini~Cat Island~Crooked Island~Eleuthera~Exuma and Cays~Grand Bahama~Harbour Island~Inagua~Long Island~Mayaguana~New Providence~Ragged Island~Rum Cay~San Salvador~Spanish Wells"},
+  "data/BT": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/BT", "key": "BT", "name": "BHUTAN", "posturl": "http://www.bhutanpost.bt/postcodes/", "zip": "\\d{5}", "zipex": "11001,31101,35003"},
+  "data/BV": {"id": "data/BV", "key": "BV", "name": "BOUVET ISLAND"},
+  "data/BW": {"id": "data/BW", "key": "BW", "name": "BOTSWANA"},
+  "data/BY": {"fmt": "%S%n%Z %C%n%A%n%O%n%N", "id": "data/BY", "key": "BY", "name": "BELARUS", "posturl": "http://ex.belpost.by/addressbook/", "zip": "\\d{6}", "zipex": "223016,225860,220050"},
+  "data/BZ": {"id": "data/BZ", "key": "BZ", "name": "BELIZE"},
+  "data/CA": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/CA", "key": "CA", "lang": "en", "languages": "en~fr", "name": "CANADA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "require": "ACSZ", "sub_isoids": "AB~BC~MB~NB~NL~NT~NS~NU~ON~PE~QC~SK~YT", "sub_keys": "AB~BC~MB~NB~NL~NT~NS~NU~ON~PE~QC~SK~YT", "sub_names": "Alberta~British Columbia~Manitoba~New Brunswick~Newfoundland and Labrador~Northwest Territories~Nova Scotia~Nunavut~Ontario~Prince Edward Island~Quebec~Saskatchewan~Yukon", "sub_zips": "T~V~R~E~A~X0E|X0G|X1A~B~X0A|X0B|X0C~K|L|M|N|P~C~G|H|J|K1A~S|R8A~Y", "upper": "ACNOSZ", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1"},
+  "data/CA--fr": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/CA--fr", "key": "CA", "lang": "fr", "name": "CANADA", "posturl": "https://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf", "require": "ACSZ", "sub_isoids": "AB~BC~PE~MB~NB~NS~NU~ON~QC~SK~NL~NT~YT", "sub_keys": "AB~BC~PE~MB~NB~NS~NU~ON~QC~SK~NL~NT~YT", "sub_names": "Alberta~Colombie-Britannique~Île-du-Prince-Édouard~Manitoba~Nouveau-Brunswick~Nouvelle-Écosse~Nunavut~Ontario~Québec~Saskatchewan~Terre-Neuve-et-Labrador~Territoires du Nord-Ouest~Yukon", "sub_zips": "T~V~C~R~E~B~X0A|X0B|X0C~K|L|M|N|P~G|H|J|K1A~S|R8A~A~X0E|X0G|X1A~Y", "upper": "ACNOSZ", "zip": "[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJ-NPRSTV-Z] ?\\d[ABCEGHJ-NPRSTV-Z]\\d", "zipex": "H3Z 2Y7,V8X 3X4,T0L 1K0,T0H 1A0,K1A 0B1"},
+  "data/CC": {"fmt": "%O%n%N%n%A%n%C %S %Z", "id": "data/CC", "key": "CC", "name": "COCOS (KEELING) ISLANDS", "upper": "CS", "zip": "6799", "zipex": "6799"},
+  "data/CD": {"id": "data/CD", "key": "CD", "name": "CONGO (DEM. REP.)"},
+  "data/CF": {"id": "data/CF", "key": "CF", "name": "CENTRAL AFRICAN REPUBLIC"},
+  "data/CG": {"id": "data/CG", "key": "CG", "name": "CONGO (REP.)"},
+  "data/CH": {"fmt": "%O%n%N%n%A%nCH-%Z %C", "id": "data/CH", "key": "CH", "name": "SWITZERLAND", "postprefix": "CH-", "posturl": "http://www.post.ch/db/owa/pv_plz_pack/pr_main", "require": "ACZ", "upper": "", "zip": "\\d{4}", "zipex": "2544,1211,1556,3030"},
+  "data/CI": {"fmt": "%N%n%O%n%X %A %C %X", "id": "data/CI", "key": "CI", "name": "COTE D'IVOIRE"},
+  "data/CK": {"id": "data/CK", "key": "CK", "name": "COOK ISLANDS"},
+  "data/CL": {"fmt": "%N%n%O%n%A%n%Z %C%n%S", "id": "data/CL", "key": "CL", "lang": "es", "languages": "es", "name": "CHILE", "posturl": "http://www.correos.cl/SitePages/home.aspx", "sub_isoids": "AN~AR~AP~AT~AI~BI~CO~LI~LL~LR~MA~ML~RM~TA~VS", "sub_keys": "Antofagasta~Araucanía~Arica y Parinacota~Atacama~Aysén~Biobío~Coquimbo~O'Higgins~Los Lagos~Los Ríos~Magallanes~Maule~Región Metropolitana~Tarapacá~Valparaíso", "sub_mores": "true~true~true~true~true~true~true~true~true~true~true~true~true~true~true", "sub_names": "Antofagasta~Araucanía~Arica y Parinacota~Atacama~Aysén del General Carlos Ibáñez del Campo~Biobío~Coquimbo~Libertador General Bernardo O'Higgins~Los Lagos~Los Ríos~Magallanes y de la Antártica Chilena~Maule~Metropolitana de Santiago~Tarapacá~Valparaíso", "zip": "\\d{7}", "zipex": "8340457,8720019,1230000,8329100"},
+  "data/CM": {"id": "data/CM", "key": "CM", "name": "CAMEROON"},
+  "data/CN": {"fmt": "%Z%n%S%C%D%n%A%n%O%n%N", "id": "data/CN", "key": "CN", "lang": "zh", "languages": "zh", "lfmt": "%N%n%O%n%A%n%D%n%C%n%S, %Z", "name": "CHINA", "posturl": "http://www.ems.com.cn/serviceguide/you_bian_cha_xun.html", "require": "ACSZ", "sub_isoids": "34~92~11~50~35~62~44~45~52~46~13~41~23~42~43~22~32~36~21~15~64~63~37~14~61~31~51~71~12~54~91~65~53~33", "sub_keys": "安徽省~澳门~北京市~重庆市~福建省~甘肃省~广东省~广西壮族自治区~贵州省~海南省~河北省~河南省~黑龙江省~湖北省~湖南省~吉林省~江苏省~江西省~辽宁省~内蒙古自治区~宁夏回族自治区~青海省~山东省~山西省~陕西省~上海市~四川省~台湾~天津市~西藏自治区~香港~新疆维吾尔自治区~云南省~浙江省", "sub_lnames": "Anhui Sheng~Macau~Beijing Shi~Chongqing Shi~Fujian Sheng~Gansu Sheng~Guangdong Sheng~Guangxi Zhuangzuzizhiqu~Guizhou Sheng~Hainan Sheng~Hebei Sheng~Henan Sheng~Heilongjiang Sheng~Hubei Sheng~Hunan Sheng~Jilin Sheng~Jiangsu Sheng~Jiangxi Sheng~Liaoning Sheng~Neimenggu Zizhiqu~Ningxia Huizuzizhiqu~Qinghai Sheng~Shandong Sheng~Shanxi Sheng~Shaanxi Sheng~Shanghai Shi~Sichuan Sheng~Taiwan~Tianjin Shi~Xizang Zizhiqu~Hong Kong~Xinjiang Weiwuerzizhiqu~Yunnan Sheng~Zhejiang Sheng", "sub_mores": "true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true", "sub_names": "安徽省~澳门~北京市~重庆市~福建省~甘肃省~广东省~广西~贵州省~海南省~河北省~河南省~黑龙江省~湖北省~湖南省~吉林省~江苏省~江西省~辽宁省~内蒙古~宁夏~青海省~山东省~山西省~陕西省~上海市~四川省~台湾~天津市~西藏~香港~新疆~云南省~浙江省", "sub_xrequires": "~A~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ACS~~~", "sub_xzips": "~999078~~~~~~~~~~~~~~~~~~~~~~~~~~\\d{3}(\\d{2})?~~~999077~~~", "sublocality_name_type": "district", "upper": "S", "zip": "\\d{6}", "zipex": "266033,317204,100096,100808"},
+  "data/CO": {"fmt": "%N%n%O%n%A%n%C, %S, %Z", "id": "data/CO", "key": "CO", "name": "COLOMBIA", "posturl": "http://www.codigopostal.gov.co/", "require": "AS", "state_name_type": "department", "zip": "\\d{6}", "zipex": "111221,130001,760011"},
+  "data/CR": {"fmt": "%N%n%O%n%A%n%S, %C%n%Z", "id": "data/CR", "key": "CR", "name": "COSTA RICA", "posturl": "https://www.correos.go.cr/nosotros/codigopostal/busqueda.html", "require": "ACS", "zip": "\\d{4,5}|\\d{3}-\\d{4}", "zipex": "1000,2010,1001"},
+  "data/CU": {"fmt": "%N%n%O%n%A%n%C %S%n%Z", "id": "data/CU", "key": "CU", "lang": "es", "languages": "es", "name": "CUBA", "sub_isoids": "15~09~08~06~12~14~11~99~03~10~04~16~01~07~13~05", "sub_keys": "Artemisa~Camagüey~Ciego de Ávila~Cienfuegos~Granma~Guantánamo~Holguín~Isla de la Juventud~La Habana~Las Tunas~Matanzas~Mayabeque~Pinar del Río~Sancti Spíritus~Santiago de Cuba~Villa Clara", "zip": "\\d{5}", "zipex": "10700"},
+  "data/CV": {"fmt": "%N%n%O%n%A%n%Z %C%n%S", "id": "data/CV", "key": "CV", "lang": "pt", "languages": "pt", "name": "CAPE VERDE", "state_name_type": "island", "sub_isoids": "BV~BR~~MA~SL~~~~SV", "sub_keys": "Boa Vista~Brava~Fogo~Maio~Sal~Santiago~Santo Antão~São Nicolau~São Vicente", "zip": "\\d{4}", "zipex": "7600"},
+  "data/CW": {"id": "data/CW", "key": "CW", "name": "CURACAO"},
+  "data/CX": {"fmt": "%O%n%N%n%A%n%C %S %Z", "id": "data/CX", "key": "CX", "name": "CHRISTMAS ISLAND", "upper": "CS", "zip": "6798", "zipex": "6798"},
+  "data/CY": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/CY", "key": "CY", "name": "CYPRUS", "zip": "\\d{4}", "zipex": "2008,3304,1900"},
+  "data/CZ": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/CZ", "key": "CZ", "name": "CZECH REP.", "posturl": "http://psc.ceskaposta.cz/CleanForm.action", "require": "ACZ", "zip": "\\d{3} ?\\d{2}", "zipex": "100 00,251 66,530 87,110 00,225 99"},
+  "data/DE": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/DE", "key": "DE", "name": "GERMANY", "posturl": "http://www.postdirekt.de/plzserver/", "require": "ACZ", "zip": "\\d{5}", "zipex": "26133,53225"},
+  "data/DJ": {"id": "data/DJ", "key": "DJ", "name": "DJIBOUTI"},
+  "data/DK": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/DK", "key": "DK", "name": "DENMARK", "posturl": "http://www.postdanmark.dk/da/Privat/Kundeservice/postnummerkort/Sider/Find-postnummer.aspx", "require": "ACZ", "zip": "\\d{4}", "zipex": "8660,1566"},
+  "data/DM": {"id": "data/DM", "key": "DM", "name": "DOMINICA"},
+  "data/DO": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/DO", "key": "DO", "name": "DOMINICAN REP.", "posturl": "http://inposdom.gob.do/codigo-postal/", "zip": "\\d{5}", "zipex": "11903,10101"},
+  "data/DZ": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/DZ", "key": "DZ", "name": "ALGERIA", "zip": "\\d{5}", "zipex": "40304,16027"},
+  "data/EC": {"fmt": "%N%n%O%n%A%n%Z%n%C", "id": "data/EC", "key": "EC", "name": "ECUADOR", "posturl": "http://www.codigopostal.gob.ec/", "upper": "CZ", "zip": "\\d{6}", "zipex": "090105,092301"},
+  "data/EE": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/EE", "key": "EE", "name": "ESTONIA", "posturl": "https://www.omniva.ee/era/sihtnumbrite_otsing", "zip": "\\d{5}", "zipex": "69501,11212"},
+  "data/EG": {"fmt": "%N%n%O%n%A%n%C%n%S%n%Z", "id": "data/EG", "key": "EG", "lang": "ar", "languages": "ar", "lfmt": "%N%n%O%n%A%n%C%n%S%n%Z", "name": "EGYPT", "sub_isoids": "ASN~AST~ALX~IS~LX~BA~BH~GZ~DK~SUZ~SHR~GH~FYM~C~KB~MNF~MN~WAD~BNS~PTS~JS~DT~SHG~SIN~KN~KFS~MT", "sub_keys": "أسوان~أسيوط~الإسكندرية~الإسماعيلية~الأقصر~البحر الأحمر~البحيرة~الجيزة~الدقهلية~السويس~الشرقية~الغربية~الفيوم~القاهرة~القليوبية~المنوفية~المنيا~الوادي الجديد~بني سويف~بورسعيد~جنوب سيناء~دمياط~سوهاج~شمال سيناء~قنا~كفر الشيخ~مطروح", "sub_lnames": "Aswan Governorate~Asyut Governorate~Alexandria Governorate~Ismailia Governorate~Luxor Governorate~Red Sea Governorate~El Beheira Governorate~Giza Governorate~Dakahlia Governorate~Suez Governorate~Ash Sharqia Governorate~Gharbia Governorate~Faiyum Governorate~Cairo Governorate~Qalyubia Governorate~Menofia Governorate~Menia Governorate~New Valley Governorate~Beni Suef Governorate~Port Said Governorate~South Sinai Governorate~Damietta Governorate~Sohag Governorate~North Sinai Governorate~Qena Governorate~Kafr El Sheikh Governorate~Matrouh Governorate", "sub_zipexs": "81000~71000~21000,23000~41000~85000~84000~22000~12000~35000~43000~44000~31000~63000~11000~13000~32000~61000~72000~62000~42000~46000~34000~82000~45000~83000~33000~51000", "sub_zips": "81~71~2[13]~41~85~84~22~12~35~43~44~31~63~11~13~32~61~72~62~42~46~34~82~45~83~33~51", "zip": "\\d{5}", "zipex": "12411,11599"},
+  "data/EH": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/EH", "key": "EH", "name": "WESTERN SAHARA", "zip": "\\d{5}", "zipex": "70000,72000"},
+  "data/ER": {"id": "data/ER", "key": "ER", "name": "ERITREA"},
+  "data/ES": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/ES", "key": "ES", "lang": "es", "languages": "es~ca~gl~eu", "name": "SPAIN", "posturl": "http://www.correos.es/contenido/13-MenuRec2/04-MenuRec24/1010_s-CodPostal.asp", "require": "ACSZ", "sub_keys": "VI~AB~A~AL~O~AV~BA~B~BU~CC~CA~S~CS~CE~CR~CO~CU~GI~GR~GU~SS~H~HU~PM~J~C~LO~GC~LE~L~LU~M~MA~ML~MU~NA~OR~P~PO~SA~TF~SG~SE~SO~T~TE~TO~V~VA~BI~ZA~Z", "sub_names": "Álava~Albacete~Alicante~Almería~Asturias~Ávila~Badajoz~Barcelona~Burgos~Cáceres~Cádiz~Cantabria~Castellón~Ceuta~Ciudad Real~Córdoba~Cuenca~Girona~Granada~Guadalajara~Guipúzcoa~Huelva~Huesca~Islas Baleares~Jaén~La Coruña~La Rioja~Las Palmas~León~Lérida~Lugo~Madrid~Málaga~Melilla~Murcia~Navarra~Ourense~Palencia~Pontevedra~Salamanca~Santa Cruz de Tenerife~Segovia~Sevilla~Soria~Tarragona~Teruel~Toledo~Valencia~Valladolid~Vizcaya~Zamora~Zaragoza", "sub_zips": "01~02~03~04~33~05~06~08~09~10~11~39~12~51~13~14~16~17~18~19~20~21~22~07~23~15~26~35~24~25~27~28~29~52~30~31~32~34~36~37~38~40~41~42~43~44~45~46~47~48~49~50", "upper": "CS", "zip": "\\d{5}", "zipex": "28039,28300,28070"},
+  "data/ES--ca": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/ES--ca", "key": "ES", "lang": "ca", "name": "SPAIN", "posturl": "http://www.correos.es/contenido/13-MenuRec2/04-MenuRec24/1010_s-CodPostal.asp", "require": "ACSZ", "sub_keys": "A~AB~AL~VI~O~AV~BA~B~BI~BU~CC~CA~S~CS~CE~CR~CO~CU~GI~GR~GU~SS~H~HU~PM~J~C~LO~GC~LE~L~LU~M~MA~ML~MU~NA~OR~P~PO~SA~TF~SG~SE~SO~T~TE~TO~V~VA~ZA~Z", "sub_names": "Alacant~Albacete~Almeria~Araba~Asturias~Àvila~Badajoz~Barcelona~Bizkaia~Burgos~Cáceres~Cadis~Cantabria~Castelló~Ceuta~Ciudad Real~Córdoba~Cuenca~Girona~Granada~Guadalajara~Guipúscoa~Huelva~Huesca~Illes Balears~Jaén~La Corunya~La Rioja~Las Palmas~León~Lleida~Lugo~Madrid~Málaga~Melilla~Murcia~Navarra~Ourense~Palencia~Pontevedra~Salamanca~Santa Cruz de Tenerife~Segovia~Sevilla~Soria~Tarragona~Teruel~Toledo~València~Valladolid~Zamora~Zaragoza", "sub_zips": "03~02~04~01~33~05~06~08~48~09~10~11~39~12~51~13~14~16~17~18~19~20~21~22~07~23~15~26~35~24~25~27~28~29~52~30~31~32~34~36~37~38~40~41~42~43~44~45~46~47~49~50", "upper": "CS", "zip": "\\d{5}", "zipex": "28039,28300,28070"},
+  "data/ES--eu": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/ES--eu", "key": "ES", "lang": "eu", "name": "SPAIN", "posturl": "http://www.correos.es/contenido/13-MenuRec2/04-MenuRec24/1010_s-CodPostal.asp", "require": "ACSZ", "sub_keys": "A~AB~AL~VI~O~AV~BA~B~BI~BU~CC~CA~S~CS~CE~CR~C~CU~SS~GI~GR~GU~H~HU~PM~J~CO~LO~GC~LE~L~LU~M~MA~ML~MU~NA~OR~P~PO~SA~TF~SG~SE~SO~T~TE~TO~V~VA~ZA~Z", "sub_names": "Alacant~Albacete~Almería~Araba~Asturias~Ávila~Badajoz~Barcelona~Bizkaia~Burgos~Cáceres~Cádiz~Cantabria~Castelló~Ceuta~Ciudad Real~Coruña~Cuenca~Gipuzkoa~Girona~Granada~Guadalajara~Huelva~Huesca~Illes Balears~Jaén~Kordoba~La Rioja~Las Palmas~León~Lleida~Lugo~Madrid~Málaga~Melilla~Murtzia~Nafarroa~Ourense~Palentzia~Pontevedra~Salamanca~Santa Cruz Tenerifekoa~Segovia~Sevilla~Soria~Tarragona~Teruel~Toledo~Valentzia~Valladolid~Zamora~Zaragoza", "sub_zips": "03~02~04~01~33~05~06~08~48~09~10~11~39~12~51~13~15~16~20~17~18~19~21~22~07~23~14~26~35~24~25~27~28~29~52~30~31~32~34~36~37~38~40~41~42~43~44~45~46~47~49~50", "upper": "CS", "zip": "\\d{5}", "zipex": "28039,28300,28070"},
+  "data/ES--gl": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/ES--gl", "key": "ES", "lang": "gl", "name": "SPAIN", "posturl": "http://www.correos.es/contenido/13-MenuRec2/04-MenuRec24/1010_s-CodPostal.asp", "require": "ACSZ", "sub_keys": "C~A~VI~AB~AL~GC~O~AV~BA~B~BI~BU~CC~CA~S~CS~CE~CR~CO~CU~GR~GU~SS~H~HU~PM~LO~LE~L~LU~M~MA~ML~MU~NA~OR~P~PO~SA~TF~SG~SE~SO~T~TE~TO~V~VA~J~GI~ZA~Z", "sub_names": "A Coruña~Alacant~Álava~Albacete~Almería~As Palmas~Asturias~Ávila~Badaxoz~Barcelona~Biscaia~Burgos~Cáceres~Cádiz~Cantabria~Castelló~Ceuta~Cidade Real~Córdoba~Cuenca~Granada~Guadalajara~Guipúscoa~Huelva~Huesca~Illas Baleares~La Rioja~León~Lleida~Lugo~Madrid~Málaga~Melilla~Murcia~Navarra~Ourense~Palencia~Pontevedra~Salamanca~Santa Cruz de Tenerife~Segovia~Sevilla~Soria~Tarragona~Teruel~Toledo~Valencia~Valladolid~Xaén~Xirona~Zamora~Zaragoza", "sub_zips": "15~03~01~02~04~35~33~05~06~08~48~09~10~11~39~12~51~13~14~16~18~19~20~21~22~07~26~24~25~27~28~29~52~30~31~32~34~36~37~38~40~41~42~43~44~45~46~47~23~17~49~50", "upper": "CS", "zip": "\\d{5}", "zipex": "28039,28300,28070"},
+  "data/ET": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/ET", "key": "ET", "name": "ETHIOPIA", "zip": "\\d{4}", "zipex": "1000"},
+  "data/FI": {"fmt": "%O%n%N%n%A%nFI-%Z %C", "id": "data/FI", "key": "FI", "name": "FINLAND", "postprefix": "FI-", "posturl": "http://www.verkkoposti.com/e3/postinumeroluettelo", "require": "ACZ", "zip": "\\d{5}", "zipex": "00550,00011"},
+  "data/FJ": {"id": "data/FJ", "key": "FJ", "name": "FIJI"},
+  "data/FK": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/FK", "key": "FK", "name": "FALKLAND ISLANDS (MALVINAS)", "require": "ACZ", "upper": "CZ", "zip": "FIQQ 1ZZ", "zipex": "FIQQ 1ZZ"},
+  "data/FM": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/FM", "key": "FM", "name": "MICRONESIA (Federated State of)", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACSZ", "state_name_type": "state", "upper": "ACNOS", "zip": "(9694[1-4])(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "96941,96944"},
+  "data/FO": {"fmt": "%N%n%O%n%A%nFO%Z %C", "id": "data/FO", "key": "FO", "name": "FAROE ISLANDS", "postprefix": "FO", "posturl": "http://www.postur.fo/", "zip": "\\d{3}", "zipex": "100"},
+  "data/FR": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/FR", "key": "FR", "name": "FRANCE", "posturl": "http://www.laposte.fr/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal", "require": "ACZ", "upper": "CX", "zip": "\\d{2} ?\\d{3}", "zipex": "33380,34092,33506"},
+  "data/GA": {"id": "data/GA", "key": "GA", "name": "GABON"},
+  "data/GB": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/GB", "key": "GB", "locality_name_type": "post_town", "name": "UNITED KINGDOM", "posturl": "http://www.royalmail.com/postcode-finder", "require": "ACZ", "upper": "CZ", "zip": "GIR ?0AA|(?:(?:AB|AL|B|BA|BB|BD|BF|BH|BL|BN|BR|BS|BT|BX|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(?:\\d[\\dA-Z]? ?\\d[ABD-HJLN-UW-Z]{2}))|BFPO ?\\d{1,4}", "zipex": "EC1Y 8SY,GIR 0AA,M2 5BQ,M34 4AB,CR0 2YR,DN16 9AA,W1A 4ZZ,EC1A 1HQ,OX14 4PG,BS18 8HF,NR25 7HG,RH6 0NP,BH23 6AA,B6 5BA,SO23 9AP,PO1 3AX,BFPO 61"},
+  "data/GD": {"id": "data/GD", "key": "GD", "name": "GRENADA (WEST INDIES)"},
+  "data/GE": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/GE", "key": "GE", "name": "GEORGIA", "posturl": "http://www.georgianpost.ge/index.php?page=10", "zip": "\\d{4}", "zipex": "0101"},
+  "data/GF": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/GF", "key": "GF", "name": "FRENCH GUIANA", "posturl": "http://www.laposte.fr/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal", "require": "ACZ", "upper": "ACX", "zip": "9[78]3\\d{2}", "zipex": "97300"},
+  "data/GG": {"fmt": "%N%n%O%n%A%n%C%nGUERNSEY%n%Z", "id": "data/GG", "key": "GG", "name": "CHANNEL ISLANDS", "posturl": "http://www.guernseypost.com/postcode_finder/", "require": "ACZ", "upper": "CZ", "zip": "GY\\d[\\dA-Z]? ?\\d[ABD-HJLN-UW-Z]{2}", "zipex": "GY1 1AA,GY2 2BT"},
+  "data/GH": {"id": "data/GH", "key": "GH", "name": "GHANA"},
+  "data/GI": {"fmt": "%N%n%O%n%A%nGIBRALTAR%n%Z", "id": "data/GI", "key": "GI", "name": "GIBRALTAR", "require": "A", "zip": "GX11 1AA", "zipex": "GX11 1AA"},
+  "data/GL": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/GL", "key": "GL", "name": "GREENLAND", "require": "ACZ", "zip": "39\\d{2}", "zipex": "3900,3950,3911"},
+  "data/GM": {"id": "data/GM", "key": "GM", "name": "GAMBIA"},
+  "data/GN": {"fmt": "%N%n%O%n%Z %A %C", "id": "data/GN", "key": "GN", "name": "GUINEA", "zip": "\\d{3}", "zipex": "001,200,100"},
+  "data/GP": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/GP", "key": "GP", "name": "GUADELOUPE", "posturl": "http://www.laposte.fr/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal", "require": "ACZ", "upper": "ACX", "zip": "9[78][01]\\d{2}", "zipex": "97100"},
+  "data/GQ": {"id": "data/GQ", "key": "GQ", "name": "EQUATORIAL GUINEA"},
+  "data/GR": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/GR", "key": "GR", "name": "GREECE", "posturl": "http://www.elta.gr/findapostcode.aspx", "require": "ACZ", "zip": "\\d{3} ?\\d{2}", "zipex": "151 24,151 10,101 88"},
+  "data/GS": {"fmt": "%N%n%O%n%A%n%n%C%n%Z", "id": "data/GS", "key": "GS", "name": "SOUTH GEORGIA", "require": "ACZ", "upper": "CZ", "zip": "SIQQ 1ZZ", "zipex": "SIQQ 1ZZ"},
+  "data/GT": {"fmt": "%N%n%O%n%A%n%Z- %C", "id": "data/GT", "key": "GT", "name": "GUATEMALA", "zip": "\\d{5}", "zipex": "09001,01501"},
+  "data/GU": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/GU", "key": "GU", "name": "GUAM", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACZ", "upper": "ACNO", "zip": "(969(?:[12]\\d|3[12]))(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "96910,96931"},
+  "data/GW": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/GW", "key": "GW", "name": "GUINEA-BISSAU", "zip": "\\d{4}", "zipex": "1000,1011"},
+  "data/GY": {"id": "data/GY", "key": "GY", "name": "GUYANA"},
+  "data/HK": {"fmt": "%S%n%C%n%A%n%O%n%N", "id": "data/HK", "key": "HK", "lang": "zh-Hant", "languages": "zh-Hant~en", "lfmt": "%N%n%O%n%A%n%C%n%S", "locality_name_type": "district", "name": "HONG KONG", "require": "AS", "state_name_type": "area", "sub_keys": "Kowloon~Hong Kong Island~New Territories", "sub_mores": "true~true~true", "sub_names": "九龍~香港島~新界", "upper": "S"},
+  "data/HK--en": {"fmt": "%S%n%C%n%A%n%O%n%N", "id": "data/HK--en", "key": "HK", "lang": "en", "lfmt": "%N%n%O%n%A%n%C%n%S", "locality_name_type": "district", "name": "HONG KONG", "require": "AS", "state_name_type": "area", "sub_keys": "Hong Kong Island~Kowloon~New Territories", "sub_lnames": "Hong Kong Island~Kowloon~New Territories", "sub_mores": "true~true~true", "upper": "S"},
+  "data/HM": {"fmt": "%O%n%N%n%A%n%C %S %Z", "id": "data/HM", "key": "HM", "name": "HEARD AND MCDONALD ISLANDS", "upper": "CS", "zip": "\\d{4}", "zipex": "7050"},
+  "data/HN": {"fmt": "%N%n%O%n%A%n%C, %S%n%Z", "id": "data/HN", "key": "HN", "name": "HONDURAS", "require": "ACS", "zip": "\\d{5}", "zipex": "31301"},
+  "data/HR": {"fmt": "%N%n%O%n%A%nHR-%Z %C", "id": "data/HR", "key": "HR", "name": "CROATIA", "postprefix": "HR-", "posturl": "http://www.posta.hr/default.aspx?pretpum", "zip": "\\d{5}", "zipex": "10000,21001,10002"},
+  "data/HT": {"fmt": "%N%n%O%n%A%nHT%Z %C", "id": "data/HT", "key": "HT", "name": "HAITI", "postprefix": "HT", "zip": "\\d{4}", "zipex": "6120,5310,6110,8510"},
+  "data/HU": {"fmt": "%N%n%O%n%C%n%A%n%Z", "id": "data/HU", "key": "HU", "name": "HUNGARY (Rep.)", "posturl": "http://posta.hu/ugyfelszolgalat/iranyitoszam_kereso", "require": "ACZ", "upper": "ACNO", "zip": "\\d{4}", "zipex": "1037,2380,1540"},
+  "data/ID": {"fmt": "%N%n%O%n%A%n%C%n%S %Z", "id": "data/ID", "key": "ID", "lang": "id", "languages": "id", "name": "INDONESIA", "require": "AS", "sub_isoids": "AC~BA~BT~BE~YO~JK~GO~JA~JB~JT~JI~KB~KS~KT~KI~KU~BB~KR~LA~MA~MU~NB~NT~PA~PB~RI~SR~SN~ST~SG~SA~SB~SS~SU", "sub_keys": "Aceh~Bali~Banten~Bengkulu~Daerah Istimewa Yogyakarta~DKI Jakarta~Gorontalo~Jambi~Jawa Barat~Jawa Tengah~Jawa Timur~Kalimantan Barat~Kalimantan Selatan~Kalimantan Tengah~Kalimantan Timur~Kalimantan Utara~Kepulauan Bangka Belitung~Kepulauan Riau~Lampung~Maluku~Maluku Utara~Nusa Tenggara Barat~Nusa Tenggara Timur~Papua~Papua Barat~Riau~Sulawesi Barat~Sulawesi Selatan~Sulawesi Tengah~Sulawesi Tenggara~Sulawesi Utara~Sumatera Barat~Sumatera Selatan~Sumatera Utara", "zip": "\\d{5}", "zipex": "40115"},
+  "data/IE": {"fmt": "%N%n%O%n%A%n%D%n%C%n%S %Z", "id": "data/IE", "key": "IE", "lang": "en", "languages": "en", "name": "IRELAND", "posturl": "https://finder.eircode.ie", "state_name_type": "county", "sub_isoids": "CW~CN~CE~C~DL~D~G~KY~KE~KK~LS~LM~LK~LD~LH~MO~MH~MN~OY~RN~SO~TA~WD~WH~WX~WW", "sub_keys": "Co. Carlow~Co. Cavan~Co. Clare~Co. Cork~Co. Donegal~Co. Dublin~Co. Galway~Co. Kerry~Co. Kildare~Co. Kilkenny~Co. Laois~Co. Leitrim~Co. Limerick~Co. Longford~Co. Louth~Co. Mayo~Co. Meath~Co. Monaghan~Co. Offaly~Co. Roscommon~Co. Sligo~Co. Tipperary~Co. Waterford~Co. Westmeath~Co. Wexford~Co. Wicklow", "sublocality_name_type": "townland", "zip": "[\\dA-Z]{3} ?[\\dA-Z]{4}", "zip_name_type": "eircode", "zipex": "A65 F4E2"},
+  "data/IL": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/IL", "key": "IL", "name": "ISRAEL", "posturl": "http://www.israelpost.co.il/zipcode.nsf/demozip?openform", "zip": "\\d{5}(?:\\d{2})?", "zipex": "9614303"},
+  "data/IM": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/IM", "key": "IM", "name": "ISLE OF MAN", "posturl": "https://www.iompost.com/tools-forms/postcode-finder/", "require": "ACZ", "upper": "CZ", "zip": "IM\\d[\\dA-Z]? ?\\d[ABD-HJLN-UW-Z]{2}", "zipex": "IM2 1AA,IM99 1PS"},
+  "data/IN": {"fmt": "%N%n%O%n%A%n%C %Z%n%S", "id": "data/IN", "key": "IN", "lang": "en", "languages": "en~hi", "name": "INDIA", "posturl": "https://www.indiapost.gov.in/vas/pages/FindPinCode.aspx", "require": "ACSZ", "state_name_type": "state", "sub_isoids": "AN~AP~AR~AS~BR~CH~CT~DN~DD~DL~GA~GJ~HR~HP~JK~JH~KA~KL~LD~MP~MH~MN~ML~MZ~NL~OR~PY~PB~RJ~SK~TN~TG~TR~UP~UT~WB", "sub_keys": "Andaman and Nicobar Islands~Andhra Pradesh~Arunachal Pradesh~Assam~Bihar~Chandigarh~Chhattisgarh~Dadra and Nagar Haveli~Daman and Diu~Delhi~Goa~Gujarat~Haryana~Himachal Pradesh~Jammu and Kashmir~Jharkhand~Karnataka~Kerala~Lakshadweep~Madhya Pradesh~Maharashtra~Manipur~Meghalaya~Mizoram~Nagaland~Odisha~Puducherry~Punjab~Rajasthan~Sikkim~Tamil Nadu~Telangana~Tripura~Uttar Pradesh~Uttarakhand~West Bengal", "sub_names": "Andaman & Nicobar~Andhra Pradesh~Arunachal Pradesh~Assam~Bihar~Chandigarh~Chhattisgarh~Dadra & Nagar Haveli~Daman & Diu~Delhi~Goa~Gujarat~Haryana~Himachal Pradesh~Jammu & Kashmir~Jharkhand~Karnataka~Kerala~Lakshadweep~Madhya Pradesh~Maharashtra~Manipur~Meghalaya~Mizoram~Nagaland~Odisha~Puducherry~Punjab~Rajasthan~Sikkim~Tamil Nadu~Telangana~Tripura~Uttar Pradesh~Uttarakhand~West Bengal", "sub_zips": "744~5[0-3]~79[0-2]~78~8[0-5]~16|1440[3-9]~49~396~396~11~403~3[6-9]~1[23]~17~1[89]~81[4-9]|82|83[0-5]~5[4-9]|53[7-9]~6[7-9]|6010|607008|777~682~4[5-8]|490~4[0-4]~79[56]~79[34]~796~79[78]~7[5-7]~60[579]~1[456]~3[0-4]~737|750~6[0-6]|536~5[0-3]~799~2[0-35-8]|24[0-7]|26[12]~24[46-9]|254|26[23]~7[0-4]", "zip": "\\d{6}", "zip_name_type": "pin", "zipex": "110034,110001"},
+  "data/IN--hi": {"fmt": "%N%n%O%n%A%n%C %Z%n%S", "id": "data/IN--hi", "key": "IN", "lang": "hi", "name": "INDIA", "posturl": "https://www.indiapost.gov.in/vas/pages/FindPinCode.aspx", "require": "ACSZ", "state_name_type": "state", "sub_isoids": "AN~AR~AS~AP~UP~UT~OR~KA~KL~GJ~GA~CH~CT~JK~JH~TN~TG~TR~DD~DN~DL~NL~PB~WB~PY~BR~MN~MP~MH~MZ~ML~RJ~LD~SK~HR~HP", "sub_keys": "Andaman & Nicobar~Arunachal Pradesh~Assam~Andhra Pradesh~Uttar Pradesh~Uttarakhand~Odisha~Karnataka~Kerala~Gujarat~Goa~Chandigarh~Chhattisgarh~Jammu & Kashmir~Jharkhand~Tamil Nadu~Telangana~Tripura~Daman & Diu~Dadra & Nagar Haveli~Delhi~Nagaland~Punjab~West Bengal~Puducherry~Bihar~Manipur~Madhya Pradesh~Maharashtra~Mizoram~Meghalaya~Rajasthan~Lakshadweep~Sikkim~Haryana~Himachal Pradesh", "sub_names": "अंडमान और निकोबार द्वीपसमूह~अरुणाचल प्रदेश~असम~आंध्र प्रदेश~उत्तर प्रदेश~उत्तराखण्ड~ओड़िशा~कर्नाटक~केरल~गुजरात~गोआ~चंडीगढ़~छत्तीसगढ़~जम्मू और कश्मीर~झारखण्ड~तमिल नाडु~तेलंगाना~त्रिपुरा~दमन और दीव~दादरा और नगर हवेली~दिल्ली~नागालैंड~पंजाब~पश्चिम बंगाल~पांडिचेरी~बिहार~मणिपुर~मध्य प्रदेश~महाराष्ट्र~मिजोरम~मेघालय~राजस्थान~लक्षद्वीप~सिक्किम~हरियाणा~हिमाचल प्रदेश", "sub_zips": "744~79[0-2]~78~5[0-3]~2[0-35-8]|24[0-7]|26[12]~24[46-9]|254|26[23]~7[5-7]~5[4-9]|53[7-9]~6[7-9]|6010|607008|777~3[6-9]~403~16|1440[3-9]~49~1[89]~81[4-9]|82|83[0-5]~6[0-6]|536~5[0-3]~799~396~396~11~79[78]~1[456]~7[0-4]~60[579]~8[0-5]~79[56]~4[5-8]|490~4[0-4]~796~79[34]~3[0-4]~682~737|750~1[23]~17", "zip": "\\d{6}", "zip_name_type": "pin", "zipex": "110034,110001"},
+  "data/IO": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/IO", "key": "IO", "name": "BRITISH INDIAN OCEAN TERRITORY", "require": "ACZ", "upper": "CZ", "zip": "BBND 1ZZ", "zipex": "BBND 1ZZ"},
+  "data/IQ": {"fmt": "%O%n%N%n%A%n%C, %S%n%Z", "id": "data/IQ", "key": "IQ", "name": "IRAQ", "require": "ACS", "upper": "CS", "zip": "\\d{5}", "zipex": "31001"},
+  "data/IR": {"fmt": "%O%n%N%n%S%n%C, %D%n%A%n%Z", "id": "data/IR", "key": "IR", "lang": "fa", "languages": "fa", "name": "IRAN", "sub_isoids": "01~02~03~04~32~05~06~07~08~29~30~31~10~11~12~13~14~28~26~16~15~17~18~27~19~20~21~22~23~24~25", "sub_keys": "استان آذربایجان شرقی~استان آذربایجان غربی~استان اردبیل~استان اصفهان~استان البرز~استان ایلام~استان بوشهر~استان تهران~استان چهارمحال و بختیاری~استان خراسان جنوبی~استان خراسان رضوی~استان خراسان شمالی~استان خوزستان~استان زنجان~استان سمنان~استان سیستان و بلوچستان~استان فارس~استان قزوین~استان قم~استان کردستان~استان کرمان~استان کرمانشاه~استان کهگیلویه و بویراحمد~استان گلستان~استان گیلان~استان لرستان~استان مازندران~استان مرکزی~استان هرمزگان~استان همدان~استان یزد", "sub_lnames": "East Azerbaijan Province~West Azerbaijan Province~Ardabil Province~Isfahan Province~Alborz Province~Ilam Province~Bushehr Province~Tehran Province~Chaharmahal and Bakhtiari Province~South Khorasan Province~Razavi Khorasan Province~North Khorasan Province~Khuzestan Province~Zanjan Province~Semnan Province~Sistan and Baluchestan Province~Fars Province~Qazvin Province~Qom Province~Kurdistan Province~Kerman Province~Kermanshah Province~Kohgiluyeh and Boyer-Ahmad Province~Golestan Province~Gilan Province~Lorestan Province~Mazandaran Province~Markazi Province~Hormozgan Province~Hamadan Province~Yazd Province", "sublocality_name_type": "neighborhood", "zip": "\\d{5}-?\\d{5}", "zipex": "11936-12345"},
+  "data/IS": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/IS", "key": "IS", "name": "ICELAND", "posturl": "http://www.postur.is/einstaklingar/posthus/postnumer/", "zip": "\\d{3}", "zipex": "320,121,220,110"},
+  "data/IT": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/IT", "key": "IT", "lang": "it", "languages": "it", "name": "ITALY", "posturl": "http://www.poste.it/online/cercacap/", "require": "ACSZ", "sub_isoids": "AG~AL~AN~AO~AR~AP~AT~AV~BA~BT~BL~BN~BG~BI~BO~BZ~BS~BR~CA~CL~CB~CI~CE~CT~CZ~CH~CO~CS~CR~KR~CN~EN~FM~FE~FI~FG~FC~FR~GE~GO~GR~IM~IS~AQ~SP~LT~LE~LC~LI~LO~LU~MC~MN~MS~MT~VS~ME~MI~MO~MB~NA~NO~NU~OG~OT~OR~PD~PA~PR~PV~PG~PU~PE~PC~PI~PT~PN~PZ~PO~RG~RA~RC~RE~RI~RN~RM~RO~SA~SS~SV~SI~SR~SO~TA~TE~TR~TO~TP~TN~TV~TS~UD~VA~VE~VB~VC~VR~VV~VI~VT", "sub_keys": "AG~AL~AN~AO~AR~AP~AT~AV~BA~BT~BL~BN~BG~BI~BO~BZ~BS~BR~CA~CL~CB~CI~CE~CT~CZ~CH~CO~CS~CR~KR~CN~EN~FM~FE~FI~FG~FC~FR~GE~GO~GR~IM~IS~AQ~SP~LT~LE~LC~LI~LO~LU~MC~MN~MS~MT~VS~ME~MI~MO~MB~NA~NO~NU~OG~OT~OR~PD~PA~PR~PV~PG~PU~PE~PC~PI~PT~PN~PZ~PO~RG~RA~RC~RE~RI~RN~RM~RO~SA~SS~SV~SI~SR~SO~TA~TE~TR~TO~TP~TN~TV~TS~UD~VA~VE~VB~VC~VR~VV~VI~VT", "sub_names": "Agrigento~Alessandria~Ancona~Aosta~Arezzo~Ascoli Piceno~Asti~Avellino~Bari~Barletta-Andria-Trani~Belluno~Benevento~Bergamo~Biella~Bologna~Bolzano~Brescia~Brindisi~Cagliari~Caltanissetta~Campobasso~Carbonia-Iglesias~Caserta~Catania~Catanzaro~Chieti~Como~Cosenza~Cremona~Crotone~Cuneo~Enna~Fermo~Ferrara~Firenze~Foggia~Forlì-Cesena~Frosinone~Genova~Gorizia~Grosseto~Imperia~Isernia~L'Aquila~La Spezia~Latina~Lecce~Lecco~Livorno~Lodi~Lucca~Macerata~Mantova~Massa-Carrara~Matera~Medio Campidano~Messina~Milano~Modena~Monza e Brianza~Napoli~Novara~Nuoro~Ogliastra~Olbia-Tempio~Oristano~Padova~Palermo~Parma~Pavia~Perugia~Pesaro e Urbino~Pescara~Piacenza~Pisa~Pistoia~Pordenone~Potenza~Prato~Ragusa~Ravenna~Reggio Calabria~Reggio Emilia~Rieti~Rimini~Roma~Rovigo~Salerno~Sassari~Savona~Siena~Siracusa~Sondrio~Taranto~Teramo~Terni~Torino~Trapani~Trento~Treviso~Trieste~Udine~Varese~Venezia~Verbano-Cusio-Ossola~Vercelli~Verona~Vibo Valentia~Vicenza~Viterbo", "sub_zips": "92~15~60~11~52~63~14~83~70~76[01]~32~82~24~13[89]~40~39~25~72~0912[1-9]|0913[0-4]|0901[0289]|0902[03468]|0903[0234]|0904|0803[035]|08043~93~860[1-4]|86100~0901[013-7]~81~95~88[01]~66~22~87~26[01]~88[89]~12|18025~94~638|63900~44~50~71~47[015]~03~16~34[01]7~58~18~860[7-9]|86170~67~19~04~73~23[89]~57~26[89]~55~62~46~54~75~0902[012579]|0903[015-9]|09040~98~20~41~208|20900~80~28[01]~080[1-3]|08100~08037|0804[024-9]~08020|0702|0703[08]~090[7-9]|09170|0801[039]|0803[04]~35~90~43~27~06~61~65~29~56~51~330[7-9]|33170~85~59~97~48~89[01]~42~02~47[89]~00~45~84~070[14]|0703[0-79]|07100~17|12071~53~96~23[01]~74~64~05~10~91~38~31~3401|341[0-689]|34062~330[1-5]|33100~21~30~28[89]~13[01]~37~89[89]~36~01", "upper": "CS", "zip": "\\d{5}", "zipex": "00144,47037,39049"},
+  "data/JE": {"fmt": "%N%n%O%n%A%n%C%nJERSEY%n%Z", "id": "data/JE", "key": "JE", "name": "CHANNEL ISLANDS", "posturl": "http://www.jerseypost.com/tools/postcode-address-finder/", "require": "ACZ", "upper": "CZ", "zip": "JE\\d[\\dA-Z]? ?\\d[ABD-HJLN-UW-Z]{2}", "zipex": "JE1 1AA,JE2 2BT"},
+  "data/JM": {"fmt": "%N%n%O%n%A%n%C%n%S %X", "id": "data/JM", "key": "JM", "lang": "en", "languages": "en", "name": "JAMAICA", "require": "ACS", "state_name_type": "parish", "sub_isoids": "13~09~01~12~04~02~06~14~11~08~05~03~07~10", "sub_keys": "Clarendon~Hanover~Kingston~Manchester~Portland~St. Andrew~St. Ann~St. Catherine~St. Elizabeth~St. James~St. Mary~St. Thomas~Trelawny~Westmoreland"},
+  "data/JO": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/JO", "key": "JO", "name": "JORDAN", "zip": "\\d{5}", "zipex": "11937,11190"},
+  "data/JP": {"fmt": "〒%Z%n%S%n%A%n%O%n%N", "id": "data/JP", "key": "JP", "lang": "ja", "languages": "ja", "lfmt": "%N%n%O%n%A, %S%n%Z", "name": "JAPAN", "posturl": "http://www.post.japanpost.jp/zipcode/", "require": "ASZ", "state_name_type": "prefecture", "sub_isoids": "01~02~03~04~05~06~07~08~09~10~11~12~13~14~15~16~17~18~19~20~21~22~23~24~25~26~27~28~29~30~31~32~33~34~35~36~37~38~39~40~41~42~43~44~45~46~47", "sub_keys": "北海道~青森県~岩手県~宮城県~秋田県~山形県~福島県~茨城県~栃木県~群馬県~埼玉県~千葉県~東京都~神奈川県~新潟県~富山県~石川県~福井県~山梨県~長野県~岐阜県~静岡県~愛知県~三重県~滋賀県~京都府~大阪府~兵庫県~奈良県~和歌山県~鳥取県~島根県~岡山県~広島県~山口県~徳島県~香川県~愛媛県~高知県~福岡県~佐賀県~長崎県~熊本県~大分県~宮崎県~鹿児島県~沖縄県", "sub_lnames": "Hokkaido~Aomori~Iwate~Miyagi~Akita~Yamagata~Fukushima~Ibaraki~Tochigi~Gunma~Saitama~Chiba~Tokyo~Kanagawa~Niigata~Toyama~Ishikawa~Fukui~Yamanashi~Nagano~Gifu~Shizuoka~Aichi~Mie~Shiga~Kyoto~Osaka~Hyogo~Nara~Wakayama~Tottori~Shimane~Okayama~Hiroshima~Yamaguchi~Tokushima~Kagawa~Ehime~Kochi~Fukuoka~Saga~Nagasaki~Kumamoto~Oita~Miyazaki~Kagoshima~Okinawa", "sub_zips": "0[4-9]|00[1-7]~03|018~02~98~01~99~9[67]~3[01]~32|311|349~37|38[49]~3[3-6]~2[6-9]~1[0-8]|19[0-8]|20~2[1-5]|199~9[45]|389~93~92|939~91|922~40~3[89]|949~50~4[1-9]~4[4-9]|431~51|498|647~52~6[0-2]|520~5[3-9]|618|630~6[5-7]|563~63|64[78]~64|519~68~69|68[45]~7[01]~7[23]~7[45]~77~76~79~78~8[0-3]|871~84~85|81[17]|848~86~87|839~88~89~90", "upper": "S", "zip": "\\d{3}-?\\d{4}", "zipex": "154-0023,350-1106,951-8073,112-0001,208-0032,231-0012"},
+  "data/KE": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/KE", "key": "KE", "name": "KENYA", "zip": "\\d{5}", "zipex": "20100,00100"},
+  "data/KG": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/KG", "key": "KG", "name": "KYRGYZSTAN", "zip": "\\d{6}", "zipex": "720001"},
+  "data/KH": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/KH", "key": "KH", "name": "CAMBODIA", "zip": "\\d{5}", "zipex": "12203,14206,12000"},
+  "data/KI": {"fmt": "%N%n%O%n%A%n%S%n%C", "id": "data/KI", "key": "KI", "name": "KIRIBATI", "state_name_type": "island", "upper": "ACNOS"},
+  "data/KM": {"id": "data/KM", "key": "KM", "name": "COMOROS", "upper": "AC"},
+  "data/KN": {"fmt": "%N%n%O%n%A%n%C, %S", "id": "data/KN", "key": "KN", "lang": "en", "languages": "en", "name": "SAINT KITTS AND NEVIS", "require": "ACS", "state_name_type": "island", "sub_isoids": "N~K", "sub_keys": "Nevis~St. Kitts"},
+  "data/KP": {"fmt": "%Z%n%S%n%C%n%A%n%O%n%N", "id": "data/KP", "key": "KP", "lang": "ko", "languages": "ko", "lfmt": "%N%n%O%n%A%n%C%n%S, %Z", "name": "NORTH KOREA", "sub_isoids": "07~13~10~04~02~03~01~08~09~05~06", "sub_keys": "강원도~라선 특별시~량강도~자강도~평안 남도~평안 북도~평양 직할시~함경 남도~함경 북도~황해남도~황해북도", "sub_lnames": "Kangwon~Rason~Ryanggang~Chagang~South Pyongan~North Pyongan~Pyongyang~South Hamgyong~North Hamgyong~South Hwanghae~North Hwanghae"},
+  "data/KR": {"fmt": "%S %C%D%n%A%n%O%n%N%n%Z", "id": "data/KR", "key": "KR", "lang": "ko", "languages": "ko", "lfmt": "%N%n%O%n%A%n%D%n%C%n%S%n%Z", "name": "SOUTH KOREA", "posturl": "http://www.epost.go.kr/search/zipcode/search5.jsp", "require": "ACSZ", "state_name_type": "do_si", "sub_isoids": "42~41~48~47~29~27~30~26~11~50~31~28~46~45~49~44~43", "sub_keys": "강원도~경기도~경상남도~경상북도~광주광역시~대구광역시~대전광역시~부산광역시~서울특별시~세종특별자치시~울산광역시~인천광역시~전라남도~전라북도~제주특별자치도~충청남도~충청북도", "sub_lnames": "Gangwon-do~Gyeonggi-do~Gyeongsangnam-do~Gyeongsangbuk-do~Gwangju~Daegu~Daejeon~Busan~Seoul~Sejong~Ulsan~Incheon~Jeollanam-do~Jeollabuk-do~Jeju-do~Chungcheongnam-do~Chungcheongbuk-do", "sub_mores": "true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true", "sub_names": "강원~경기~경남~경북~광주~대구~대전~부산~서울~세종~울산~인천~전남~전북~제주~충남~충북", "sub_zipexs": "25627~12410~53286~38540~62394~42456~34316~46706~06321~30065~44782~23024~59222~56445~63563~32832~28006", "sub_zips": "2[456]\\d{2}~1[0-8]\\d{2}~5[0-3]\\d{2}~(?:3[6-9]|40)\\d{2}~6[12]\\d{2}~4[12]\\d{2}~3[45]\\d{2}~4[6-9]\\d{2}~0[1-8]\\d{2}~30[01]\\d~4[45]\\d{2}~2[1-3]\\d{2}~5[7-9]\\d{2}~5[4-6]\\d{2}~63[0-356]\\d~3[1-3]\\d{2}~2[789]\\d{2}", "sublocality_name_type": "district", "upper": "Z", "zip": "\\d{5}", "zipex": "03051"},
+  "data/KW": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/KW", "key": "KW", "name": "KUWAIT", "zip": "\\d{5}", "zipex": "54541,54551,54404,13009"},
+  "data/KY": {"fmt": "%N%n%O%n%A%n%S %Z", "id": "data/KY", "key": "KY", "lang": "en", "languages": "en", "name": "CAYMAN ISLANDS", "posturl": "http://www.caymanpost.gov.ky/", "require": "AS", "state_name_type": "island", "sub_keys": "Cayman Brac~Grand Cayman~Little Cayman", "zip": "KY\\d-\\d{4}", "zipex": "KY1-1100,KY1-1702,KY2-2101"},
+  "data/KZ": {"fmt": "%Z%n%S%n%C%n%A%n%O%n%N", "id": "data/KZ", "key": "KZ", "name": "KAZAKHSTAN", "zip": "\\d{6}", "zipex": "040900,050012"},
+  "data/LA": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/LA", "key": "LA", "name": "LAO (PEOPLE'S DEM. REP.)", "zip": "\\d{5}", "zipex": "01160,01000"},
+  "data/LB": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/LB", "key": "LB", "name": "LEBANON", "zip": "(?:\\d{4})(?: ?(?:\\d{4}))?", "zipex": "2038 3054,1107 2810,1000"},
+  "data/LC": {"id": "data/LC", "key": "LC", "name": "SAINT LUCIA"},
+  "data/LI": {"fmt": "%O%n%N%n%A%nFL-%Z %C", "id": "data/LI", "key": "LI", "name": "LIECHTENSTEIN", "postprefix": "FL-", "posturl": "http://www.post.ch/db/owa/pv_plz_pack/pr_main", "require": "ACZ", "zip": "948[5-9]|949[0-8]", "zipex": "9496,9491,9490,9485"},
+  "data/LK": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/LK", "key": "LK", "name": "SRI LANKA", "posturl": "http://www.slpost.gov.lk/", "zip": "\\d{5}", "zipex": "20000,00100"},
+  "data/LR": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/LR", "key": "LR", "name": "LIBERIA", "zip": "\\d{4}", "zipex": "1000"},
+  "data/LS": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/LS", "key": "LS", "name": "LESOTHO", "zip": "\\d{3}", "zipex": "100"},
+  "data/LT": {"fmt": "%O%n%N%n%A%nLT-%Z %C", "id": "data/LT", "key": "LT", "name": "LITHUANIA", "postprefix": "LT-", "posturl": "http://www.post.lt/lt/?id=316", "zip": "\\d{5}", "zipex": "04340,03500"},
+  "data/LU": {"fmt": "%O%n%N%n%A%nL-%Z %C", "id": "data/LU", "key": "LU", "name": "LUXEMBOURG", "postprefix": "L-", "posturl": "https://www.post.lu/fr/grandes-entreprises/solutions-postales/rechercher-un-code-postal", "require": "ACZ", "zip": "\\d{4}", "zipex": "4750,2998"},
+  "data/LV": {"fmt": "%N%n%O%n%A%n%C, %Z", "id": "data/LV", "key": "LV", "name": "LATVIA", "posturl": "http://www.pasts.lv/lv/uzzinas/nodalas/", "zip": "LV-\\d{4}", "zipex": "LV-1073,LV-1000"},
+  "data/LY": {"id": "data/LY", "key": "LY", "name": "LIBYA"},
+  "data/MA": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/MA", "key": "MA", "name": "MOROCCO", "zip": "\\d{5}", "zipex": "53000,10000,20050,16052"},
+  "data/MC": {"fmt": "%N%n%O%n%A%nMC-%Z %C %X", "id": "data/MC", "key": "MC", "name": "MONACO", "postprefix": "MC-", "zip": "980\\d{2}", "zipex": "98000,98020,98011,98001"},
+  "data/MD": {"fmt": "%N%n%O%n%A%nMD-%Z %C", "id": "data/MD", "key": "MD", "name": "Rep. MOLDOVA", "postprefix": "MD-", "zip": "\\d{4}", "zipex": "2012,2019"},
+  "data/ME": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/ME", "key": "ME", "name": "MONTENEGRO", "zip": "8\\d{4}", "zipex": "81257,81258,81217,84314,85366"},
+  "data/MF": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/MF", "key": "MF", "name": "SAINT MARTIN", "posturl": "http://www.laposte.fr/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal", "require": "ACZ", "upper": "ACX", "zip": "9[78][01]\\d{2}", "zipex": "97100"},
+  "data/MG": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/MG", "key": "MG", "name": "MADAGASCAR", "zip": "\\d{3}", "zipex": "501,101"},
+  "data/MH": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/MH", "key": "MH", "name": "MARSHALL ISLANDS", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACSZ", "state_name_type": "state", "upper": "ACNOS", "zip": "(969[67]\\d)(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "96960,96970"},
+  "data/MK": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/MK", "key": "MK", "name": "MACEDONIA", "zip": "\\d{4}", "zipex": "1314,1321,1443,1062"},
+  "data/ML": {"id": "data/ML", "key": "ML", "name": "MALI"},
+  "data/MM": {"fmt": "%N%n%O%n%A%n%C, %Z", "id": "data/MM", "key": "MM", "name": "MYANMAR", "zip": "\\d{5}", "zipex": "11181"},
+  "data/MN": {"fmt": "%N%n%O%n%A%n%C%n%S %Z", "id": "data/MN", "key": "MN", "name": "MONGOLIA", "posturl": "http://www.zipcode.mn/", "zip": "\\d{5}", "zipex": "65030,65270"},
+  "data/MO": {"fmt": "%A%n%O%n%N", "id": "data/MO", "key": "MO", "lfmt": "%N%n%O%n%A", "name": "MACAO", "require": "A"},
+  "data/MP": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/MP", "key": "MP", "name": "NORTHERN MARIANA ISLANDS", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACSZ", "state_name_type": "state", "upper": "ACNOS", "zip": "(9695[012])(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "96950,96951,96952"},
+  "data/MQ": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/MQ", "key": "MQ", "name": "MARTINIQUE", "posturl": "http://www.laposte.fr/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal", "require": "ACZ", "upper": "ACX", "zip": "9[78]2\\d{2}", "zipex": "97220"},
+  "data/MR": {"id": "data/MR", "key": "MR", "name": "MAURITANIA", "upper": "AC"},
+  "data/MS": {"id": "data/MS", "key": "MS", "name": "MONTSERRAT"},
+  "data/MT": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/MT", "key": "MT", "name": "MALTA", "posturl": "http://postcodes.maltapost.com/", "upper": "CZ", "zip": "[A-Z]{3} ?\\d{2,4}", "zipex": "NXR 01,ZTN 05,GPO 01,BZN 1130,SPB 6031,VCT 1753"},
+  "data/MU": {"fmt": "%N%n%O%n%A%n%Z%n%C", "id": "data/MU", "key": "MU", "name": "MAURITIUS", "upper": "CZ", "zip": "\\d{3}(?:\\d{2}|[A-Z]{2}\\d{3})", "zipex": "42602"},
+  "data/MV": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/MV", "key": "MV", "name": "MALDIVES", "posturl": "http://www.maldivespost.com/?lid=10", "zip": "\\d{5}", "zipex": "20026"},
+  "data/MW": {"fmt": "%N%n%O%n%A%n%C %X", "id": "data/MW", "key": "MW", "name": "MALAWI"},
+  "data/MX": {"fmt": "%N%n%O%n%A%n%D%n%Z %C, %S", "id": "data/MX", "key": "MX", "lang": "es", "languages": "es", "name": "MEXICO", "posturl": "http://www.correosdemexico.gob.mx/ServiciosLinea/Paginas/ccpostales.aspx", "require": "ACZ", "state_name_type": "state", "sub_isoids": "AGU~BCN~BCS~CAM~CHP~CHH~CMX~COA~COL~DUR~MEX~GUA~GRO~HID~JAL~MIC~MOR~NAY~NLE~OAX~PUE~QUE~ROO~SLP~SIN~SON~TAB~TAM~TLA~VER~YUC~ZAC", "sub_keys": "Ags.~B.C.~B.C.S.~Camp.~Chis.~Chih.~CDMX~Coah.~Col.~Dgo.~Méx.~Gto.~Gro.~Hgo.~Jal.~Mich.~Mor.~Nay.~N.L.~Oax.~Pue.~Qro.~Q.R.~S.L.P.~Sin.~Son.~Tab.~Tamps.~Tlax.~Ver.~Yuc.~Zac.", "sub_names": "Aguascalientes~Baja California~Baja California Sur~Campeche~Chiapas~Chihuahua~Ciudad de México~Coahuila de Zaragoza~Colima~Durango~Estado de México~Guanajuato~Guerrero~Hidalgo~Jalisco~Michoacán~Morelos~Nayarit~Nuevo León~Oaxaca~Puebla~Querétaro~Quintana Roo~San Luis Potosí~Sinaloa~Sonora~Tabasco~Tamaulipas~Tlaxcala~Veracruz~Yucatán~Zacatecas", "sub_zipexs": "20000,20999~21000,22999~23000,23999~24000,24999~29000,30999~31000,33999~00000,16999~25000,27999~28000,28999~34000,35999~50000,57999~36000,38999~39000,41999~42000,43999~44000,49999~58000,61999~62000,62999~63000,63999~64000,67999~68000,71999~72000,75999~76000,76999~77000,77999~78000,79999~80000,82999~83000,85999~86000,86999~87000,89999~90000,90999~91000,96999~97000,97999~98000,99999", "sub_zips": "20~2[12]~23~24~29|30~3[1-3]~0|1[0-6]~2[5-7]~28~3[45]~5[0-7]~3[6-8]~39|4[01]~4[23]~4[4-9]~5[89]|6[01]~62~63~6[4-7]~6[89]|7[01]~7[2-5]~76~77~7[89]~8[0-2]~8[3-5]~86~8[7-9]~90~9[1-6]~97~9[89]", "sublocality_name_type": "neighborhood", "upper": "CSZ", "zip": "\\d{5}", "zipex": "02860,77520,06082"},
+  "data/MY": {"fmt": "%N%n%O%n%A%n%D%n%Z %C%n%S", "id": "data/MY", "key": "MY", "lang": "ms", "languages": "ms", "name": "MALAYSIA", "posturl": "http://www.pos.com.my", "require": "ACZ", "state_name_type": "state", "sub_isoids": "01~02~03~14~15~04~05~06~08~09~07~16~12~13~10~11", "sub_keys": "Johor~Kedah~Kelantan~Kuala Lumpur~Labuan~Melaka~Negeri Sembilan~Pahang~Perak~Perlis~Pulau Pinang~Putrajaya~Sabah~Sarawak~Selangor~Terengganu", "sub_zipexs": "79000,86999~05000,09999,34950~15000,18599~50000,60000~87000,87999~75000,78399~70000,73599~25000,28999,39000,49000,69000~30000,36899,39000~01000,02799~10000,14999~62000,62999~88000,91999~93000,98999~40000,48999,63000,68199~20000,24999", "sub_zips": "79|8[0-6]~0[5-9]|34950~1[5-9]~5|60~87~7[5-8]~7[0-4]~2[5-8]|[346]9~3[0-6]|39000~0[12]~1[0-4]~62~8[89]|9[01]~9[3-8]~4[0-8]|6[3-8]~2[0-4]", "sublocality_name_type": "village_township", "upper": "CS", "zip": "\\d{5}", "zipex": "43000,50754,88990,50670"},
+  "data/MZ": {"fmt": "%N%n%O%n%A%n%Z %C%S", "id": "data/MZ", "key": "MZ", "lang": "pt", "languages": "pt", "name": "MOZAMBIQUE", "sub_isoids": "P~MPM~G~I~B~L~N~A~S~T~Q", "sub_keys": "Cabo Delgado~Cidade de Maputo~Gaza~Inhambane~Manica~Maputo~Nampula~Niassa~Sofala~Tete~Zambezia", "zip": "\\d{4}", "zipex": "1102,1119,3212"},
+  "data/NA": {"id": "data/NA", "key": "NA", "name": "NAMIBIA"},
+  "data/NC": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/NC", "key": "NC", "name": "NEW CALEDONIA", "posturl": "http://poste.opt.nc/index.php?option=com_content&view=article&id=80&Itemid=131", "require": "ACZ", "upper": "ACX", "zip": "988\\d{2}", "zipex": "98814,98800,98810"},
+  "data/NE": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/NE", "key": "NE", "name": "NIGER", "zip": "\\d{4}", "zipex": "8001"},
+  "data/NF": {"fmt": "%O%n%N%n%A%n%C %S %Z", "id": "data/NF", "key": "NF", "name": "NORFOLK ISLAND", "upper": "CS", "zip": "2899", "zipex": "2899"},
+  "data/NG": {"fmt": "%N%n%O%n%A%n%D%n%C %Z%n%S", "id": "data/NG", "key": "NG", "lang": "en", "languages": "en", "name": "NIGERIA", "posturl": "http://www.nigeriapostcodes.com/", "state_name_type": "state", "sub_isoids": "AB~AD~AK~AN~BA~BY~BE~BO~CR~DE~EB~ED~EK~EN~FC~GO~IM~JI~KD~KN~KT~KE~KO~KW~LA~NA~NI~OG~ON~OS~OY~PL~RI~SO~TA~YO~ZA", "sub_keys": "Abia~Adamawa~Akwa Ibom~Anambra~Bauchi~Bayelsa~Benue~Borno~Cross River~Delta~Ebonyi~Edo~Ekiti~Enugu~Federal Capital Territory~Gombe~Imo~Jigawa~Kaduna~Kano~Katsina~Kebbi~Kogi~Kwara~Lagos~Nasarawa~Niger~Ogun State~Ondo~Osun~Oyo~Plateau~Rivers~Sokoto~Taraba~Yobe~Zamfara", "upper": "CS", "zip": "\\d{6}", "zipex": "930283,300001,931104"},
+  "data/NI": {"fmt": "%N%n%O%n%A%n%Z%n%C, %S", "id": "data/NI", "key": "NI", "lang": "es", "languages": "es", "name": "NICARAGUA", "posturl": "http://www.correos.gob.ni/index.php/codigo-postal-2", "state_name_type": "department", "sub_isoids": "BO~CA~CI~CO~ES~GR~JI~LE~MD~MN~MS~MT~NS~AN~AS~SJ~RI", "sub_keys": "Boaco~Carazo~Chinandega~Chontales~Esteli~Granada~Jinotega~Leon~Madriz~Managua~Masaya~Matagalpa~Nueva Segovia~Raan~Raas~Rio San Juan~Rivas", "sub_zips": "5[12]~4[56]~2[5-7]~5[56]~3[12]~4[34]~6[56]~2[12]~3[45]~1[0-6]~4[12]~6[1-3]~3[7-9]~7[12]~8[1-3]~9[12]~4[78]", "upper": "CS", "zip": "\\d{5}", "zipex": "52000"},
+  "data/NL": {"fmt": "%O%n%N%n%A%n%Z %C", "id": "data/NL", "key": "NL", "name": "NETHERLANDS", "posturl": "http://www.postnl.nl/voorthuis/", "require": "ACZ", "zip": "\\d{4} ?[A-Z]{2}", "zipex": "1234 AB,2490 AA"},
+  "data/NO": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/NO", "key": "NO", "locality_name_type": "post_town", "name": "NORWAY", "posturl": "http://adressesok.posten.no/nb/postal_codes/search", "require": "ACZ", "zip": "\\d{4}", "zipex": "0025,0107,6631"},
+  "data/NP": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/NP", "key": "NP", "name": "NEPAL", "posturl": "http://www.gpo.gov.np/Home/Postalcode", "zip": "\\d{5}", "zipex": "44601"},
+  "data/NR": {"fmt": "%N%n%O%n%A%n%S", "id": "data/NR", "key": "NR", "lang": "en", "languages": "en", "name": "NAURU CENTRAL PACIFIC", "require": "AS", "state_name_type": "district", "sub_isoids": "01~02~03~04~05~06~07~08~09~10~11~12~13~14", "sub_keys": "Aiwo District~Anabar District~Anetan District~Anibare District~Baiti District~Boe District~Buada District~Denigomodu District~Ewa District~Ijuw District~Meneng District~Nibok District~Uaboe District~Yaren District"},
+  "data/NU": {"id": "data/NU", "key": "NU", "name": "NIUE"},
+  "data/NZ": {"fmt": "%N%n%O%n%A%n%D%n%C %Z", "id": "data/NZ", "key": "NZ", "name": "NEW ZEALAND", "posturl": "http://www.nzpost.co.nz/Cultures/en-NZ/OnlineTools/PostCodeFinder/", "require": "ACZ", "zip": "\\d{4}", "zipex": "6001,6015,6332,8252,1030"},
+  "data/OM": {"fmt": "%N%n%O%n%A%n%Z%n%C", "id": "data/OM", "key": "OM", "name": "OMAN", "zip": "(?:PC )?\\d{3}", "zipex": "133,112,111"},
+  "data/PA": {"fmt": "%N%n%O%n%A%n%C%n%S", "id": "data/PA", "key": "PA", "name": "PANAMA (REP.)", "upper": "CS"},
+  "data/PE": {"fmt": "%N%n%O%n%A%n%C %Z%n%S", "id": "data/PE", "key": "PE", "lang": "es", "languages": "es", "locality_name_type": "district", "name": "PERU", "posturl": "http://www.serpost.com.pe/cpostal/codigo", "sub_isoids": "AMA~ANC~APU~ARE~AYA~CAJ~CAL~CUS~LIM~HUV~HUC~ICA~JUN~LAL~LAM~LOR~MDD~MOQ~LMA~PAS~PIU~PUN~SAM~TAC~TUM~UCA", "sub_keys": "Amazonas~Áncash~Apurímac~Arequipa~Ayacucho~Cajamarca~Callao~Cuzco~Gobierno Regional de Lima~Huancavelica~Huánuco~Ica~Junín~La Libertad~Lambayeque~Loreto~Madre de Dios~Moquegua~Municipalidad Metropolitana de Lima~Pasco~Piura~Puno~San Martín~Tacna~Tumbes~Ucayali", "zip": "(?:LIMA \\d{1,2}|CALLAO 0?\\d)|[0-2]\\d{4}", "zipex": "LIMA 23,LIMA 42,CALLAO 2,02001"},
+  "data/PF": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/PF", "key": "PF", "name": "FRENCH POLYNESIA", "require": "ACSZ", "state_name_type": "island", "upper": "CS", "zip": "987\\d{2}", "zipex": "98709"},
+  "data/PG": {"fmt": "%N%n%O%n%A%n%C %Z %S", "id": "data/PG", "key": "PG", "name": "PAPUA NEW GUINEA", "require": "ACS", "zip": "\\d{3}", "zipex": "111"},
+  "data/PH": {"fmt": "%N%n%O%n%A%n%D, %C%n%Z %S", "id": "data/PH", "key": "PH", "lang": "en", "languages": "en", "name": "PHILIPPINES", "posturl": "http://www.philpost.gov.ph/", "sub_isoids": "ABR~AGN~AGS~AKL~ALB~ANT~APA~AUR~BAS~BAN~BTN~BTG~BEN~BIL~BOH~BUK~BUL~CAG~CAN~CAS~CAM~CAP~CAT~CAV~CEB~COM~NCO~DAV~DAS~DVO~DAO~DIN~EAS~GUI~IFU~ILN~ILS~ILI~ISA~KAL~LUN~LAG~LAN~LAS~LEY~MAG~MAD~MAS~00~MDC~MDR~MSC~MSR~MOU~NEC~NER~NSA~NUE~NUV~PLW~PAM~PAN~QUE~QUI~RIZ~ROM~WSA~SAR~SIG~SOR~SCO~SLE~SUK~SLU~SUN~SUR~TAR~TAW~ZMB~ZAN~ZAS~ZSI", "sub_keys": "Abra~Agusan del Norte~Agusan del Sur~Aklan~Albay~Antique~Apayao~Aurora~Basilan~Bataan~Batanes~Batangas~Benguet~Biliran~Bohol~Bukidnon~Bulacan~Cagayan~Camarines Norte~Camarines Sur~Camiguin~Capiz~Catanduanes~Cavite~Cebu~Compostela Valley~Cotabato~Davao del Norte~Davao del Sur~Davao Occidental~Davao Oriental~Dinagat Islands~Eastern Samar~Guimaras~Ifugao~Ilocos Norte~Ilocos Sur~Iloilo~Isabela~Kalinga~La Union~Laguna~Lanao del Norte~Lanao del Sur~Leyte~Maguindanao~Marinduque~Masbate~Metro Manila~Mindoro Occidental~Mindoro Oriental~Misamis Occidental~Misamis Oriental~Mountain Province~Negros Occidental~Negros Oriental~Northern Samar~Nueva Ecija~Nueva Vizcaya~Palawan~Pampanga~Pangasinan~Quezon Province~Quirino~Rizal~Romblon~Samar~Sarangani~Siquijor~Sorsogon~South Cotabato~Southern Leyte~Sultan Kudarat~Sulu~Surigao del Norte~Surigao del Sur~Tarlac~Tawi-Tawi~Zambales~Zamboanga del Norte~Zamboanga del Sur~Zamboanga Sibuguey", "sub_zipexs": "2800,2826~8600,8611~8500,8513~5600,5616~4500,4517~5700,5717~3800,3806,3808~3200,3207~7300,7306~2100,2114~3900,3905~4200,4234~2600,2615~6543,6550~6300,6337~8700,8723~3000,3024~3500,3528~4600,4612~4400,4436~9100,9104~5800,5816~4800,4810~4100,4126~6000,6053~8800,8810~9400,9417~8100,8120~8000,8010~8015,8013~8200,8210~8426,8412~6800,6822~5044,5046~3600,3610~2900,2922~2700,2733~5000,5043~3300,3336~3807,3809,3814~2500,2520~4000,4033~9200,9223~9300,9321,9700,9716~6500,6542~9600,9619~4900,4905~5400,5421~~5100,5111~5200,5214~7200,7215~9000,9025~2616,2625~6100,6132~6200,6224~6400,6423~3100,3133~3700,3714~5300,5322~2000,2022~2400,2447~4300,4342~3400,3405~1850,1990~5500,5516~6700,6725~8015~6225,6230~4700,4715~9500,9513~6600,6613~9800,9811~7400,7416~8400,8425~8300,8319~2300,2318~7500,7509~2200,2213~7100,7124~7000,7043~7000,7043", "sub_zips": "28[0-2]~86[01]~85[01]~56[01]~45[01]~57[01]~380[0-68]~320~730~21[01]~390~42[0-3]~26(0|1[0-5])~65(4[3-9]|5)~63[0-3]~87[0-2]~30[0-2]~35[0-2]~46[01]~44[0-3]~910~58[01]~48[01]~41[0-2]~60[0-5]~88[01]~94[01]~81[0-2]~80[01]~801[1-5]~82[01]~84[12]~68[0-2]~504[4-6]~36[01]~29[0-2]~27[0-3]~50([0-3]|4[0-3])~33[0-3]~38(0[79]|1[0-4])~25[0-2]~40[0-3]~92[0-2]~9(3[0-2]|7[01])~65([0-3]|4[0-2])~96[01]~490~54[0-2]~~51[01]~52[01]~72[01]~90[0-2]~26(1[6-9]|2[0-5])~61[0-3]~62[0-2]~64[0-2]~31[0-3]~37[01]~53[0-2]~20[0-2]~24[0-4]~43[0-4]~340~1[89]~55[01]~67[0-2]~8015~62(2[5-9]|30)~47[01]~95[01]~66[10]~98[01]~74[01]~84[0-2]~83[01]~23[01]~750~22[01]~71[0-2]~70[0-4]~70[0-4]", "zip": "\\d{4}", "zipex": "1008,1050,1135,1207,2000,1000"},
+  "data/PK": {"fmt": "%N%n%O%n%A%n%C-%Z", "id": "data/PK", "key": "PK", "name": "PAKISTAN", "posturl": "http://www.pakpost.gov.pk/postcode.php", "zip": "\\d{5}", "zipex": "44000"},
+  "data/PL": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/PL", "key": "PL", "name": "POLAND", "posturl": "http://kody.poczta-polska.pl/", "require": "ACZ", "zip": "\\d{2}-\\d{3}", "zipex": "00-950,05-470,48-300,32-015,00-940"},
+  "data/PM": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/PM", "key": "PM", "name": "ST. PIERRE AND MIQUELON", "require": "ACZ", "upper": "ACX", "zip": "9[78]5\\d{2}", "zipex": "97500"},
+  "data/PN": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/PN", "key": "PN", "name": "PITCAIRN", "require": "ACZ", "upper": "CZ", "zip": "PCRN 1ZZ", "zipex": "PCRN 1ZZ"},
+  "data/PR": {"fmt": "%N%n%O%n%A%n%C PR %Z", "id": "data/PR", "key": "PR", "name": "PUERTO RICO", "postprefix": "PR ", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACZ", "upper": "ACNO", "zip": "(00[679]\\d{2})(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "00930"},
+  "data/PT": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/PT", "key": "PT", "name": "PORTUGAL", "posturl": "http://www.ctt.pt/feapl_2/app/open/tools.jspx?tool=1", "require": "ACZ", "zip": "\\d{4}-\\d{3}", "zipex": "2725-079,1250-096,1201-950,2860-571,1208-148"},
+  "data/PW": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/PW", "key": "PW", "name": "PALAU", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACSZ", "state_name_type": "state", "upper": "ACNOS", "zip": "(969(?:39|40))(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "96940"},
+  "data/PY": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/PY", "key": "PY", "name": "PARAGUAY", "zip": "\\d{4}", "zipex": "1536,1538,1209"},
+  "data/QA": {"id": "data/QA", "key": "QA", "name": "QATAR", "upper": "AC"},
+  "data/RE": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/RE", "key": "RE", "name": "REUNION", "posturl": "http://www.laposte.fr/Particulier/Utiliser-nos-outils-pratiques/Outils-et-documents/Trouvez-un-code-postal", "require": "ACZ", "upper": "ACX", "zip": "9[78]4\\d{2}", "zipex": "97400"},
+  "data/RO": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/RO", "key": "RO", "name": "ROMANIA", "posturl": "http://www.posta-romana.ro/zip_codes", "upper": "AC", "zip": "\\d{6}", "zipex": "060274,061357,200716"},
+  "data/RS": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/RS", "key": "RS", "name": "REPUBLIC OF SERBIA", "posturl": "http://www.posta.rs/struktura/lat/aplikacije/pronadji/nadji-postu.asp", "zip": "\\d{5,6}", "zipex": "106314"},
+  "data/RU": {"fmt": "%N%n%O%n%A%n%C%n%S%n%Z", "id": "data/RU", "key": "RU", "lang": "ru", "languages": "ru", "lfmt": "%N%n%O%n%A%n%C%n%S%n%Z", "name": "RUSSIAN FEDERATION", "posturl": "http://info.russianpost.ru/servlet/department", "require": "ACSZ", "state_name_type": "oblast", "sub_isoids": "ALT~AMU~ARK~AST~BEL~BRY~VLA~VGG~VLG~VOR~YEV~ZAB~IVA~IRK~KB~KGD~KLU~KAM~KC~KEM~KIR~KOS~KDA~KYA~KGN~KRS~LEN~LIP~MAG~MOW~MOS~MUR~NEN~NIZ~NGR~NVS~OMS~ORE~ORL~PNZ~PER~PRI~PSK~AD~AL~BA~BU~DA~IN~KL~KR~KO~~ME~MO~SA~SE~TA~TY~UD~KK~ROS~RYA~SAM~SPE~SAR~SAK~SVE~~SMO~STA~TAM~TVE~TOM~TUL~TYU~ULY~KHA~KHM~CHE~CE~CU~CHU~YAN~YAR", "sub_keys": "Алтайский край~Амурская область~Архангельская область~Астраханская область~Белгородская область~Брянская область~Владимирская область~Волгоградская область~Вологодская область~Воронежская область~Еврейская автономная область~Забайкальский край~Ивановская область~Иркутская область~Кабардино-Балкарская Республика~Калининградская область~Калужская область~Камчатский край~Карачаево-Черкесская Республика~Кемеровская область~Кировская область~Костромская область~Краснодарский край~Красноярский край~Курганская область~Курская область~Ленинградская область~Липецкая область~Магаданская область~Москва~Московская область~Мурманская область~Ненецкий автономный округ~Нижегородская область~Новгородская область~Новосибирская область~Омская область~Оренбургская область~Орловская область~Пензенская область~Пермский край~Приморский край~Псковская область~Республика Адыгея~Республика Алтай~Республика Башкортостан~Республика Бурятия~Республика Дагестан~Республика Ингушетия~Республика Калмыкия~Республика Карелия~Республика Коми~Автономна Республіка Крим~Республика Марий Эл~Республика Мордовия~Республика Саха (Якутия)~Республика Северная Осетия-Алания~Республика Татарстан~Республика Тыва~Республика Удмуртия~Республика Хакасия~Ростовская область~Рязанская область~Самарская область~Санкт-Петербург~Саратовская область~Сахалинская область~Свердловская область~Севастополь~Смоленская область~Ставропольский край~Тамбовская область~Тверская область~Томская область~Тульская область~Тюменская область~Ульяновская область~Хабаровский край~Ханты-Мансийский автономный округ~Челябинская область~Чеченская Республика~Чувашская Республика~Чукотский автономный округ~Ямало-Ненецкий автономный округ~Ярославская область", "sub_lnames": "Altayskiy kray~Amurskaya oblast'~Arkhangelskaya oblast'~Astrakhanskaya oblast'~Belgorodskaya oblast'~Bryanskaya oblast'~Vladimirskaya oblast'~Volgogradskaya oblast'~Vologodskaya oblast'~Voronezhskaya oblast'~Evreyskaya avtonomnaya oblast'~Zabaykalskiy kray~Ivanovskaya oblast'~Irkutskaya oblast'~Kabardino-Balkarskaya Republits~Kaliningradskaya oblast'~Kaluzhskaya oblast'~Kamchatskiy kray~Karachaevo-Cherkesskaya Republits~Kemerovskaya oblast'~Kirovskaya oblast'~Kostromskaya oblast'~Krasnodarskiy kray~Krasnoyarskiy kray~Kurganskaya oblast'~Kurskaya oblast'~Leningradskaya oblast'~Lipetskaya oblast'~Magadanskaya oblast'~Moskva~Moskovskaya oblast'~Murmanskaya oblast'~Nenetskiy~Nizhegorodskaya oblast'~Novgorodskaya oblast'~Novosibirskaya oblast'~Omskaya oblast'~Orenburgskaya oblast'~Orlovskaya oblast'~Penzenskaya oblast'~Permskiy kray~Primorskiy kray~Pskovskaya oblast'~Respublika Adygeya~Altay Republits~Bashkortostan Republits~Buryatiya Republits~Dagestan Republits~Ingushetiya Republits~Respublika Kalmykiya~Kareliya Republits~Komi Republits~Respublika Krym~Respublika Mariy El~Respublika Mordoviya~Sakha (Yakutiya) Republits~Respublika Severnaya Osetiya-Alaniya~Respublika Tatarstan~Tyva Republits~Respublika Udmurtiya~Khakasiya Republits~Rostovskaya oblast'~Ryazanskaya oblast'~Samarskaya oblast'~Sankt-Peterburg~Saratovskaya oblast'~Sakhalinskaya oblast'~Sverdlovskaya oblast'~Sevastopol'~Smolenskaya oblast'~Stavropolskiy kray~Tambovskaya oblast'~Tverskaya oblast'~Tomskaya oblast'~Tulskaya oblast'~Tyumenskaya oblast'~Ulyanovskaya oblast'~Khabarovskiy kray~Khanty-Mansiyskiy avtonomnyy okrug~Chelyabinskaya oblast'~Chechenskaya Republits~Chuvashia~Chukotskiy~Yamalo-Nenetskiy~Yaroslavskaya oblast'", "sub_names": "Алтайский край~Амурская область~Архангельская область~Астраханская область~Белгородская область~Брянская область~Владимирская область~Волгоградская область~Вологодская область~Воронежская область~Еврейская автономная область~Забайкальский край~Ивановская область~Иркутская область~Кабардино-Балкарская Республика~Калининградская область~Калужская область~Камчатский край~Карачаево-Черкесская Республика~Кемеровская область~Кировская область~Костромская область~Краснодарский край~Красноярский край~Курганская область~Курская область~Ленинградская область~Липецкая область~Магаданская область~Москва~Московская область~Мурманская область~Ненецкий автономный округ~Нижегородская область~Новгородская область~Новосибирская область~Омская область~Оренбургская область~Орловская область~Пензенская область~Пермский край~Приморский край~Псковская область~Республика Адыгея~Республика Алтай~Республика Башкортостан~Республика Бурятия~Республика Дагестан~Республика Ингушетия~Республика Калмыкия~Республика Карелия~Республика Коми~Республика Крым~Республика Марий Эл~Республика Мордовия~Республика Саха (Якутия)~Республика Северная Осетия-Алания~Республика Татарстан~Республика Тыва~Республика Удмуртия~Республика Хакасия~Ростовская область~Рязанская область~Самарская область~Санкт-Петербург~Саратовская область~Сахалинская область~Свердловская область~Севастополь~Смоленская область~Ставропольский край~Тамбовская область~Тверская область~Томская область~Тульская область~Тюменская область~Ульяновская область~Хабаровский край~Ханты-Мансийский автономный округ~Челябинская область~Чеченская Республика~Чувашская Республика~Чукотский автономный округ~Ямало-Ненецкий автономный округ~Ярославская область", "sub_zips": "65[6-9]~67[56]~16[3-5]~41[4-6]~30[89]~24[1-3]~60[0-2]~40[0-4]~16[0-2]~39[4-7]~679~6(?:7[2-4]|87)~15[3-5]~66[4-9]~36[01]~23[6-8]~24[89]~68[348]~369~65[0-4]~61[0-3]~15[67]~35[0-4]~6(?:6[0-3]|4[78])~64[01]~30[5-7]~18[78]~39[89]~68[56]~1(?:0[1-9]|1|2|3[0-5]|4[0-4])~14[0-4]~18[34]~166~60[3-7]~17[3-5]~63[0-3]~64[4-6]~46[0-2]~30[23]~44[0-2]~61[4-9]~69[0-2]~18[0-2]~385~649~45[0-3]~67[01]~36[78]~386~35[89]~18[56]~16[7-9]~29[5-8]~42[45]~43[01]~67[78]~36[23]~42[0-3]~66[78]~42[67]~655~34[4-7]~39[01]~44[3-6]~19~41[0-3]~69[34]~62[0-4]~299~21[4-6]~35[5-7]~39[23]~17[0-2]~63[4-6]~30[01]~62[5-7]~43[23]~68[0-2]~628~45[4-7]~36[4-6]~42[89]~689~629~15[0-2]", "upper": "AC", "zip": "\\d{6}", "zipex": "247112,103375,188300"},
+  "data/RW": {"id": "data/RW", "key": "RW", "name": "RWANDA", "upper": "AC"},
+  "data/SA": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/SA", "key": "SA", "name": "SAUDI ARABIA", "zip": "\\d{5}", "zipex": "11564,11187,11142"},
+  "data/SB": {"id": "data/SB", "key": "SB", "name": "SOLOMON ISLANDS"},
+  "data/SC": {"fmt": "%N%n%O%n%A%n%C%n%S", "id": "data/SC", "key": "SC", "name": "SEYCHELLES", "state_name_type": "island", "upper": "S"},
+  "data/SD": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/SD", "key": "SD", "locality_name_type": "district", "name": "SUDAN", "zip": "\\d{5}", "zipex": "11042,11113"},
+  "data/SE": {"fmt": "%O%n%N%n%A%nSE-%Z %C", "id": "data/SE", "key": "SE", "locality_name_type": "post_town", "name": "SWEDEN", "postprefix": "SE-", "posturl": "http://www.posten.se/sv/Kundservice/Sidor/Sok-postnummer-resultat.aspx", "require": "ACZ", "zip": "\\d{3} ?\\d{2}", "zipex": "11455,12345,10500"},
+  "data/SG": {"fmt": "%N%n%O%n%A%nSINGAPORE %Z", "id": "data/SG", "key": "SG", "name": "REP. OF SINGAPORE", "posturl": "https://www.singpost.com/find-postal-code", "require": "AZ", "zip": "\\d{6}", "zipex": "546080,308125,408600"},
+  "data/SH": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/SH", "key": "SH", "name": "SAINT HELENA", "require": "ACZ", "upper": "CZ", "zip": "(?:ASCN|STHL) 1ZZ", "zipex": "STHL 1ZZ"},
+  "data/SI": {"fmt": "%N%n%O%n%A%nSI-%Z %C", "id": "data/SI", "key": "SI", "name": "SLOVENIA", "postprefix": "SI-", "zip": "\\d{4}", "zipex": "4000,1001,2500"},
+  "data/SK": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/SK", "key": "SK", "name": "SLOVAKIA", "posturl": "http://psc.posta.sk", "require": "ACZ", "zip": "\\d{3} ?\\d{2}", "zipex": "010 01,023 14,972 48,921 01,975 99"},
+  "data/SL": {"id": "data/SL", "key": "SL", "name": "SIERRA LEONE"},
+  "data/SM": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/SM", "key": "SM", "name": "SAN MARINO", "posturl": "http://www.poste.it/online/cercacap/", "require": "AZ", "zip": "4789\\d", "zipex": "47890,47891,47895,47899"},
+  "data/SN": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/SN", "key": "SN", "name": "SENEGAL", "zip": "\\d{5}", "zipex": "12500,46024,16556,10000"},
+  "data/SO": {"fmt": "%N%n%O%n%A%n%C, %S %Z", "id": "data/SO", "key": "SO", "lang": "so", "languages": "so", "name": "SOMALIA", "require": "ACS", "sub_isoids": "AW~BK~BN~BR~BY~GA~GE~HI~JD~JH~MU~NU~SA~SD~SH~SO~TO~WO", "sub_keys": "AD~BK~BN~BR~BY~GG~GD~HR~JD~JH~MD~NG~SG~SD~SH~SL~TG~WG", "sub_names": "Awdal~Bakool~Banaadir~Bari~Bay~Galguduud~Gedo~Hiiraan~Jubbada Dhexe~Jubbada Hoose~Mudug~Nugaal~Sanaag~Shabeellaha Dhexe~Shabeellaha Hoose~Sool~Togdheer~Woqooyi Galbeed", "upper": "ACS", "zip": "[A-Z]{2} ?\\d{5}", "zipex": "JH 09010,AD 11010"},
+  "data/SR": {"fmt": "%N%n%O%n%A%n%C%n%S", "id": "data/SR", "key": "SR", "lang": "nl", "languages": "nl", "name": "SURINAME", "sub_isoids": "BR~CM~CR~MA~NI~PR~PM~SA~SI~WA", "sub_keys": "Brokopondo~Commewijne~Coronie~Marowijne~Nickerie~Para~Paramaribo~Saramacca~Sipaliwini~Wanica", "upper": "AS"},
+  "data/SS": {"id": "data/SS", "key": "SS", "name": "SOUTH SUDAN"},
+  "data/ST": {"id": "data/ST", "key": "ST", "name": "SAO TOME AND PRINCIPE"},
+  "data/SV": {"fmt": "%N%n%O%n%A%n%Z-%C%n%S", "id": "data/SV", "key": "SV", "lang": "es", "languages": "es", "name": "EL SALVADOR", "require": "ACS", "sub_isoids": "AH~CA~CH~CU~LI~PA~UN~MO~SM~SS~SV~SA~SO~US", "sub_keys": "Ahuachapan~Cabanas~Calatenango~Cuscatlan~La Libertad~La Paz~La Union~Morazan~San Miguel~San Salvador~San Vicente~Santa Ana~Sonsonate~Usulutan", "sub_names": "Ahuachapán~Cabañas~Chalatenango~Cuscatlán~La Libertad~La Paz~La Unión~Morazán~San Miguel~San Salvador~San Vicente~Santa Ana~Sonsonate~Usulután", "sub_zipexs": "CP 2101~CP 1201~CP 1301~CP 1401~CP 1501~CP 1601~CP 3101~CP 3201~CP 3301~CP 1101~CP 1701~CP 2201~CP 2301~CP 3401", "sub_zips": "CP 21~CP 12~CP 13~CP 14~CP 15~CP 16~CP 31~CP 32~CP 33~CP 11~CP 17~CP 22~CP 23~CP 34", "upper": "CSZ", "zip": "CP [1-3][1-7][0-2]\\d", "zipex": "CP 1101"},
+  "data/SX": {"id": "data/SX", "key": "SX", "name": "SINT MAARTEN"},
+  "data/SY": {"id": "data/SY", "key": "SY", "locality_name_type": "district", "name": "SYRIA"},
+  "data/SZ": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/SZ", "key": "SZ", "name": "SWAZILAND", "posturl": "http://www.sptc.co.sz/swazipost/codes/index.php", "upper": "ACZ", "zip": "[HLMS]\\d{3}", "zipex": "H100"},
+  "data/TC": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/TC", "key": "TC", "name": "TURKS AND CAICOS ISLANDS", "require": "ACZ", "upper": "CZ", "zip": "TKCA 1ZZ", "zipex": "TKCA 1ZZ"},
+  "data/TD": {"id": "data/TD", "key": "TD", "name": "CHAD"},
+  "data/TF": {"id": "data/TF", "key": "TF", "name": "FRENCH SOUTHERN TERRITORIES"},
+  "data/TG": {"id": "data/TG", "key": "TG", "name": "TOGO"},
+  "data/TH": {"fmt": "%N%n%O%n%A%n%D %C%n%S %Z", "id": "data/TH", "key": "TH", "lang": "th", "languages": "th", "lfmt": "%N%n%O%n%A%n%D, %C%n%S %Z", "name": "THAILAND", "sub_isoids": "81~10~71~46~62~40~38~22~24~20~18~36~86~57~50~92~23~63~26~73~48~30~80~60~12~96~55~31~13~77~25~94~14~56~82~93~66~65~76~67~54~83~44~49~58~35~95~45~85~21~70~16~52~51~42~33~47~90~91~11~75~74~27~19~17~64~72~84~32~43~39~15~37~41~53~61~34", "sub_keys": "กระบี่~กรุงเทพมหานคร~กาญจนบุรี~กาฬสินธุ์~กำแพงเพชร~ขอนแก่น~จังหวัด บึงกาฬ~จันทบุรี~ฉะเชิงเทรา~ชลบุรี~ชัยนาท~ชัยภูมิ~ชุมพร~เชียงราย~เชียงใหม่~ตรัง~ตราด~ตาก~นครนายก~นครปฐม~นครพนม~นครราชสีมา~นครศรีธรรมราช~นครสวรรค์~นนทบุรี~นราธิวาส~น่าน~บุรีรัมย์~ปทุมธานี~ประจวบคีรีขันธ์~ปราจีนบุรี~ปัตตานี~พระนครศรีอยุธยา~พะเยา~พังงา~พัทลุง~พิจิตร~พิษณุโลก~เพชรบุรี~เพชรบูรณ์~แพร่~ภูเก็ต~มหาสารคาม~มุกดาหาร~แม่ฮ่องสอน~ยโสธร~ยะลา~ร้อยเอ็ด~ระนอง~ระยอง~ราชบุรี~ลพบุรี~ลำปาง~ลำพูน~เลย~ศรีสะเกษ~สกลนคร~สงขลา~สตูล~สมุทรปราการ~สมุทรสงคราม~สมุทรสาคร~สระแก้ว~สระบุรี~สิงห์บุรี~สุโขทัย~สุพรรณบุรี~สุราษฎร์ธานี~สุรินทร์~หนองคาย~หนองบัวลำภู~อ่างทอง~อำนาจเจริญ~อุดรธานี~อุตรดิตถ์~อุทัยธานี~อุบลราชธานี", "sub_lnames": "Krabi~Bangkok~Kanchanaburi~Kalasin~Kamphaeng Phet~Khon Kaen~Bueng Kan~Chanthaburi~Chachoengsao~Chon Buri~Chai Nat~Chaiyaphum~Chumpon~Chiang Rai~Chiang Mai~Trang~Trat~Tak~Nakhon Nayok~Nakhon Pathom~Nakhon Phanom~Nakhon Ratchasima~Nakhon Si Thammarat~Nakhon Sawan~Nonthaburi~Narathiwat~Nan~Buri Ram~Pathum Thani~Prachuap Khiri Khan~Prachin Buri~Pattani~Phra Nakhon Si Ayutthaya~Phayao~Phang Nga~Phattalung~Phichit~Phitsanulok~Phetchaburi~Phetchabun~Phrae~Phuket~Maha Sarakham~Mukdahan~Mae Hong Son~Yasothon~Yala~Roi Et~Ranong~Rayong~Ratchaburi~Lop Buri~Lampang~Lamphun~Loei~Si Sa Ket~Sakon Nakhon~Songkhla~Satun~Samut Prakan~Samut Songkhram~Samut Sakhon~Sa Kaeo~Saraburi~Sing Buri~Sukhothai~Suphanburi~Surat Thani~Surin~Nong Khai~Nong Bua Lam Phu~Ang Thong~Amnat Charoen~Udon Thani~Uttaradit~Uthai Thani~Ubon Ratchathani", "sub_zips": "81~10~71~46~62~40~~22~24~20~17~36~86~57~50~92~23~63~26~73~48~30~80~60~11~96~55~31~12~77~25~94~13~56~82~93~66~65~76~67~54~83~44~49~58~35~95~45~85~21~70~15~52~51~42~33~47~90~91~10~75~74~27~18~16~64~72~84~32~43~39~14~37~41~53~61~34", "upper": "S", "zip": "\\d{5}", "zipex": "10150,10210"},
+  "data/TJ": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/TJ", "key": "TJ", "name": "TAJIKISTAN", "zip": "\\d{6}", "zipex": "735450,734025"},
+  "data/TK": {"id": "data/TK", "key": "TK", "name": "TOKELAU"},
+  "data/TL": {"id": "data/TL", "key": "TL", "name": "TIMOR-LESTE"},
+  "data/TM": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/TM", "key": "TM", "name": "TURKMENISTAN", "zip": "\\d{6}", "zipex": "744000"},
+  "data/TN": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/TN", "key": "TN", "name": "TUNISIA", "posturl": "http://www.poste.tn/codes.php", "zip": "\\d{4}", "zipex": "1002,8129,3100,1030"},
+  "data/TO": {"id": "data/TO", "key": "TO", "name": "TONGA"},
+  "data/TR": {"fmt": "%N%n%O%n%A%n%Z %C/%S", "id": "data/TR", "key": "TR", "lang": "tr", "languages": "tr", "locality_name_type": "district", "name": "TURKEY", "posturl": "http://postakodu.ptt.gov.tr/", "require": "ACZ", "sub_isoids": "01~02~03~04~68~05~06~07~75~08~09~10~74~72~69~11~12~13~14~15~16~17~18~19~20~21~81~22~23~24~25~26~27~28~29~30~31~76~32~34~35~46~78~70~36~37~38~71~39~40~79~41~42~43~44~45~47~33~48~49~50~51~52~80~53~54~55~56~57~58~63~73~59~60~61~62~64~65~77~66~67", "sub_keys": "Adana~Adıyaman~Afyon~Ağrı~Aksaray~Amasya~Ankara~Antalya~Ardahan~Artvin~Aydın~Balıkesir~Bartın~Batman~Bayburt~Bilecik~Bingöl~Bitlis~Bolu~Burdur~Bursa~Çanakkale~Çankırı~Çorum~Denizli~Diyarbakır~Düzce~Edirne~Elazığ~Erzincan~Erzurum~Eskişehir~Gaziantep~Giresun~Gümüşhane~Hakkari~Hatay~Iğdır~Isparta~İstanbul~İzmir~Kahramanmaraş~Karabük~Karaman~Kars~Kastamonu~Kayseri~Kırıkkale~Kırklareli~Kırşehir~Kilis~Kocaeli~Konya~Kütahya~Malatya~Manisa~Mardin~Mersin~Muğla~Muş~Nevşehir~Niğde~Ordu~Osmaniye~Rize~Sakarya~Samsun~Siirt~Sinop~Sivas~Şanlıurfa~Şırnak~Tekirdağ~Tokat~Trabzon~Tunceli~Uşak~Van~Yalova~Yozgat~Zonguldak", "sub_zips": "01~02~03~04~68~05~06~07~75~08~09~10~74~72~69~11~12~13~14~15~16~17~18~19~20~21~81~22~23~24~25~26~27~28~29~30~31~76~32~34~35~46~78~70~36~37~38~71~39~40~79~41~42~43~44~45~47~33~48~49~50~51~52~80~53~54~55~56~57~58~63~73~59~60~61~62~64~65~77~66~67", "zip": "\\d{5}", "zipex": "01960,06101"},
+  "data/TT": {"id": "data/TT", "key": "TT", "name": "TRINIDAD AND TOBAGO"},
+  "data/TV": {"fmt": "%N%n%O%n%A%n%C%n%S", "id": "data/TV", "key": "TV", "lang": "tyv", "languages": "tyv", "name": "TUVALU", "state_name_type": "island", "sub_isoids": "FUN~NMG~NMA~~NIT~NUI~NKF~NKL~VAI", "sub_keys": "Funafuti~Nanumanga~Nanumea~Niulakita~Niutao~Nui~Nukufetau~Nukulaelae~Vaitupu", "upper": "ACS"},
+  "data/TW": {"fmt": "%Z%n%S%C%n%A%n%O%n%N", "id": "data/TW", "key": "TW", "lang": "zh-Hant", "languages": "zh-Hant", "lfmt": "%N%n%O%n%A%n%C, %S %Z", "name": "TAIWAN", "posturl": "http://www.post.gov.tw/post/internet/f_searchzone/index.jsp?ID=190102", "require": "ACSZ", "state_name_type": "county", "sub_isoids": "TXG~TPE~TTT~TNN~ILA~HUA~~NAN~PIF~MIA~TAO~KHH~KEE~~YUN~NWT~HSZ~HSQ~CYI~CYQ~CHA~PEN", "sub_keys": "台中市~台北市~台東縣~台南市~宜蘭縣~花蓮縣~金門縣~南投縣~屏東縣~苗栗縣~桃園市~高雄市~基隆市~連江縣~雲林縣~新北市~新竹市~新竹縣~嘉義市~嘉義縣~彰化縣~澎湖縣", "sub_lnames": "Taichung City~Taipei City~Taitung County~Tainan City~Yilan County~Hualien County~Kinmen County~Nantou County~Pingtung County~Miaoli County~Taoyuan City~Kaohsiung City~Keelung City~Lienchiang County~Yunlin County~New Taipei City~Hsinchu City~Hsinchu County~Chiayi City~Chiayi County~Changhua County~Penghu County", "sub_mores": "true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true~true", "sub_zipexs": "400,408,411,439~100,119~950,966~700,745~260,272~970,983~890,896~540,558~900,947~350,369~320,338~800,815,817,852~200,206~209,212~630,655~207,208,220,253~~302,315~~602,625~500,530~880,885", "sub_zips": "4[0-3]~1[01]~9[56]~7[0-4]~2[67]~9[78]~89~5[45]~9[0-4]~3[56]~3[23]~8[02-5]|81[1-579]~20[0-6]~209|21[012]~6[3-5]~20[78]|2[2345]~300~30[2-8]|31~600~60[1-9]|6[12]~5[0123]~88", "zip": "\\d{3}(?:\\d{2})?", "zipex": "104,106,10603,40867"},
+  "data/TZ": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/TZ", "key": "TZ", "name": "TANZANIA (UNITED REP.)", "zip": "\\d{4,5}", "zipex": "6090,34413"},
+  "data/UA": {"fmt": "%N%n%O%n%A%n%C%n%S%n%Z", "id": "data/UA", "key": "UA", "lang": "uk", "languages": "uk", "lfmt": "%N%n%O%n%A%n%C%n%S%n%Z", "name": "UKRAINE", "posturl": "http://services.ukrposhta.com/postindex_new/", "require": "ACSZ", "state_name_type": "oblast", "sub_isoids": "43~05~07~12~14~18~21~23~26~30~32~35~09~46~48~51~53~56~40~59~61~63~65~68~71~77~74", "sub_keys": "Автономна Республіка Крим~Вінницька область~Волинська область~Дніпропетровська область~Донецька область~Житомирська область~Закарпатська область~Запорізька область~Івано-Франківська область~місто Київ~Київська область~Кіровоградська область~Луганська область~Львівська область~Миколаївська область~Одеська область~Полтавська область~Рівненська область~місто Севастополь~Сумська область~Тернопільська область~Харківська область~Херсонська область~Хмельницька область~Черкаська область~Чернівецька область~Чернігівська область", "sub_lnames": "Crimea~Vinnyts'ka oblast~Volyns'ka oblast~Dnipropetrovsk oblast~Donetsk oblast~Zhytomyrs'ka oblast~Zakarpats'ka oblast~Zaporiz'ka oblast~Ivano-Frankivs'ka oblast~Kyiv city~Kiev oblast~Kirovohrads'ka oblast~Luhans'ka oblast~Lviv oblast~Mykolaivs'ka oblast~Odessa oblast~Poltavs'ka oblast~Rivnens'ka oblast~Sevastopol' city~Sums'ka oblast~Ternopil's'ka oblast~Kharkiv oblast~Khersons'ka oblast~Khmel'nyts'ka oblast~Cherkas'ka oblast~Chernivets'ka oblast~Chernihivs'ka oblast", "sub_names": "Автономна Республіка Крим~Вінницька область~Волинська область~Дніпропетровська область~Донецька область~Житомирська область~Закарпатська область~Запорізька область~Івано-Франківська область~Київ~Київська область~Кіровоградська область~Луганська область~Львівська область~Миколаївська область~Одеська область~Полтавська область~Рівненська область~Севастополь~Сумська область~Тернопільська область~Харківська область~Херсонська область~Хмельницька область~Черкаська область~Чернівецька область~Чернігівська область", "sub_zips": "9[5-8]~2[1-4]~4[3-5]~49|5[0-3]~8[3-7]~1[0-3]~8[89]|90~69|7[0-2]~7[6-8]~0[1-6]~0[7-9]~2[5-8]~9[1-4]~79|8[0-2]~5[4-7]~6[5-8]~3[6-9]~3[3-5]~99~4[0-2]~4[6-8]~6[1-4]~7[3-5]~29|3[0-2]~1[89]|20~5[89]|60~1[4-7]", "zip": "\\d{5}", "zipex": "15432,01055,01001"},
+  "data/UG": {"id": "data/UG", "key": "UG", "name": "UGANDA"},
+  "data/US": {"fmt": "%N%n%O%n%A%n%C, %S %Z", "id": "data/US", "key": "US", "lang": "en", "languages": "en", "name": "UNITED STATES", "posturl": "https://tools.usps.com/go/ZipLookupAction!input.action", "require": "ACSZ", "state_name_type": "state", "sub_isoids": "AL~AK~~AZ~AR~~~~CA~CO~CT~DE~DC~FL~GA~~HI~ID~IL~IN~IA~KS~KY~LA~ME~~MD~MA~MI~~MN~MS~MO~MT~NE~NV~NH~NJ~NM~NY~NC~ND~~OH~OK~OR~~PA~~RI~SC~SD~TN~TX~UT~VT~~VA~WA~WV~WI~WY", "sub_keys": "AL~AK~AS~AZ~AR~AA~AE~AP~CA~CO~CT~DE~DC~FL~GA~GU~HI~ID~IL~IN~IA~KS~KY~LA~ME~MH~MD~MA~MI~FM~MN~MS~MO~MT~NE~NV~NH~NJ~NM~NY~NC~ND~MP~OH~OK~OR~PW~PA~PR~RI~SC~SD~TN~TX~UT~VT~VI~VA~WA~WV~WI~WY", "sub_names": "Alabama~Alaska~American Samoa~Arizona~Arkansas~Armed Forces (AA)~Armed Forces (AE)~Armed Forces (AP)~California~Colorado~Connecticut~Delaware~District of Columbia~Florida~Georgia~Guam~Hawaii~Idaho~Illinois~Indiana~Iowa~Kansas~Kentucky~Louisiana~Maine~Marshall Islands~Maryland~Massachusetts~Michigan~Micronesia~Minnesota~Mississippi~Missouri~Montana~Nebraska~Nevada~New Hampshire~New Jersey~New Mexico~New York~North Carolina~North Dakota~Northern Mariana Islands~Ohio~Oklahoma~Oregon~Palau~Pennsylvania~Puerto Rico~Rhode Island~South Carolina~South Dakota~Tennessee~Texas~Utah~Vermont~Virgin Islands~Virginia~Washington~West Virginia~Wisconsin~Wyoming", "sub_zipexs": "35000,36999~99500,99999~96799~85000,86999~71600,72999~34000,34099~09000,09999~96200,96699~90000,96199~80000,81999~06000,06999~19700,19999~20000,56999~32000,34999~30000,39901~96910,96932~96700,96899~83200,83999~60000,62999~46000,47999~50000,52999~66000,67999~40000,42799~70000,71599~03900,04999~96960,96979~20600,21999~01000,05544~48000,49999~96941,96944~55000,56799~38600,39799~63000,65999~59000,59999~68000,69999~88900,89999~03000,03899~07000,08999~87000,88499~10000,00544~27000,28999~58000,58999~96950,96952~43000,45999~73000,74999~97000,97999~96940~15000,19699~00600,00999~02800,02999~29000,29999~57000,57999~37000,38599~75000,73344~84000,84999~05000,05999~00800,00899~20100,24699~98000,99499~24700,26999~53000,54999~82000,83414", "sub_zips": "3[56]~99[5-9]~96799~8[56]~71[6-9]|72~340~09~96[2-6]~9[0-5]|96[01]~8[01]~06~19[7-9]~20[02-5]|569~3[23]|34[1-9]~3[01]|398|39901~969([1-2]\\d|3[12])~967[0-8]|9679[0-8]|968~83[2-9]~6[0-2]~4[67]~5[0-2]~6[67]~4[01]|42[0-7]~70|71[0-5]~039|04~969[67]~20[6-9]|21~01|02[0-7]|05501|05544~4[89]~9694[1-4]~55|56[0-7]~38[6-9]|39[0-7]~6[3-5]~59~6[89]~889|89~03[0-8]~0[78]~87|88[0-4]~1[0-4]|06390|00501|00544~2[78]~58~9695[0-2]~4[3-5]~7[34]~97~969(39|40)~1[5-8]|19[0-6]~00[679]~02[89]~29~57~37|38[0-5]~7[5-9]|885|73301|73344~84~05~008~201|2[23]|24[0-6]~98|99[0-4]~24[7-9]|2[56]~5[34]~82|83[01]|83414", "upper": "CS", "zip": "(\\d{5})(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "95014,22162-1010"},
+  "data/UY": {"fmt": "%N%n%O%n%A%n%Z %C %S", "id": "data/UY", "key": "UY", "lang": "es", "languages": "es", "name": "URUGUAY", "posturl": "http://www.correo.com.uy/index.asp?codPag=codPost&switchMapa=codPost", "sub_isoids": "AR~CA~CL~CO~DU~FS~FD~LA~MA~MO~PA~RN~RV~RO~SA~SJ~SO~TA~TT", "sub_keys": "Artigas~Canelones~Cerro Largo~Colonia~Durazno~Flores~Florida~Lavalleja~Maldonado~Montevideo~Paysandú~Río Negro~Rivera~Rocha~Salto~San José~Soriano~Tacuarembó~Treinta y Tres", "sub_zips": "55~9[01]|1[456]~37~70|75204~97~85~94|9060|97005~30~20~1|91600~60~65|60002~40~27~50~80~75|70003~45~33|30203|30204|30302|37007", "upper": "CS", "zip": "\\d{5}", "zipex": "11600"},
+  "data/UZ": {"fmt": "%N%n%O%n%A%n%Z %C%n%S", "id": "data/UZ", "key": "UZ", "name": "UZBEKISTAN", "posturl": "http://www.pochta.uz/ru/uslugi/indexsearch.html", "upper": "CS", "zip": "\\d{6}", "zipex": "702100,700000"},
+  "data/VA": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/VA", "key": "VA", "name": "VATICAN", "zip": "00120", "zipex": "00120"},
+  "data/VC": {"fmt": "%N%n%O%n%A%n%C %Z", "id": "data/VC", "key": "VC", "name": "SAINT VINCENT AND THE GRENADINES (ANTILLES)", "posturl": "http://www.svgpost.gov.vc/?option=com_content&view=article&id=3&Itemid=16", "zip": "VC\\d{4}", "zipex": "VC0100,VC0110,VC0400"},
+  "data/VE": {"fmt": "%N%n%O%n%A%n%C %Z, %S", "id": "data/VE", "key": "VE", "lang": "es", "languages": "es", "name": "VENEZUELA", "posturl": "http://www.ipostel.gob.ve/index.php/oficinas-postales", "require": "ACS", "state_name_type": "state", "sub_isoids": "Z~B~C~D~E~F~G~H~Y~W~A~I~J~K~L~M~N~O~P~R~S~T~X~U~V", "sub_keys": "Amazonas~Anzoátegui~Apure~Aragua~Barinas~Bolívar~Carabobo~Cojedes~Delta Amacuro~Dependencias Federales~Distrito Federal~Falcón~Guárico~Lara~Mérida~Miranda~Monagas~Nueva Esparta~Portuguesa~Sucre~Táchira~Trujillo~Vargas~Yaracuy~Zulia", "upper": "CS", "zip": "\\d{4}", "zipex": "1010,3001,8011,1020"},
+  "data/VG": {"fmt": "%N%n%O%n%A%n%C%n%Z", "id": "data/VG", "key": "VG", "name": "VIRGIN ISLANDS (BRITISH)", "require": "A", "zip": "VG\\d{4}", "zipex": "VG1110,VG1150,VG1160"},
+  "data/VI": {"fmt": "%N%n%O%n%A%n%C %S %Z", "id": "data/VI", "key": "VI", "name": "VIRGIN ISLANDS (U.S.)", "posturl": "http://zip4.usps.com/zip4/welcome.jsp", "require": "ACSZ", "state_name_type": "state", "upper": "ACNOS", "zip": "(008(?:(?:[0-4]\\d)|(?:5[01])))(?:[ \\-](\\d{4}))?", "zip_name_type": "zip", "zipex": "00802-1222,00850-9802"},
+  "data/VN": {"fmt": "%N%n%O%n%A%n%C%n%S %Z", "id": "data/VN", "key": "VN", "lang": "vi", "languages": "vi", "lfmt": "%N%n%O%n%A%n%C%n%S %Z", "name": "VIET NAM", "posturl": "http://postcode.vnpost.vn/services/search.aspx", "sub_isoids": "44~43~55~54~53~56~50~57~31~58~40~59~04~CT~DN~33~72~71~39~45~30~03~63~HN~23~61~HP~73~14~66~34~47~28~01~09~02~35~41~67~22~18~36~68~32~24~27~29~13~25~52~05~37~20~69~21~SG~26~46~51~07~49~70~06", "sub_keys": "An Giang~Bà Rịa–Vũng Tàu~Bạc Liêu~Bắc Giang~Bắc Kạn~Bắc Ninh~Bến Tre~Bình Dương~Bình Định~Bình Phước~Bình Thuận~Cà Mau~Cao Bằng~Cần Thơ~Đà Nẵng~Đắk Lắk~Đăk Nông~Điện Biên~Đồng Nai~Đồng Tháp~Gia Lai~Hà Giang~Hà Nam~Hà Nội~Hà Tĩnh~Hải Dương~Hải Phòng~Hậu Giang~Hòa Bình~Hưng Yên~Khánh Hòa~Kiên Giang~Kon Tum~Lai Châu~Lạng Sơn~Lào Cai~Lâm Đồng~Long An~Nam Định~Nghệ An~Ninh Bình~Ninh Thuận~Phú Thọ~Phú Yên~Quảng Bình~Quảng Nam~Quảng Ngãi~Quảng Ninh~Quảng Trị~Sóc Trăng~Sơn La~Tây Ninh~Thái Bình~Thái Nguyên~Thanh Hóa~Thành phố Hồ Chí Minh~Thừa Thiên–Huế~Tiền Giang~Trà Vinh~Tuyên Quang~Vĩnh Long~Vĩnh Phúc~Yên Bái", "sub_lnames": "An Giang Province~Ba Ria-Vung Tau Province~Bac Lieu Province~Bac Giang Province~Bac Kan Province~Bac Ninh Province~Ben Tre Province~Binh Duong Province~Binh Dinh Province~Binh Phuoc Province~Binh Thuan Province~Ca Mau Province~Cao Bang Province~Can Tho City~Da Nang City~Dak Lak Province~Dak Nong Province~Dien Bien Province~Dong Nai Province~Dong Thap Province~Gia Lai Province~Ha Giang Province~Ha Nam Province~Hanoi City~Ha Tinh Province~Hai Duong Province~Haiphong City~Hau Giang Province~Hoa Binh Province~Hung Yen Province~Khanh Hoa Province~Kien Giang Province~Kon Tum Province~Lai Chau Province~Lang Song Province~Lao Cai Province~Lam Dong Province~Long An Province~Nam Dinh Province~Nghe An Province~Ninh Binh Province~Ninh Thuan Province~Phu Tho Province~Phu Yen Province~Quang Binh Province~Quang Nam Province~Quang Ngai Province~Quang Ninh Province~Quang Tri Province~Soc Trang Province~Son La Province~Tay Ninh Province~Thai Binh Province~Thai Nguyen Province~Thanh Hoa Province~Ho Chi Minh City~Thua Thien-Hue Province~Tien Giang Province~Tra Vinh Province~Tuyen Quang Province~Vinh Long Province~Vinh Phuc Province~Yen Bai Province", "zip": "\\d{5}\\d?", "zipex": "70010,55999"},
+  "data/VU": {"id": "data/VU", "key": "VU", "name": "VANUATU"},
+  "data/WF": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/WF", "key": "WF", "name": "WALLIS AND FUTUNA ISLANDS", "require": "ACZ", "upper": "ACX", "zip": "986\\d{2}", "zipex": "98600"},
+  "data/WS": {"id": "data/WS", "key": "WS", "name": "SAMOA"},
+  "data/XK": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/XK", "key": "XK", "name": "KOSOVO", "zip": "[1-7]\\d{4}", "zipex": "10000"},
+  "data/YE": {"id": "data/YE", "key": "YE", "name": "YEMEN"},
+  "data/YT": {"fmt": "%O%n%N%n%A%n%Z %C %X", "id": "data/YT", "key": "YT", "name": "MAYOTTE", "require": "ACZ", "upper": "ACX", "zip": "976\\d{2}", "zipex": "97600"},
+  "data/ZA": {"fmt": "%N%n%O%n%A%n%D%n%C%n%Z", "id": "data/ZA", "key": "ZA", "name": "SOUTH AFRICA", "posturl": "https://www.postoffice.co.za/Questions/postalcode.html", "require": "ACZ", "zip": "\\d{4}", "zipex": "0083,1451,0001"},
+  "data/ZM": {"fmt": "%N%n%O%n%A%n%Z %C", "id": "data/ZM", "key": "ZM", "name": "ZAMBIA", "zip": "\\d{5}", "zipex": "50100,50101"},
+  "data/ZW": {"id": "data/ZW", "key": "ZW", "name": "ZIMBABWE"},
 };
--- a/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js
+++ b/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* exported addressDataExt */
 /* eslint max-len: 0 */
 
 "use strict";
 
-// "addressDataExt" uses the same key as "addressData" in "addressReferences.js" and contains
+// "addressDataExt" uses the same key as "addressData" in "addressReferences.js" and
 //  contains the information we need but absent in "libaddressinput" such as alternative names.
 
 // TODO: We only support the alternative name of US in MVP. We are going to support more countries in
 //       bug 1370193.
 var addressDataExt = {
   "data/US": {
     alternative_names: ["US", "United States of America", "United States", "America", "U.S.", "USA", "U.S.A.", "U.S.A"],
     fmt: "%N%n%A%n%C%S%n%Z%O",
--- a/browser/extensions/formautofill/content/autofillEditForms.js
+++ b/browser/extensions/formautofill/content/autofillEditForms.js
@@ -117,26 +117,29 @@ class EditAutofillForm {
 
 class EditAddress extends EditAutofillForm {
   /**
    * @param {HTMLElement[]} elements
    * @param {object} record
    * @param {object} config
    * @param {string[]} config.DEFAULT_REGION
    * @param {function} config.getFormFormat Function to return form layout info for a given country.
-   * @param {string[]} config.supportedCountries
+   * @param {string[]} config.countries
    */
   constructor(elements, record, config) {
     super(elements);
 
     Object.assign(this, config);
+    let {form} = this._elements;
     Object.assign(this._elements, {
-      addressLevel1Label: this._elements.form.querySelector("#address-level1-container > span"),
-      postalCodeLabel: this._elements.form.querySelector("#postal-code-container > span"),
-      country: this._elements.form.querySelector("#country"),
+      addressLevel3Label: form.querySelector("#address-level3-container > .label-text"),
+      addressLevel2Label: form.querySelector("#address-level2-container > .label-text"),
+      addressLevel1Label: form.querySelector("#address-level1-container > .label-text"),
+      postalCodeLabel: form.querySelector("#postal-code-container > .label-text"),
+      country: form.querySelector("#country"),
     });
 
     this.populateCountries();
     // Need to populate the countries before trying to set the initial country.
     // Also need to use this._record so it has the default country selected.
     this.loadRecord(record);
     this.attachEventListeners();
 
@@ -144,17 +147,17 @@ class EditAddress extends EditAutofillFo
       this.form.setAttribute("novalidate", "true");
     }
   }
 
   loadRecord(record) {
     this._record = record;
     if (!record) {
       record = {
-        country: this.supportedCountries.find(supported => supported == this.DEFAULT_REGION),
+        country: this.DEFAULT_REGION,
       };
     }
     super.loadRecord(record);
     this.formatForm(record.country);
   }
 
   /**
    * `mailing-address` is a special attribute token to indicate mailing fields + country.
@@ -200,21 +203,25 @@ class EditAddress extends EditAutofillFo
 
   /**
    * Format the form based on country. The address-level1 and postal-code labels
    * should be specific to the given country.
    * @param  {string} country
    */
   formatForm(country) {
     const {
+      addressLevel3Label,
+      addressLevel2Label,
       addressLevel1Label,
       postalCodeLabel,
       fieldsOrder: mailingFieldsOrder,
       postalCodePattern,
     } = this.getFormFormat(country);
+    this._elements.addressLevel3Label.dataset.localization = addressLevel3Label;
+    this._elements.addressLevel2Label.dataset.localization = addressLevel2Label;
     this._elements.addressLevel1Label.dataset.localization = addressLevel1Label;
     this._elements.postalCodeLabel.dataset.localization = postalCodeLabel;
     let addressFields = this._elements.form.dataset.addressFields;
     let fieldClasses = EditAddress.computeVisibleFields(mailingFieldsOrder, addressFields);
     this.arrangeFields(fieldClasses);
     this.updatePostalCodeValidation(postalCodePattern);
   }
 
@@ -223,16 +230,17 @@ class EditAddress extends EditAutofillFo
    *
    * @param {object[]} fieldsOrder array of objects with `fieldId` and optional `newLine` properties
    */
   arrangeFields(fieldsOrder) {
     let fields = [
       "name",
       "organization",
       "street-address",
+      "address-level3",
       "address-level2",
       "address-level1",
       "postal-code",
       "country",
       "tel",
       "email",
     ];
     let inputs = [];
@@ -268,20 +276,22 @@ class EditAddress extends EditAutofillFo
       postalCodeInput.setAttribute("pattern", postalCodePattern);
     } else {
       postalCodeInput.removeAttribute("pattern");
     }
   }
 
   populateCountries() {
     let fragment = document.createDocumentFragment();
-    for (let country of this.supportedCountries) {
+    // Sort countries by their visible names.
+    let countries = [...this.countries.entries()].sort((e1, e2) => e1[1].localeCompare(e2[1]));
+    for (let country of countries) {
       let option = new Option();
-      option.value = country;
-      option.dataset.localizationRegion = country.toLowerCase();
+      option.value = country[0];
+      option.dataset.localizationRegion = country[0].toLowerCase();
       fragment.appendChild(option);
     }
     this._elements.country.appendChild(fragment);
   }
 
   handleChange(event) {
     if (event.target == this._elements.country) {
       this.formatForm(event.target.value);
--- a/browser/extensions/formautofill/content/editAddress.xhtml
+++ b/browser/extensions/formautofill/content/editAddress.xhtml
@@ -39,19 +39,23 @@
     <label id="organization-container" class="container">
       <input id="organization" type="text"/>
       <span data-localization="organization2" class="label-text"/>
     </label>
     <label id="street-address-container" class="container">
       <textarea id="street-address" rows="3" required="required"/>
       <span data-localization="streetAddress" class="label-text"/>
     </label>
+    <label id="address-level3-container" class="container">
+      <input id="address-level3" type="text" required="required"/>
+      <span class="label-text"/>
+    </label>
     <label id="address-level2-container" class="container">
       <input id="address-level2" type="text" required="required"/>
-      <span data-localization="city" class="label-text"/>
+      <span class="label-text"/>
     </label>
     <label id="address-level1-container" class="container">
       <input id="address-level1" type="text" required="required"/>
       <span class="label-text"/>
     </label>
     <label id="postal-code-container" class="container">
       <input id="postal-code" type="text" required="required"/>
       <span class="label-text"/>
@@ -76,31 +80,31 @@
     <button id="save" disabled="disabled" data-localization="saveBtnLabel"/>
     <span id="country-warning-message" data-localization="countryWarningMessage2"/>
   </div>
   <script type="application/javascript"><![CDATA[
     "use strict";
 
     let {
       DEFAULT_REGION,
-      supportedCountries,
+      countries,
     } = FormAutofill;
     let {
       getFormFormat,
     } = FormAutofillUtils;
     let record = window.arguments && window.arguments[0];
     let novalidate = window.arguments && window.arguments[1] == "novalidate";
 
     /* import-globals-from autofillEditForms.js */
-    let fieldContainer = new EditAddress({
+    var fieldContainer = new EditAddress({
       form: document.getElementById("form"),
     }, record, {
       DEFAULT_REGION,
       getFormFormat: getFormFormat.bind(FormAutofillUtils),
-      supportedCountries,
+      countries,
       novalidate,
     });
 
     /* import-globals-from editDialog.js */
     new EditAddressDialog({
       title: document.querySelector("title"),
       fieldContainer,
       controlsContainer: document.getElementById("controls-container"),
--- a/browser/extensions/formautofill/locales/en-US/formautofill.properties
+++ b/browser/extensions/formautofill/locales/en-US/formautofill.properties
@@ -114,21 +114,64 @@ manageDialogsWidth = 560px
 # in browser preferences.
 addNewAddressTitle = Add New Address
 editAddressTitle = Edit Address
 givenName = First Name
 additionalName = Middle Name
 familyName = Last Name
 organization2 = Organization
 streetAddress = Street Address
+
+## address-level-3 (Sublocality) names
+# LOCALIZATION NOTE (neighborhood): Used in IR, MX
+neighborhood = Neighborhood
+# LOCALIZATION NOTE (village_township): Used in MY
+village_township = Village or Township
+island = Island
+# LOCALIZATION NOTE (townland): Used in IE
+townland = Townland
+
+## address-level-2 names
 city = City
+# LOCALIZATION NOTE (district): Used in HK, SD, SY, TR as Address Level-2
+# and used in KR as Sublocality.
+district = District
+# LOCALIZATION NOTE (post_town): Used in GB, NO, SE
+post_town = Post town
+# LOCALIZATION NOTE (suburb): Used in AU as Address Level-2
+# and used in ZZ as Sublocality.
+suburb = Suburb
+
+# address-level-1 names
 province = Province
 state = State
+county = County
+# LOCALIZATION NOTE (parish): Used in BB, JM
+parish = Parish
+# LOCALIZATION NOTE (prefecture): Used in JP
+prefecture = Prefecture
+# LOCALIZATION NOTE (area): Used in HK
+area = Area
+# LOCALIZATION NOTE (do_si): Used in KR
+do_si = Do/Si
+# LOCALIZATION NOTE (department): Used in NI, CO
+department = Department
+# LOCALIZATION NOTE (emirate): Used in AE
+emirate = Emirate
+# LOCALIZATION NOTE (oblast): Used in RU and UA
+oblast = Oblast
+
+# LOCALIZATION NOTE (pin, postalCode, zip, eircode): Postal code name types
+# LOCALIZATION NOTE (pin): Used in IN
+pin = Pin
 postalCode = Postal Code
 zip = ZIP Code
+# LOCALIZATION NOTE (eircode): Used in IE
+eircode = Eircode
+
 country = Country or Region
 tel = Phone
 email = Email
 cancelBtnLabel = Cancel
 saveBtnLabel = Save
 countryWarningMessage2 = Form Autofill is currently available only for certain countries.
 
 # LOCALIZATION NOTE (addNewCreditCardTitle, editCreditCardTitle): The dialog title for creating or editing
--- a/browser/extensions/formautofill/skin/shared/editAddress.css
+++ b/browser/extensions/formautofill/skin/shared/editAddress.css
@@ -22,16 +22,18 @@
   flex-grow: 1;
 }
 
 #country-container {
   /* The country dropdown has a different intrinsic (content) width than the
      other fields which are <input>. */
   flex-basis: calc(50% - var(--grid-column-row-gap));
   flex-grow: 0;
+  /* Country names can be longer than 50% which ruins the symmetry in the grid. */
+  max-width: calc(50% - var(--grid-column-row-gap));
 }
 
 
 /* Begin name field rules */
 
 #name-container input {
   /* Override the default @size="20" on <input>, which acts like a min-width, not
    * allowing the fields to shrink with flexbox as small as they need to to match
--- a/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js
+++ b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js
@@ -1,10 +1,12 @@
 "use strict";
 
+requestLongerTimeout(6);
+
 add_task(async function setup_supportedCountries() {
   await SpecialPowers.pushPrefEnv({set: [
     [SUPPORTED_COUNTRIES_PREF, "US,CA,DE"],
   ]});
 });
 
 
 add_task(async function test_cancelEditAddressDialog() {
@@ -44,19 +46,19 @@ add_task(async function test_defaultCoun
   });
   SpecialPowers.pushPrefEnv({set: [[DEFAULT_REGION_PREF, "US"]]});
 });
 
 add_task(async function test_saveAddress() {
   await testDialog(EDIT_ADDRESS_DIALOG_URL, win => {
     let doc = win.document;
     // Verify labels
-    is(doc.querySelector("#address-level1-container > span").textContent, "State",
+    is(doc.querySelector("#address-level1-container > .label-text").textContent, "State",
                          "US address-level1 label should be 'State'");
-    is(doc.querySelector("#postal-code-container > span").textContent, "ZIP Code",
+    is(doc.querySelector("#postal-code-container > .label-text").textContent, "ZIP Code",
                          "US postal-code label should be 'ZIP Code'");
     // Input address info and verify move through form with tab keys
     const keyInputs = [
       "VK_TAB",
       TEST_ADDRESS_1["given-name"],
       "VK_TAB",
       TEST_ADDRESS_1["additional-name"],
       "VK_TAB",
@@ -67,17 +69,17 @@ add_task(async function test_saveAddress
       TEST_ADDRESS_1["address-level2"],
       "VK_TAB",
       TEST_ADDRESS_1["address-level1"],
       "VK_TAB",
       TEST_ADDRESS_1["postal-code"],
       "VK_TAB",
       TEST_ADDRESS_1.organization,
       "VK_TAB",
-      TEST_ADDRESS_1.country,
+      // TEST_ADDRESS_1.country, // Country is already US
       "VK_TAB",
       TEST_ADDRESS_1.tel,
       "VK_TAB",
       TEST_ADDRESS_1.email,
       "VK_TAB",
       "VK_TAB",
       "VK_RETURN",
     ];
@@ -113,22 +115,25 @@ add_task(async function test_editAddress
 add_task(async function test_saveAddressCA() {
   await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
     let doc = win.document;
     // Change country to verify labels
     doc.querySelector("#country").focus();
     EventUtils.synthesizeKey("Canada", {}, win);
 
     await TestUtils.waitForCondition(() => {
-      return doc.querySelector("#address-level1-container > span").textContent == "Province";
+      return doc.querySelector("#address-level1-container > .label-text").textContent == "Province";
     }, "Wait for the mutation observer to change the labels");
-    is(doc.querySelector("#address-level1-container > span").textContent, "Province",
+    is(doc.querySelector("#address-level1-container > .label-text").textContent, "Province",
                          "CA address-level1 label should be 'Province'");
-    is(doc.querySelector("#postal-code-container > span").textContent, "Postal Code",
+    is(doc.querySelector("#postal-code-container > .label-text").textContent, "Postal Code",
                          "CA postal-code label should be 'Postal Code'");
+    is(doc.querySelector("#address-level3-container").style.display, "none",
+                         "CA address-level3 should be hidden");
+
     // Input address info and verify move through form with tab keys
     doc.querySelector("#given-name").focus();
     const keyInputs = [
       TEST_ADDRESS_CA_1["given-name"],
       "VK_TAB",
       TEST_ADDRESS_CA_1["additional-name"],
       "VK_TAB",
       TEST_ADDRESS_CA_1["family-name"],
@@ -138,17 +143,17 @@ add_task(async function test_saveAddress
       TEST_ADDRESS_CA_1["street-address"],
       "VK_TAB",
       TEST_ADDRESS_CA_1["address-level2"],
       "VK_TAB",
       TEST_ADDRESS_CA_1["address-level1"],
       "VK_TAB",
       TEST_ADDRESS_CA_1["postal-code"],
       "VK_TAB",
-      TEST_ADDRESS_CA_1.country,
+      // TEST_ADDRESS_1.country, // Country is already selected above
       "VK_TAB",
       TEST_ADDRESS_CA_1.tel,
       "VK_TAB",
       TEST_ADDRESS_CA_1.email,
       "VK_TAB",
       "VK_TAB",
       "VK_RETURN",
     ];
@@ -163,22 +168,24 @@ add_task(async function test_saveAddress
 
 add_task(async function test_saveAddressDE() {
   await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
     let doc = win.document;
     // Change country to verify labels
     doc.querySelector("#country").focus();
     EventUtils.synthesizeKey("Germany", {}, win);
     await TestUtils.waitForCondition(() => {
-      return doc.querySelector("#postal-code-container > span").textContent == "Postal Code";
+      return doc.querySelector("#postal-code-container > .label-text").textContent == "Postal Code";
     }, "Wait for the mutation observer to change the labels");
-    is(doc.querySelector("#postal-code-container > span").textContent, "Postal Code",
+    is(doc.querySelector("#postal-code-container > .label-text").textContent, "Postal Code",
                          "DE postal-code label should be 'Postal Code'");
     is(doc.querySelector("#address-level1-container").style.display, "none",
                          "DE address-level1 should be hidden");
+    is(doc.querySelector("#address-level3-container").style.display, "none",
+                         "DE address-level3 should be hidden");
     // Input address info and verify move through form with tab keys
     doc.querySelector("#given-name").focus();
     const keyInputs = [
       TEST_ADDRESS_DE_1["given-name"],
       "VK_TAB",
       TEST_ADDRESS_DE_1["additional-name"],
       "VK_TAB",
       TEST_ADDRESS_DE_1["family-name"],
@@ -186,17 +193,17 @@ add_task(async function test_saveAddress
       TEST_ADDRESS_DE_1.organization,
       "VK_TAB",
       TEST_ADDRESS_DE_1["street-address"],
       "VK_TAB",
       TEST_ADDRESS_DE_1["postal-code"],
       "VK_TAB",
       TEST_ADDRESS_DE_1["address-level2"],
       "VK_TAB",
-      TEST_ADDRESS_DE_1.country,
+      // TEST_ADDRESS_1.country, // Country is already selected above
       "VK_TAB",
       TEST_ADDRESS_DE_1.tel,
       "VK_TAB",
       TEST_ADDRESS_DE_1.email,
       "VK_TAB",
       "VK_TAB",
       "VK_RETURN",
     ];
@@ -204,16 +211,115 @@ add_task(async function test_saveAddress
   });
   let addresses = await getAddresses();
   for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_DE_1)) {
     is(addresses[0][fieldName], fieldValue, "check " + fieldName);
   }
   await removeAllRecords();
 });
 
+add_task(async function test_saveAddressIE() {
+  await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+    let doc = win.document;
+    // Change country to verify labels
+    doc.querySelector("#country").focus();
+    EventUtils.synthesizeKey("Ireland", {}, win);
+    await TestUtils.waitForCondition(() => {
+      return doc.querySelector("#postal-code-container > .label-text").textContent == "Eircode";
+    }, "Wait for the mutation observer to change the labels");
+    is(doc.querySelector("#postal-code-container > .label-text").textContent, "Eircode",
+                         "IE postal-code label should be 'Eircode'");
+    is(doc.querySelector("#address-level1-container > .label-text").textContent, "County",
+                         "IE address-level1 should be 'County'");
+    is(doc.querySelector("#address-level3-container > .label-text").textContent, "Townland",
+                         "IE address-level3 should be 'Townland'");
+
+    // Input address info and verify move through form with tab keys
+    doc.querySelector("#given-name").focus();
+    const keyInputs = [
+      TEST_ADDRESS_IE_1["given-name"],
+      "VK_TAB",
+      TEST_ADDRESS_IE_1["additional-name"],
+      "VK_TAB",
+      TEST_ADDRESS_IE_1["family-name"],
+      "VK_TAB",
+      TEST_ADDRESS_IE_1.organization,
+      "VK_TAB",
+      TEST_ADDRESS_IE_1["street-address"],
+      "VK_TAB",
+      TEST_ADDRESS_IE_1["address-level3"],
+      "VK_TAB",
+      TEST_ADDRESS_IE_1["address-level2"],
+      "VK_TAB",
+      TEST_ADDRESS_IE_1["address-level1"],
+      "VK_TAB",
+      TEST_ADDRESS_IE_1["postal-code"],
+      "VK_TAB",
+      // TEST_ADDRESS_1.country, // Country is already selected above
+      "VK_TAB",
+      TEST_ADDRESS_IE_1.tel,
+      "VK_TAB",
+      TEST_ADDRESS_IE_1.email,
+      "VK_TAB",
+      "VK_TAB",
+      "VK_RETURN",
+    ];
+    keyInputs.forEach(input => EventUtils.synthesizeKey(input, {}, win));
+  });
+
+  let addresses = await getAddresses();
+  for (let [fieldName, fieldValue] of Object.entries(TEST_ADDRESS_IE_1)) {
+    is(addresses[0][fieldName], fieldValue, "check " + fieldName);
+  }
+  await removeAllRecords();
+});
+
+add_task(async function test_countryFieldLabels() {
+  await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
+    let doc = win.document;
+    // Change country to verify labels
+    doc.querySelector("#country").focus();
+
+    let mutatableLabels = [
+      "postal-code-container",
+      "address-level1-container",
+      "address-level2-container",
+      "address-level3-container",
+    ].map(containerID => doc.getElementById(containerID).querySelector(":scope > .label-text"));
+
+    for (let countryOption of doc.querySelector("#country").options) {
+      if (countryOption.value == "") {
+        info("Skipping the empty option");
+        continue;
+      }
+
+      // Clear L10N attributes and textContent to not leave leftovers between country tests
+      for (let labelEl of mutatableLabels) {
+        labelEl.textContent = "";
+        delete labelEl.dataset.localization;
+      }
+
+      info(`Selecting '${countryOption.label}' (${countryOption.value})`);
+      EventUtils.synthesizeKey(countryOption.label, {}, win);
+
+      // Check that the labels were filled
+      for (let labelEl of mutatableLabels) {
+        await TestUtils.waitForCondition(() => labelEl.textContent,
+                                         "Wait for label to be populated by the mutation observer");
+        isnot(labelEl.textContent, "",
+              "Ensure textContent is non-empty for: " + countryOption.value);
+        is(labelEl.dataset.localization, undefined,
+           "Ensure data-localization was removed: " + countryOption.value);
+      }
+    }
+
+    doc.querySelector("#cancel").click();
+  });
+});
+
 add_task(async function test_combined_name_fields() {
   await testDialog(EDIT_ADDRESS_DIALOG_URL, async win => {
     let doc = win.document;
     let givenNameField = doc.querySelector("#given-name");
     let addtlNameField = doc.querySelector("#additional-name");
     let familyNameField = doc.querySelector("#family-name");
 
     function getComputedPropertyValue(field, property) {
--- a/browser/extensions/formautofill/test/browser/head.js
+++ b/browser/extensions/formautofill/test/browser/head.js
@@ -1,10 +1,11 @@
 /* exported MANAGE_ADDRESSES_DIALOG_URL, MANAGE_CREDIT_CARDS_DIALOG_URL, EDIT_ADDRESS_DIALOG_URL, EDIT_CREDIT_CARD_DIALOG_URL,
             BASE_URL, TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3, TEST_ADDRESS_4, TEST_ADDRESS_5, TEST_ADDRESS_CA_1, TEST_ADDRESS_DE_1,
+            TEST_ADDRESS_IE_1,
             TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2, TEST_CREDIT_CARD_3, FORM_URL, CREDITCARD_FORM_URL,
             FTU_PREF, ENABLED_AUTOFILL_ADDRESSES_PREF, AUTOFILL_CREDITCARDS_AVAILABLE_PREF, ENABLED_AUTOFILL_CREDITCARDS_PREF,
             SUPPORTED_COUNTRIES_PREF,
             SYNC_USERNAME_PREF, SYNC_ADDRESSES_PREF, SYNC_CREDITCARDS_PREF, SYNC_CREDITCARDS_AVAILABLE_PREF, CREDITCARDS_USED_STATUS_PREF,
             DEFAULT_REGION_PREF,
             sleep, expectPopupOpen, openPopupOn, expectPopupClose, closePopup, clickDoorhangerButton,
             getAddresses, saveAddress, removeAddresses, saveCreditCard,
             getDisplayedPopupItems, getDoorhangerCheckbox, waitForMasterPasswordDialog,
@@ -94,16 +95,31 @@ const TEST_ADDRESS_DE_1 = {
   "street-address": "Geb\u00E4ude 3, 4. Obergeschoss\nSchlesische Stra\u00DFe 27",
   "address-level2": "Berlin",
   "postal-code": "10997",
   country: "DE",
   tel: "+4930983333000",
   email: "timbl@w3.org",
 };
 
+const TEST_ADDRESS_IE_1 = {
+  "given-name": "Bob",
+  "additional-name": "Z.",
+  "family-name": "Builder",
+  organization: "Best Co.",
+  "street-address": "123 Kilkenny St.",
+  "address-level3": "Some Townland",
+  "address-level2": "Dublin",
+  "address-level1": "Co. Dublin",
+  "postal-code": "A65 F4E2",
+  country: "IE",
+  tel: "+13534564947391",
+  email: "ie@example.com",
+};
+
 const TEST_CREDIT_CARD_1 = {
   "cc-name": "John Doe",
   "cc-number": "4111111111111111",
   "cc-exp-month": 4,
   "cc-exp-year": new Date().getFullYear(),
   "cc-type": "visa",
 };
 
--- a/browser/extensions/formautofill/test/unit/test_createRecords.js
+++ b/browser/extensions/formautofill/test/unit/test_createRecords.js
@@ -64,21 +64,18 @@ const TESTCASES = [
                 <input id="country" autocomplete="country">
                </form>`,
     formValue: {
       "given-name": "John",
       "organization": "Mozilla",
       "country": "United States",
     },
     expectedRecord: {
-      address: [{
-        "given-name": "John",
-        "organization": "Mozilla",
-        "country": "United States",
-      }],
+      // "United States" is not a valid country, only country-name. See isRecordCreatable.
+      address: [],
       creditCard: [],
     },
   },
   {
     description: "\"country\" using heuristics should be identified aggressively",
     document: `<form>
                 <input id="given-name" autocomplete="given-name">
                 <input id="organization" autocomplete="organization">
@@ -127,72 +124,72 @@ const TESTCASES = [
                 <input id="given-name" autocomplete="given-name">
                 <input id="organization" autocomplete="organization">
                 <input id="country" autocomplete="country">
                 <input id="tel" autocomplete="tel-national">
                </form>`,
     formValue: {
       "given-name": "John",
       "organization": "Mozilla",
-      "country": "United States",
+      "country": "US",
       "tel": "1234",
     },
     expectedRecord: {
       address: [{
         "given-name": "John",
         "organization": "Mozilla",
-        "country": "United States",
+        "country": "US",
         "tel": "",
       }],
       creditCard: [],
     },
   },
   {
     description: "\"tel\" should be removed if it's too long",
     document: `<form>
                 <input id="given-name" autocomplete="given-name">
                 <input id="organization" autocomplete="organization">
                 <input id="country" autocomplete="country">
                 <input id="tel" autocomplete="tel-national">
                </form>`,
     formValue: {
       "given-name": "John",
       "organization": "Mozilla",
-      "country": "United States",
+      "country": "US",
       "tel": "1234567890123456",
     },
     expectedRecord: {
       address: [{
         "given-name": "John",
         "organization": "Mozilla",
-        "country": "United States",
+        "country": "US",
         "tel": "",
       }],
       creditCard: [],
     },
   },
   {
     description: "\"tel\" should be removed if it contains invalid characters",
     document: `<form>
                 <input id="given-name" autocomplete="given-name">
                 <input id="organization" autocomplete="organization">
                 <input id="country" autocomplete="country">
                 <input id="tel" autocomplete="tel-national">
                </form>`,
     formValue: {
       "given-name": "John",
       "organization": "Mozilla",
-      "country": "United States",
+      "country": "US",
       "tel": "12345###!!!",
     },
     expectedRecord: {
       address: [{
         "given-name": "John",
         "organization": "Mozilla",
-        "country": "United States",
+        "country": "US",
         "tel": "",
       }],
       creditCard: [],
     },
   },
   {
     description: "All name related fields should be counted as 1 field only.",
     document: `<form>
--- a/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
+++ b/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js
@@ -53,29 +53,29 @@ const TESTCASES = [
     expectedResult: {
       formSubmission: false,
     },
   },
   {
     description: "Trigger address saving",
     formValue: {
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
       "tel": "1-650-903-0800",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "street-address": "331 E. Evelyn Avenue",
             "address-level1": "",
             "address-level2": "",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "1-650-903-0800",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
@@ -104,33 +104,33 @@ const TESTCASES = [
         }],
       },
     },
   },
   {
     description: "Trigger address and credit card saving",
     formValue: {
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
       "tel": "1-650-903-0800",
       "cc-name": "John Doe",
       "cc-number": "5105105105105100",
       "cc-exp-month": 12,
       "cc-exp-year": 2000,
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "street-address": "331 E. Evelyn Avenue",
             "address-level1": "",
             "address-level2": "",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "1-650-903-0800",
           },
           untouchedFields: [],
         }],
         creditCard: [{
           guid: null,
           record: {
@@ -143,266 +143,266 @@ const TESTCASES = [
         }],
       },
     },
   },
   {
     description: "Profile saved with trimmed string",
     formValue: {
       "street-addr": "331 E. Evelyn Avenue  ",
-      "country": "USA",
+      "country": "US",
       "tel": "  1-650-903-0800",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "street-address": "331 E. Evelyn Avenue",
             "address-level1": "",
             "address-level2": "",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "1-650-903-0800",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Eliminate the field that is empty after trimmed",
     formValue: {
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
       "email": "  ",
       "tel": "1-650-903-0800",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "street-address": "331 E. Evelyn Avenue",
             "address-level1": "",
             "address-level2": "",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "1-650-903-0800",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Save state with regular select option",
     formValue: {
       "address-level1": "CA",
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "address-level1": "CA",
             "address-level2": "",
             "street-address": "331 E. Evelyn Avenue",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Save state with lowercase value",
     formValue: {
       "address-level1": "ca",
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "address-level1": "CA",
             "address-level2": "",
             "street-address": "331 E. Evelyn Avenue",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Save state with a country code prefixed to the label",
     formValue: {
       "address-level1": "AR",
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "address-level1": "AR",
             "address-level2": "",
             "street-address": "331 E. Evelyn Avenue",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Save state with a country code prefixed to the value",
     formValue: {
       "address-level1": "US-CA",
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "address-level1": "CA",
             "address-level2": "",
             "street-address": "331 E. Evelyn Avenue",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Save state with a country code prefixed to the value and label",
     formValue: {
       "address-level1": "US-AZ",
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "address-level1": "AZ",
             "address-level2": "",
             "street-address": "331 E. Evelyn Avenue",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Should save select label instead when failed to abbreviate the value",
     formValue: {
       "address-level1": "Ariz",
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "address-level1": "Arizonac",
             "address-level2": "",
             "street-address": "331 E. Evelyn Avenue",
-            "country": "USA",
+            "country": "US",
             "email": "",
             "tel": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Shouldn't save select with multiple selections",
     formValue: {
       "address-level1": ["AL", "AK", "AP"],
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
       "tel": "1-650-903-0800",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "street-address": "331 E. Evelyn Avenue",
             "address-level1": "",
             "address-level2": "",
-            "country": "USA",
+            "country": "US",
             "tel": "1-650-903-0800",
             "email": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
   },
   {
     description: "Shouldn't save select with empty value",
     formValue: {
       "address-level1": "",
       "street-addr": "331 E. Evelyn Avenue",
-      "country": "USA",
+      "country": "US",
       "tel": "1-650-903-0800",
     },
     expectedResult: {
       formSubmission: true,
       records: {
         address: [{
           guid: null,
           record: {
             "street-address": "331 E. Evelyn Avenue",
             "address-level1": "",
             "address-level2": "",
-            "country": "USA",
+            "country": "US",
             "tel": "1-650-903-0800",
             "email": "",
           },
           untouchedFields: [],
         }],
         creditCard: [],
       },
     },
@@ -579,16 +579,17 @@ TESTCASES.forEach(testcase => {
     }
     sinon.stub(FormAutofillContent, "_onFormSubmit");
 
     let element = MOCK_DOC.getElementById(TARGET_ELEMENT_ID);
     FormAutofillContent.identifyAutofillFields(element);
     FormAutofillContent.notify(form);
 
     Assert.equal(FormAutofillContent._onFormSubmit.called,
-                testcase.expectedResult.formSubmission);
+                 testcase.expectedResult.formSubmission,
+                 "Check expected onFormSubmit.called");
     if (FormAutofillContent._onFormSubmit.called) {
       Assert.deepEqual(FormAutofillContent._onFormSubmit.args[0][0],
                        testcase.expectedResult.records);
     }
     FormAutofillContent._onFormSubmit.restore();
   });
 });
--- a/browser/extensions/formautofill/test/unit/test_parseAddressFormat.js
+++ b/browser/extensions/formautofill/test/unit/test_parseAddressFormat.js
@@ -33,16 +33,28 @@ add_task(async function test_parseAddres
       parsed: [
         {fieldId: "name", newLine: true},
         {fieldId: "organization", newLine: true},
         {fieldId: "street-address", newLine: true},
         {fieldId: "postal-code"},
         {fieldId: "address-level2"},
       ],
     },
+    {
+      fmt: "%N%n%O%n%A%n%D%n%C%n%S %Z", // IE
+      parsed: [
+        {fieldId: "name", newLine: true},
+        {fieldId: "organization", newLine: true},
+        {fieldId: "street-address", newLine: true},
+        {fieldId: "address-level3", newLine: true},
+        {fieldId: "address-level2", newLine: true},
+        {fieldId: "address-level1"},
+        {fieldId: "postal-code"},
+      ],
+    },
   ];
 
   Assert.throws(() => FormAutofillUtils.parseAddressFormat(),
                 /fmt string is missing./,
                 "Should throw if fmt is empty");
   for (let tc of TEST_CASES) {
     Assert.deepEqual(FormAutofillUtils.parseAddressFormat(tc.fmt), tc.parsed);
   }
--- a/browser/extensions/formautofill/test/unit/test_transformFields.js
+++ b/browser/extensions/formautofill/test/unit/test_transformFields.js
@@ -409,17 +409,17 @@ const ADDRESS_NORMALIZE_TESTCASES = [
       "country": undefined,
       "country-name": undefined,
     },
   },
   {
     description: "Has unsupported \"country\"",
     address: {
       "given-name": "John", // Make sure it won't be an empty record.
-      "country": "TV",
+      "country": "XX",
     },
     expectedResult: {
       "country": undefined,
       "country-name": undefined,
     },
   },
 
   // Tel
--- a/dom/canvas/test/test_canvas.html
+++ b/dom/canvas/test/test_canvas.html
@@ -27,32 +27,16 @@ function IsLinux() {
         os = Cc["@mozilla.org/xre/app-info;1"]
           .getService(SpecialPowers.Ci.nsIXULRuntime).OS;
     } catch (e) {}
 
     return os.indexOf("Linux") == 0 &&
            !navigator.appVersion.includes("Android");
 }
 
-function IsMacOSX10_5orOlder() {
-    var is105orOlder = false;
-
-    if (navigator.platform.indexOf("Mac") == 0) {
-        var version = Cc["@mozilla.org/system-info;1"]
-                        .getService(SpecialPowers.Ci.nsIPropertyBag2)
-                        .getProperty("version");
-        // the next line is correct: Mac OS 10.6 corresponds to Darwin version 10 !
-        // Mac OS 10.5 would be Darwin version 9. the |version| string we've got here
-        // is the Darwin version.
-        is105orOlder = (parseFloat(version) < 10.0);
-    }
-    return is105orOlder;
-}
-
-
 function IsAzureSkia() {
   var enabled = false;
   
   try {
     var backend = Cc["@mozilla.org/gfx/info;1"].getService(SpecialPowers.Ci.nsIGfxInfo).getInfo().AzureCanvasBackend;
     enabled = (backend == "skia");
   } catch (e) { }
 
@@ -5762,17 +5746,17 @@ isPixel(ctx, 80,25, 0,255,0,255, 2);
 <script>
 
 
 function test_2d_gradient_interpolate_overlap() {
 
 var canvas = document.getElementById('c215');
 var ctx = canvas.getContext('2d');
 
-if (!IsD2DEnabled() && !IsMacOSX10_5orOlder()) {
+if (!IsD2DEnabled()) {
     // On D2D the different nature of how gradients
     // are drawn makes it so we cannot guarantee these stops are completely
     // hard.
 
     // On OS X 10.5 quartz is confused by the overlapping stops: Bug #715235
     canvas.width = 200;
     var g = ctx.createLinearGradient(0, 0, 200, 0);
     g.addColorStop(0, '#f00');
@@ -5822,24 +5806,21 @@ for (var p = 0; p < ps.length; ++p)
         g.addColorStop(ps[p], '#0f0');
         for (var i = 0; i < 15; ++i)
                 g.addColorStop(ps[p], '#f00');
         g.addColorStop(ps[p], '#0f0');
 }
 ctx.fillStyle = g;
 ctx.fillRect(0, 0, 100, 50);
 
-if (!IsMacOSX10_5orOlder()) {
-    // On OS X 10.5 quartz is confused by the overlapping stops: Bug #715235
-    isPixel(ctx, 1,25, 0,255,0,255, 0);
-    isPixel(ctx, 30,25, 0,255,0,255, 0);
-    isPixel(ctx, 40,25, 0,255,0,255, 0);
-    isPixel(ctx, 60,25, 0,255,0,255, 0);
-    isPixel(ctx, 80,25, 0,255,0,255, 0);
-}
+isPixel(ctx, 1,25, 0,255,0,255, 0);
+isPixel(ctx, 30,25, 0,255,0,255, 0);
+isPixel(ctx, 40,25, 0,255,0,255, 0);
+isPixel(ctx, 60,25, 0,255,0,255, 0);
+isPixel(ctx, 80,25, 0,255,0,255, 0);
 
 }
 </script>
 
 <!-- [[[ test_2d.gradient.interpolate.solid.html ]]] -->
 
 <p>Canvas test: 2d.gradient.interpolate.solid</p>
 <canvas id="c217" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -10762,17 +10762,16 @@ subsuite = webgl1-core
 [generated/test_conformance__buffers__index-validation-verifies-too-many-indices.html]
 subsuite = webgl1-core
 [generated/test_conformance__buffers__index-validation-with-resized-buffer.html]
 subsuite = webgl1-core
 [generated/test_conformance__buffers__index-validation.html]
 subsuite = webgl1-core
 [generated/test_conformance__canvas__buffer-offscreen-test.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__canvas__buffer-preserve-test.html]
 subsuite = webgl1-core
 [generated/test_conformance__canvas__canvas-test.html]
 subsuite = webgl1-core
 [generated/test_conformance__canvas__canvas-zero-size.html]
 subsuite = webgl1-core
 [generated/test_conformance__canvas__draw-static-webgl-to-multiple-canvas-test.html]
 subsuite = webgl1-core
@@ -11341,17 +11340,16 @@ subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__local-variable-shadowing-outer-function.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__non-ascii-comments.vert.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__non-ascii.vert.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__re-compile-re-link.html]
 subsuite = webgl1-ext
-fail-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__glsl__misc__sampler-operand.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__sequence-operator-returns-constant.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shader-precision-format-obeyed.html]
 subsuite = webgl1-ext
 [generated/test_conformance__glsl__misc__shader-struct-scope.html]
 subsuite = webgl1-ext
@@ -11602,17 +11600,16 @@ subsuite = webgl1-core
 [generated/test_conformance__misc__bad-arguments-test.html]
 subsuite = webgl1-core
 skip-if = (os == 'mac') || (os == 'win') || (os == 'linux') || (os == 'android')
 [generated/test_conformance__misc__boolean-argument-conversion.html]
 subsuite = webgl1-core
 skip-if = (os == 'android')
 [generated/test_conformance__misc__delayed-drawing.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__misc__error-reporting.html]
 subsuite = webgl1-core
 [generated/test_conformance__misc__expando-loss.html]
 subsuite = webgl1-core
 [generated/test_conformance__misc__functions-returning-strings.html]
 subsuite = webgl1-core
 [generated/test_conformance__misc__instanceof-test.html]
 subsuite = webgl1-core
@@ -11666,54 +11663,46 @@ skip-if = (os == 'android')
 [generated/test_conformance__more__conformance__quickCheckAPI-G_I.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__conformance__quickCheckAPI-L_S.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__conformance__quickCheckAPI-S_V.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__conformance__webGLArrays.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__bindBuffer.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__bindBufferBadArgs.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__bindFramebufferLeaveNonZero.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__bufferData.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__bufferDataBadArgs.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__bufferSubData.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__bufferSubDataBadArgs.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__copyTexImage2D.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__copyTexImage2DBadArgs.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__copyTexSubImage2D.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__copyTexSubImage2DBadArgs.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__deleteBufferBadArgs.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__drawArrays.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__drawArraysOutOfBounds.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__drawElements.html]
 subsuite = webgl1-core
-skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__more__functions__isTests.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__isTestsBadArgs.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__readPixels.html]
 subsuite = webgl1-core
 [generated/test_conformance__more__functions__readPixelsBadArgs.html]
 subsuite = webgl1-core
@@ -12089,17 +12078,16 @@ subsuite = webgl1-core
 [generated/test_conformance__programs__gl-shader-test.html]
 subsuite = webgl1-core
 [generated/test_conformance__programs__invalid-UTF-16.html]
 subsuite = webgl1-core
 [generated/test_conformance__programs__program-infolog.html]
 subsuite = webgl1-core
 [generated/test_conformance__programs__program-test.html]
 subsuite = webgl1-core
-fail-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__programs__use-program-crash-with-discard-in-fragment-shader.html]
 subsuite = webgl1-core
 [generated/test_conformance__reading__fbo-remains-unchanged-after-read-pixels.html]
 subsuite = webgl1-core
 [generated/test_conformance__reading__read-pixels-pack-alignment.html]
 subsuite = webgl1-core
 [generated/test_conformance__reading__read-pixels-test.html]
 subsuite = webgl1-core
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -2,21 +2,20 @@
 # Modification to this file only take effect after running
 # generate-wrappers-and-manifest.py
 
 # See python/mozbuild/mozbuild/mozinfo.py for incoming data.
 
 ##########
 # android_version strings
 #   https://en.wikipedia.org/wiki/Android_version_history
-#   * Android 'Gingerbread' 2.3-2.3.2: 9
-#   * Android 'Gingerbread' 2.3.3+: 10 ('2.3' slaves)
 #   * Android 'ICS' 4.0-4.0.2: 14 ('4.0' slaves, inactive)
-#   * Android 'ICS' 4.0.3+: 15
-#   * Android 'Jellybean' 4.3: 18 ('4.3' slaves)
+#   * Android 'Jelly Bean' 4.2: 17 ('4.2' slaves)
+#   * Android 'Jelly Bean' 4.3: 18 ('4.3' slaves)
+#   * Android 'Lollipop' 5.0: 21 ('5.0' slaves)
 
 ##########
 # os_version strings
 #   https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
 #   * Windows 7: 6.1
 #   * Windows 8: 6.2
 #   * Windows 8.1: 6.3
 #   * Windows 10: 10.0
@@ -405,21 +404,16 @@ fail-if = (os == 'android')
 fail-if = (os == 'android')
 [generated/test_conformance__extensions__oes-texture-half-float-with-image.html]
 fail-if = (os == 'android')
 [generated/test_conformance__extensions__oes-texture-half-float-with-image-data.html]
 fail-if = (os == 'android')
 # Frequent but intermittent timeout on win7
 skip-if = (os == 'win' && os_version == '6.1')
 
-[generated/test_conformance__canvas__buffer-offscreen-test.html]
-# Causes frequent *blues*: "DMError: Remote Device Error: unable to
-# connect to 127.0.0.1 after 5 attempts" on 'Android 2.3 Opt'.
-skip-if = (os == 'android' && android_version == '10')
-
 [generated/test_conformance__canvas__rapid-resizing.html]
 # Frequent orange crash.
 skip-if = (os == 'android')
 
 [generated/test_conformance__glsl__bugs__long-expressions-should-not-crash.html]
 # Crashes sometimes
 skip-if = (os == 'android')
 [generated/test_conformance__canvas__drawingbuffer-hd-dpi-test.html]
@@ -531,22 +525,16 @@ skip-if = (os == 'android')
 # application crashed [@ jemalloc_crash]
 skip-if = (os == 'android')
 [generated/test_conformance__glsl__bugs__qualcomm-crash.html]
 # application crashed [@ jemalloc_crash]
 skip-if = (os == 'android')
 [generated/test_conformance__glsl__bugs__uniforms-should-not-lose-values.html]
 # application crashed [@ jemalloc_crash]
 skip-if = (os == 'android')
-####################
-# 2.3 failures
-[generated/test_conformance__glsl__misc__re-compile-re-link.html]
-fail-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__programs__program-test.html]
-fail-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__textures__misc__tex-image-with-invalid-data.html]
 skip-if = (os == 'android')
 ####################
 # Timeouts
 [generated/test_conformance__context__context-release-upon-reload.html]
 skip-if = (os == 'android')
 [generated/test_conformance__context__context-release-with-workers.html]
 skip-if = (os == 'android')
@@ -557,37 +545,16 @@ skip-if = (os == 'android') || (os == 'w
 skip-if = (os == 'android')
 
 [generated/test_conformance__glsl__misc__shader-with-non-reserved-words.html]
 fail-if = (os == 'android')
 # (TODO) Generates results after calling finish()
 skip-if = 1
 
 ####################
-# Timeout on 2.3
-[generated/test_conformance__misc__delayed-drawing.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__conformance__webGLArrays.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__functions__bufferData.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__functions__bufferDataBadArgs.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__functions__bufferSubData.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__functions__bufferSubDataBadArgs.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__functions__drawArrays.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__functions__drawArraysOutOfBounds.html]
-skip-if = (os == 'android' && android_version == '10')
-[generated/test_conformance__more__functions__drawElements.html]
-skip-if = (os == 'android' && android_version == '10')
-
-####################
 
 [generated/test_conformance__attribs__gl-bindAttribLocation-aliasing.html]
 # OOM crash
 skip-if = (os == 'android')
 [generated/test_conformance__attribs__gl-bindAttribLocation-matrix.html]
 # OOM crash
 skip-if = (os == 'android')
 [generated/test_conformance__misc__uninitialized-test.html]
--- a/dom/media/mediasource/test/mochitest.ini
+++ b/dom/media/mediasource/test/mochitest.ini
@@ -75,17 +75,16 @@ skip-if = toolkit == 'android' # Not sup
 [test_DurationUpdated_mp4.html]
 skip-if = toolkit == 'android' # Not supported on android
 [test_EndedEvent.html]
 skip-if = android_version == '22' || toolkit == 'android' # bug 1358640, bug 1401090
 [test_EndOfStream.html]
 [test_EndOfStream_mp4.html]
 skip-if = toolkit == 'android' # Not supported on android
 [test_Eviction_mp4.html]
-skip-if = android_version == '15' # Not supported on Android(Bug 1358271)
 [test_ExperimentalAsync.html]
 skip-if = android_version == '22' || toolkit == 'android' # bug 1341519, bug 1401090
 [test_FrameSelection.html]
 skip-if = android_version == '22' || toolkit == 'android' # bug 1341519, bug 1401090
 [test_FrameSelection_mp4.html]
 skip-if = toolkit == 'android' # Not supported on android
 [test_HaveMetadataUnbufferedSeek.html]
 skip-if = android_version == '22' || toolkit == 'android' # bug 1342247, bug 1401090
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -692,44 +692,43 @@ support-files =
   hls/400x300_seg1.ts
   hls/416x243_seg0_5s.ts
   hls/640x480_seg0.ts
   hls/640x480_seg1.ts
   hls/960x720_seg0.ts
   hls/960x720_seg1.ts
 
 [test_access_control.html]
-skip-if = android_version == '15' || android_version == '17' # bug 1292836, android(bug 1232305)
+skip-if = android_version == '17' # bug 1292836, android(bug 1232305)
 [test_arraybuffer.html]
-skip-if = android_version == '15' || android_version == '22' # bug 1308388, android(bug 1232305)
+skip-if = android_version == '22' # bug 1308388, android(bug 1232305)
 [test_aspectratio_mp4.html]
-skip-if = android_version == '15' # android(bug 1232305)
 [test_audio1.html]
 [test_audio2.html]
 [test_audioDocumentTitle.html]
 skip-if = true # bug 475110 - disabled since we don't play Wave files standalone
 [test_autoplay.html]
 [test_autoplay_contentEditable.html]
-skip-if = android_version == '15' || android_version == '17' || android_version == '22' # android(bug 1232305, bug 1232318, bug 1372457)
+skip-if = android_version == '17' || android_version == '22' # android(bug 1232305, bug 1232318, bug 1372457)
 [test_autoplay_policy.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_activation.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_eventdown_activation.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_key_blacklist.html]
 skip-if = android_version == '23' || (verify && debug && (os == 'win')) # bug 1424903
 [test_autoplay_policy_unmute_pauses.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_play_before_loadedmetadata.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_permission.html]
 skip-if = android_version == '23' # bug 1424903
 [test_buffered.html]
-skip-if = android_version == '15' || android_version == '22' # bug 1308388, android(bug 1232305)
+skip-if = android_version == '22' # bug 1308388, android(bug 1232305)
 [test_bug448534.html]
 [test_bug463162.xhtml]
 [test_bug465498.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_bug495145.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_bug495300.html]
 skip-if = toolkit == 'android' # bug 1243801, android(bug 1232305)
@@ -742,39 +741,39 @@ skip-if = android_version == '17' # andr
 [test_bug874897.html]
 skip-if = (android_version == '17') || (android_version == '19' && debug) # android(bug 1232305)
 [test_bug879717.html]
 skip-if = toolkit == 'android' # bug 1285441, android(bug 1232305)
 tags=capturestream
 [test_bug883173.html]
 skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_bug895091.html]
-skip-if = android_version == '15' || (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
+skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 pengl/TextureHostOGL.cpp:645
 tags=webvtt
 [test_bug895305.html]
 skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_bug919265.html]
 skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_bug957847.html]
 skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_bug1018933.html]
 [test_bug1113600.html]
-skip-if = android_version == '15' || android_version == '19' || android_version == '22' # bug 1198168, android(bug 1232305)
+skip-if = android_version == '19' || android_version == '22' # bug 1198168, android(bug 1232305)
 tags=capturestream
 [test_bug1242338.html]
 skip-if = toolkit == 'android' # bug 1306916, bug 1329566, android(bug 1232305)
 [test_bug1242594.html]
 [test_bug1248229.html]
 skip-if = android_version == '17' # bug 1306917, 1323778, android(bug 1232305)
 tags=capturestream
 [test_can_play_type.html]
 skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_can_play_type_mpeg.html]
-skip-if = (android_version == '15') || (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
+skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_can_play_type_no_ogg.html]
 skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_can_play_type_ogg.html]
 skip-if = (android_version == '23' && debug) || (android_version == '25' && debug) # android(bug 1232305)
 [test_chaining.html]
 skip-if = android_version == '17' # android(bug 1232305)
 [test_clone_media_element.html]
 skip-if = toolkit == 'android' # bug 1108558, android(bug 1232305)
@@ -868,29 +867,29 @@ skip-if = toolkit == 'android' # bug 133
 [test_imagecapture.html]
 [test_info_leak.html]
 [test_invalid_reject.html]
 skip-if = android_version == '17' # android(bug 1232305)
 [test_invalid_reject_play.html]
 skip-if = android_version <= '17' # android(bug 1232305)
 [test_invalid_seek.html]
 [test_load.html]
-skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
+skip-if = android_version == '17' # android(bug 1232305)
 fail-if = android_version == '22' # android(bug 1232305)
 [test_load_candidates.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_load_same_resource.html]
 skip-if = toolkit == 'android' # bug 1274802, android(bug 1232305)
 [test_load_source.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_loop.html]
 skip-if = toolkit == 'android' # bug 1242112, android(bug 1232305)
 [test_media_selection.html]
 [test_media_sniffer.html]
-skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
+skip-if = android_version == '17' # android(bug 1232305)
 [test_mediarecorder_avoid_recursion.html]
 skip-if = (os == 'win' && !debug) || (android_version == '17') # bug 1228605, android(bug 1232305)
 tags=msg
 [test_mediarecorder_bitrate.html]
 skip-if = toolkit == 'android' # bug 1297432, android(bug 1232305)
 tags=msg
 [test_mediarecorder_creation.html]
 skip-if = android_version == '17' # android(bug 1232305)
@@ -1064,24 +1063,23 @@ skip-if = android_version == '17' # bug 
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_playback_rate_playpause.html]
 skip-if = toolkit == 'android' # bug 1316501, android(bug 1232305)
 [test_playback_reactivate.html]
 skip-if = toolkit == 'android' # bug 1328904, android(bug 1232305)
 [test_played.html]
 skip-if = toolkit == 'android' # bug 1110922, android(bug 1153860, bug 1232305)
 [test_preload_actions.html]
-skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
+skip-if = android_version == '17' # android(bug 1232305)
 [test_preload_attribute.html]
-skip-if = android_version == '15' && debug # android(bug 1232305)
 [test_preload_suspend.html]
 [test_preserve_playbackrate_after_ui_play.html]
 skip-if = android_version == '17' && debug # android(bug 1232305)
 [test_progress.html]
-skip-if = android_version == '15' || android_version == '17' || android_version == '22' # android(bug 1232305)
+skip-if = android_version == '17' || android_version == '22' # android(bug 1232305)
 [test_reactivate.html]
 skip-if = true # see bug 1319725
 [test_readyState.html]
 [test_referer.html]
 skip-if = android_version == '25' && debug # android(bug 1232305)
 [test_replay_metadata.html]
 skip-if = toolkit == 'android' # bug 1311259, bug 1325994, android(bug 1232305)
 [test_reset_events_async.html]
@@ -1128,17 +1126,17 @@ skip-if = toolkit == 'android' # bug 132
 skip-if = toolkit == 'android' # bug 1321081, android(bug 1232305)
 [test_seek-13.html]
 skip-if = toolkit == 'android' # bug 1299174, android(bug 1232305)
 [test_seek-14.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_seekable1.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_seekLies.html]
-skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
+skip-if = android_version == '17' # android(bug 1232305)
 [test_seekToNextFrame.html]
 skip-if = toolkit == 'android' # bug 1329391, android(bug 1232305)
 tags=seektonextframe
 [test_seek_duration.html]
 [test_source.html]
 skip-if = android_version == '17' # android(bug 1232305)
 [test_source_null.html]
 skip-if = android_version == '17' # android(bug 1232305)
@@ -1156,20 +1154,20 @@ skip-if = toolkit == 'android' # bug 137
 tags=msg capturestream
 [test_streams_element_capture_playback.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 tags=msg capturestream
 [test_streams_element_capture_reset.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 tags=msg capturestream
 [test_streams_gc.html]
-skip-if = android_version == '15' || android_version == '17' || (android_version == '19' && debug) # android(bug 1232305)
+skip-if = android_version == '17' || (android_version == '19' && debug) # android(bug 1232305)
 tags=msg capturestream
 [test_streams_individual_pause.html]
-skip-if = android_version == '15' || android_version == '17' || android_version == '19' # android(bug 1232305)
+skip-if = android_version == '17' || android_version == '19' # android(bug 1232305)
 tags=msg
 [test_streams_srcObject.html]
 skip-if = toolkit == 'android' # bug 1300443, android(bug 1232305)
 tags=msg capturestream
 [test_streams_tracks.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 tags=msg capturestream
 [test_texttrack.html]
@@ -1216,17 +1214,17 @@ skip-if = toolkit == 'android' # android
 skip-if = toolkit == 'android' # bug 1372457
 [test_video_stats_resistfingerprinting.html]
 tags = resistfingerprinting
 [test_videoDocumentTitle.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_VideoPlaybackQuality.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_VideoPlaybackQuality_disabled.html]
-skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
+skip-if = android_version == '17' # android(bug 1232305)
 [test_volume.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_vttparser.html]
 skip-if = android_version == '22' # android(bug 1368010)
 tags = webvtt
 [test_webvtt_empty_displaystate.html]
 skip-if = android_version == '17' || android_version == '22' # android(bug 1368010, bug 1372457)
 tags = webvtt
@@ -1234,21 +1232,21 @@ tags = webvtt
 skip-if = android_version == '22' # android(bug 1368010)
 tags = webvtt
 
 # The tests below contain backend-specific tests. Write backend independent
 # tests rather than adding to this list.
 [test_can_play_type_webm.html]
 skip-if = toolkit == 'android' # android(bug 1232305)
 [test_can_play_type_wave.html]
-skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
+skip-if = android_version == '17' # android(bug 1232305)
 [test_fragment_noplay.html]
-skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
+skip-if = android_version == '17' # android(bug 1232305)
 [test_fragment_play.html]
-skip-if = android_version == '15' || android_version == '17' # bug 1335520, bug 1209318, android(bug 1232305)
+skip-if = android_version == '17' # bug 1335520, bug 1209318, android(bug 1232305)
 
 [test_background_video_cancel_suspend_taint.html]
 skip-if = toolkit == 'android' # bug 1346705
 tags = suspend
 [test_background_video_cancel_suspend_visible.html]
 skip-if = toolkit == 'android' # bug 1346705
 tags = suspend
 [test_background_video_no_suspend_disabled.html]
@@ -1291,17 +1289,17 @@ skip-if = toolkit == 'android' # android
 skip-if = (os == 'win' || android_version == '19') # bug 1374189
 
 [test_video_gzip_encoding.html]
 
 [test_playback_hls.html]
 # HLS is only supported on Fennec with API level >= 16
 # TODO: This test is similar to test_playback.html, will remove the
 # redundant code once test_playback.html is enabled on Fennec.
-skip-if = toolkit != 'android' || android_version < '16'
+skip-if = toolkit != 'android'
 tags = hls
 
 [test_hls_player_independency.html]
 # There's a limit for creating decoder when API lever < 18(Bug 1278574)
 # We could skip the test in that case as we cannot play 2 video at a time.
 skip-if = toolkit != 'android' || android_version < '18'
 tags = hls
 
--- a/dom/media/test/test_eme_request_notifications.html
+++ b/dom/media/test/test_eme_request_notifications.html
@@ -36,37 +36,35 @@ function Test(test) {
   });
 
   p.then(() => navigator.requestMediaKeySystemAccess(test.keySystem, gCencMediaKeySystemConfig))
    .then((keySystemAccess) => keySystemAccess.createMediaKeys());
 
   return res;
 }
 
-const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
-
 var tests = [
   {
     keySystem: CLEARKEY_KEYSYSTEM,
     expectedStatus: 'cdm-created',
     prefs: [["media.eme.enabled", false]]
   },
   {
     keySystem: "com.widevine.alpha",
     expectedStatus: 'api-disabled',
     prefs: [["media.eme.enabled", false]]
   },
   {
     keySystem: "com.widevine.alpha",
-    expectedStatus: (isWinXP ? 'cdm-not-supported' : 'cdm-disabled'),
+    expectedStatus: 'cdm-disabled',
     prefs: [["media.eme.enabled", true], ["media.gmp-widevinecdm.enabled", false]]
   },
   {
     keySystem: "com.widevine.alpha",
-    expectedStatus: (isWinXP ? 'cdm-not-supported' : 'cdm-not-installed'),
+    expectedStatus: 'cdm-not-installed',
     prefs: [["media.eme.enabled", true], , ["media.gmp-widevinecdm.enabled", true]]
   },
   {
     keySystem: CLEARKEY_KEYSYSTEM,
     expectedStatus: 'cdm-created',
     prefs: [["media.eme.enabled", true]]
   }
 ];
--- a/dom/media/tests/mochitest/head.js
+++ b/dom/media/tests/mochitest/head.js
@@ -1135,30 +1135,15 @@ class VideoStreamHelper {
         }, { offsetX, offsetY, cancel: wait(time, "timeout") });
       ok(false, "Frame changed within " + time/1000 + " seconds");
     } catch (e) {
       is(e, "timeout", "Frame shouldn't change for " + time/1000 + " seconds");
     }
   }
 }
 
-
-function IsMacOSX10_6orOlder() {
-  if (navigator.platform.indexOf("Mac") !== 0) {
-    return false;
-  }
-
-  var version = Cc["@mozilla.org/system-info;1"]
-      .getService(Ci.nsIPropertyBag2)
-      .getProperty("version");
-  // the next line is correct: Mac OS 10.6 corresponds to Darwin version 10.x !
-  // Mac OS 10.7 is Darwin version 11.x. the |version| string we've got here
-  // is the Darwin version.
-  return (parseFloat(version) < 11.0);
-}
-
 (function(){
   var el = document.createElement("link");
   el.rel = "stylesheet";
   el.type = "text/css";
   el.href= "/tests/SimpleTest/test.css";
   document.head.appendChild(el);
 }());
--- a/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html
@@ -62,22 +62,16 @@
     await verifyAround(screenSizeSq * 3 / 4, screenSizeSq * 3 / 4, downright);
   };
 
   /**
    * Run a test to verify that we can complete a start and stop media playback
    * cycle for a screenshare MediaStream on a video HTMLMediaElement.
    */
   runTest(async function () {
-    const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
-    if (IsMacOSX10_6orOlder() || isWinXP) {
-        ok(true, "Screensharing disabled for OSX10.6 and WinXP");
-        return;
-    }
-
     await pushPrefs(
       ["full-screen-api.enabled", true],
       ["full-screen-api.unprefix.enabled", true],
       ["full-screen-api.allow-trusted-requests-only", false],
       ["full-screen-api.transition-duration.enter", "0 0"],
       ["full-screen-api.transition-duration.leave", "0 0"],
     );
 
--- a/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html
@@ -12,21 +12,16 @@
   });
   /**
    * Run a test to verify that we can complete a start and stop media playback
    * cycle for a tabshare LocalMediaStream on a video HTMLMediaElement.
    *
    * Additionally, exercise applyConstraints code for tabshare viewport offset.
    */
   runTest(function () {
-    const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
-    if (IsMacOSX10_6orOlder() || isWinXP) {
-        ok(true, "Screensharing disabled for OSX10.6 and WinXP");
-        return;
-    }
     var testVideo = createMediaElement('video', 'testVideo');
 
     return Promise.resolve()
       .then(() => pushPrefs(["media.getusermedia.browser.enabled", true]))
       .then(() => getUserMedia({
         video: { mediaSource: "browser",
                  scrollWithPage: true },
         fake: false
--- a/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html
@@ -10,21 +10,16 @@
     title: "getUserMedia Basic Windowshare Test",
     bug: "1038926"
   });
   /**
    * Run a test to verify that we can complete a start and stop media playback
    * cycle for an screenshare LocalMediaStream on a video HTMLMediaElement.
    */
   runTest(function () {
-    const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
-    if (IsMacOSX10_6orOlder() || isWinXP) {
-        ok(true, "Screensharing disabled for OSX10.6 and WinXP");
-        return;
-    }
     var testVideo = createMediaElement('video', 'testVideo');
     var constraints = {
       video: {
          mozMediaSource: "window",
          mediaSource: "window"
       },
       fake: false
     };
--- a/dom/media/tests/mochitest/test_getUserMedia_scarySources.html
+++ b/dom/media/tests/mochitest/test_getUserMedia_scarySources.html
@@ -24,22 +24,16 @@ let getDevices = async constraints => {
   let window = Services.wm.getOuterWindowWithId(windowID);
   let devices = await new Promise((resolve, reject) =>
       window.navigator.mozGetUserMediaDevices({}, resolve, reject,
                                               innerWindowID, callID));
   return devices.map(SpecialPowers.wrapCallback(d => d.QueryInterface(Ci.nsIMediaDevice)));
 };
 
 runTest(async () => {
-  const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
-  if (IsMacOSX10_6orOlder() || isWinXP) {
-    ok(true, "Screensharing disabled for OSX10.6 and WinXP");
-    return;
-  }
-
   await pushPrefs(["media.navigator.permission.disabled", true],
                   ["media.navigator.permission.fake", true],
                   ["media.navigator.permission.force", true]);
   let devices = await getDevices({video: { mediaSource: "window" }});
   ok(devices.length, "Found one or more windows.");
   devices = devices.filter(d => d.scary);
   ok(devices.length, "Found one or more scary windows (our own counts).");
   devices.filter(d => d.name.includes("MochiTest"));
--- a/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html
@@ -8,22 +8,16 @@
 <script type="application/javascript">
   createHTML({
     bug: "1039666",
     title: "Basic screenshare-only peer connection"
   });
 
   var test;
   runNetworkTest(function (options) {
-    const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
-    if (IsMacOSX10_6orOlder() || isWinXP) {
-        ok(true, "Screensharing disabled for OSX10.6 and WinXP");
-        SimpleTest.finish();
-        return;
-    }
     test = new PeerConnectionTest(options);
     var constraints = {
       video: {
          mozMediaSource: "screen",
          mediaSource: "screen"
       },
       fake: false
     };
--- a/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html
+++ b/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html
@@ -8,22 +8,16 @@
 <script type="application/javascript">
   createHTML({
     bug: "1038926",
     title: "Basic windowshare-only peer connection"
   });
 
   var test;
   runNetworkTest(function (options) {
-    const isWinXP = navigator.userAgent.includes("Windows NT 5.1");
-    if (IsMacOSX10_6orOlder() || isWinXP) {
-        ok(true, "Screensharing disabled for OSX10.6 and WinXP");
-        SimpleTest.finish();
-        return;
-    }
     test = new PeerConnectionTest(options);
     var constraints = {
       video: {
          mozMediaSource: "window",
          mediaSource: "window"
       },
       fake: false
     };
--- a/netwerk/test/unit/test_udp_multicast.js
+++ b/netwerk/test/unit/test_udp_multicast.js
@@ -11,17 +11,16 @@ const ADDRESS_TEST1 = "224.0.0.200";
 const ADDRESS_TEST2 = "224.0.0.201";
 const ADDRESS_TEST3 = "224.0.0.202";
 const ADDRESS_TEST4 = "224.0.0.203";
 
 const TIMEOUT = 2000;
 
 const ua = Cc["@mozilla.org/network/protocol;1?name=http"]
            .getService(Ci.nsIHttpProtocolHandler).userAgent;
-const isWinXP = ua.includes("Windows NT 5.1");
 
 var gConverter;
 
 function run_test() {
   setup();
   run_next_test();
 }
 
@@ -80,32 +79,27 @@ add_test(() => {
   let socket = createSocketAndJoin(ADDRESS_TEST2);
   socket.multicastLoopback = false;
   sendPing(socket, ADDRESS_TEST2).then(
     () => do_throw("Loopback disabled, but still got a packet"),
     run_next_test
   );
 });
 
-// The following multicast interface test doesn't work on Windows XP, as it
-// appears to allow packets no matter what address is given, so we'll skip the
-// test there.
-if (!isWinXP) {
-  add_test(() => {
-    info("Changing multicast interface");
-    let socket = createSocketAndJoin(ADDRESS_TEST3);
-    socket.multicastInterface = "127.0.0.1";
-    sendPing(socket, ADDRESS_TEST3).then(
-      () => do_throw("Changed interface, but still got a packet"),
-      run_next_test
-    );
-  });
+add_test(() => {
+  info("Changing multicast interface");
+  let socket = createSocketAndJoin(ADDRESS_TEST3);
+  socket.multicastInterface = "127.0.0.1";
+  sendPing(socket, ADDRESS_TEST3).then(
+    () => do_throw("Changed interface, but still got a packet"),
+    run_next_test
+  );
+});
 
 add_test(() => {
   info("Leaving multicast group");
   let socket = createSocketAndJoin(ADDRESS_TEST4);
   socket.leaveMulticast(ADDRESS_TEST4);
   sendPing(socket, ADDRESS_TEST4).then(
     () => do_throw("Left group, but still got a packet"),
     run_next_test
   );
 });
-}
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -881,16 +881,21 @@ class MachCommandConditions(object):
     @staticmethod
     def is_android(cls):
         """Must have an Android build."""
         if hasattr(cls, 'substs'):
             return cls.substs.get('MOZ_WIDGET_TOOLKIT') == 'android'
         return False
 
     @staticmethod
+    def is_firefox_or_android(cls):
+        """Must have a Firefox or Android build."""
+        return MachCommandConditions.is_firefox(cls) or MachCommandConditions.is_android(cls)
+
+    @staticmethod
     def is_hg(cls):
         """Must have a mercurial source checkout."""
         return getattr(cls, 'substs', {}).get('VCS_CHECKOUT_TYPE') == 'hg'
 
     @staticmethod
     def is_git(cls):
         """Must have a git source checkout."""
         return getattr(cls, 'substs', {}).get('VCS_CHECKOUT_TYPE') == 'git'
--- a/testing/marionette/mach_commands.py
+++ b/testing/marionette/mach_commands.py
@@ -16,21 +16,16 @@ from mach.decorators import (
 )
 
 from mozbuild.base import (
     MachCommandBase,
     MachCommandConditions as conditions,
 )
 
 
-def is_firefox_or_android(cls):
-    """Must have Firefox build or Android build."""
-    return conditions.is_firefox(cls) or conditions.is_android(cls)
-
-
 def create_parser_tests():
     from marionette_harness.runtests import MarionetteArguments
     from mozlog.structured import commandline
     parser = MarionetteArguments()
     commandline.add_logging_group(parser)
     return parser
 
 
@@ -69,17 +64,17 @@ def run_marionette(tests, binary=None, t
         return 0
 
 
 @CommandProvider
 class MarionetteTest(MachCommandBase):
     @Command("marionette-test",
              category="testing",
              description="Remote control protocol to Gecko, used for functional UI tests and browser automation.",
-             conditions=[is_firefox_or_android],
+             conditions=[conditions.is_firefox_or_android],
              parser=create_parser_tests,
              )
     def marionette_test(self, tests, **kwargs):
         if "test_objects" in kwargs:
             tests = []
             for obj in kwargs["test_objects"]:
                 tests.append(obj["file_relpath"])
             del kwargs["test_objects"]
@@ -94,17 +89,17 @@ class Marionette(MachCommandBase):
 
     @property
     def srcdir(self):
         return os.path.join(self.topsrcdir, "testing/marionette")
 
     @Command("marionette",
              category="misc",
              description="Remote control protocol to Gecko, used for functional UI tests and browser automation.",
-             conditions=[is_firefox_or_android],
+             conditions=[conditions.is_firefox_or_android],
              )
     def marionette(self):
         self.parser.print_usage()
         return 1
 
     @SubCommand("marionette", "test",
                 description="Run browser automation tests based on Marionette harness.",
                 parser=create_parser_tests,
--- a/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py
+++ b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py
@@ -69,16 +69,36 @@ def get_disk_io_counters():
         if io_counters is None:
             return PsutilStub().disk_io_counters()
     except RuntimeError:
         io_counters = PsutilStub().disk_io_counters()
 
     return io_counters
 
 
+def _poll(pipe, poll_interval=0.1):
+    """Wrap multiprocessing.Pipe.poll to hide POLLERR and POLLIN
+    exceptions.
+
+    multiprocessing.Pipe is not actually a pipe on at least Linux.
+    That has an effect on the expected outcome of reading from it when
+    the other end of the pipe dies, leading to possibly hanging on revc()
+    below.
+    """
+    try:
+        return pipe.poll(poll_interval)
+    except Exception:
+        # Poll might throw an exception even though there's still
+        # data to read. That happens when the underlying system call
+        # returns both POLLERR and POLLIN, but python doesn't tell us
+        # about it. So assume there is something to read, and we'll
+        # get an exception when trying to read the data.
+        return True
+
+
 def _collect(pipe, poll_interval):
     """Collects system metrics.
 
     This is the main function for the background process. It collects
     data then forwards it on a pipe until told to stop.
     """
 
     data = []
@@ -93,17 +113,17 @@ def _collect(pipe, poll_interval):
     swap_last = psutil.swap_memory()
     psutil.cpu_percent(None, True)
 
     sin_index = swap_last._fields.index('sin')
     sout_index = swap_last._fields.index('sout')
 
     sleep_interval = poll_interval
 
-    while not pipe.poll(sleep_interval):
+    while not _poll(pipe, poll_interval=sleep_interval):
         io = get_disk_io_counters()
         cpu_times = psutil.cpu_times(True)
         cpu_percent = psutil.cpu_percent(None, True)
         virt_mem = psutil.virtual_memory()
         swap_mem = psutil.swap_memory()
         measured_end_time = time.time()
 
         # TODO Does this wrap? At 32 bits? At 64 bits?
@@ -253,17 +273,17 @@ class SystemResourceMonitor(object):
         self._io_len = len(io)
         self._virt_type = type(virt)
         self._virt_len = len(virt)
         self._swap_type = type(swap)
         self._swap_len = len(swap)
 
         self._pipe, child_pipe = multiprocessing.Pipe(True)
 
-        self._process = multiprocessing.Process(None, _collect,
+        self._process = multiprocessing.Process(target=_collect,
                                                 args=(child_pipe, poll_interval))
 
     def __del__(self):
         if self._running:
             self._pipe.send(('terminate',))
             self._process.join()
 
     # Methods to control monitoring.
@@ -303,31 +323,17 @@ class SystemResourceMonitor(object):
 
         self.measurements = []
 
         # The child process will send each data sample over the pipe
         # as a separate data structure. When it has finished sending
         # samples, it sends a special "done" message to indicate it
         # is finished.
 
-        # multiprocessing.Pipe is not actually a pipe on at least Linux.  that
-        # has an effect on the expected outcome of reading from it when the
-        # other end of the pipe dies, leading to possibly hanging on revc()
-        # below. So we must poll().
-        def poll():
-            try:
-                return self._pipe.poll(0.1)
-            except Exception:
-                # Poll might throw an exception even though there's still
-                # data to read. That happens when the underlying system call
-                # returns both POLLERR and POLLIN, but python doesn't tell us
-                # about it. So assume there is something to read, and we'll
-                # get an exception when trying to read the data.
-                return True
-        while poll():
+        while _poll(self._pipe, poll_interval=0.1):
             try:
                 start_time, end_time, io_diff, cpu_diff, cpu_percent, virt_mem, \
                     swap_mem = self._pipe.recv()
             except Exception:
                 # Let's assume we're done here
                 break
 
             # There should be nothing after the "done" message so
--- a/testing/mozharness/mach_commands.py
+++ b/testing/mozharness/mach_commands.py
@@ -178,13 +178,13 @@ class MozharnessRunner(MozbuildObject):
         rv = subprocess.call(cmd, cwd=os.path.dirname(script))
         return rv
 
 
 @CommandProvider
 class MozharnessCommands(MachCommandBase):
     @Command('mozharness', category='testing',
              description='Run tests using mozharness.',
-             conditions=[conditions.is_firefox],
+             conditions=[conditions.is_firefox_or_android],
              parser=get_parser)
     def mozharness(self, **kwargs):
         runner = self._spawn(MozharnessRunner)
         return runner.run_suite(kwargs.pop("suite_name")[0], **kwargs)
--- a/testing/web-platform/mach_commands.py
+++ b/testing/web-platform/mach_commands.py
@@ -18,21 +18,16 @@ from mozbuild.base import (
 from mach.decorators import (
     CommandProvider,
     Command,
 )
 
 from mach_commands_base import WebPlatformTestsRunner, create_parser_wpt
 
 
-def is_firefox_or_android(cls):
-    """Must have Firefox build or Android build."""
-    return conditions.is_firefox(cls) or conditions.is_android(cls)
-
-
 class WebPlatformTestsRunnerSetup(MozbuildObject):
     default_log_type = "mach"
 
     def kwargs_common(self, kwargs):
         build_path = os.path.join(self.topobjdir, 'build')
         here = os.path.split(__file__)[0]
         tests_src_path = os.path.join(here, "tests")
         if build_path not in sys.path:
@@ -353,17 +348,17 @@ def create_parser_manifest_download():
 
 @CommandProvider
 class MachCommands(MachCommandBase):
     def setup(self):
         self._activate_virtualenv()
 
     @Command("web-platform-tests",
              category="testing",
-             conditions=[is_firefox_or_android],
+             conditions=[conditions.is_firefox_or_android],
              parser=create_parser_wpt)
     def run_web_platform_tests(self, **params):
         self.setup()
         if conditions.is_android(self) and params["product"] != "fennec":
             if params["product"] is None:
                 params["product"] = "fennec"
             else:
                 raise ValueError("Must specify --product=fennec in Android environment.")
@@ -375,17 +370,17 @@ class MachCommands(MachCommandBase):
         self.wpt_manifest_download(**params)
         params["manifest_update"] = False
         wpt_setup = self._spawn(WebPlatformTestsRunnerSetup)
         wpt_runner = WebPlatformTestsRunner(wpt_setup)
         return wpt_runner.run(**params)
 
     @Command("wpt",
              category="testing",
-             conditions=[is_firefox_or_android],
+             conditions=[conditions.is_firefox_or_android],
              parser=create_parser_wpt)
     def run_wpt(self, **params):
         return self.run_web_platform_tests(**params)
 
     @Command("web-platform-tests-update",
              category="testing",
              parser=create_parser_update)
     def update_web_platform_tests(self, **params):
--- a/toolkit/components/mozintl/mozIMozIntl.idl
+++ b/toolkit/components/mozintl/mozIMozIntl.idl
@@ -46,29 +46,38 @@ interface mozIMozIntl : nsISupports
    *
    * 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 = getLanguageDisplayNames(["pl"], ["US", "CA", "MX"]);
+   *   let regs = getRegionDisplayNames(["pl"], ["US", "CA", "MX"]);
    *   regs === ["Stany Zjednoczone", "Kanada", "Meksyk"]
    */
   jsval getRegionDisplayNames(in jsval locales, in jsval regionCodes);
 
   /**
    * Returns a list of locale names formatted for display.
    *
    * Example:
-   *   let locs = getLanguageDisplayNames(["pl"], ["sr-RU", "es-MX", "fr-CA"]);
+   *   let locs = getLocaleDisplayNames(["pl"], ["sr-RU", "es-MX", "fr-CA"]);
    *   locs === ["Serbski (Rosja)", "Hiszpański (Meksyk)", "Francuski (Kanada)"]
    */
   jsval getLocaleDisplayNames(in jsval locales, in jsval localeCodes);
 
   readonly attribute jsval DateTimeFormat;
   readonly attribute jsval NumberFormat;
   readonly attribute jsval Collator;
   readonly attribute jsval PluralRules;
--- a/toolkit/components/mozintl/mozIntl.js
+++ b/toolkit/components/mozintl/mozIntl.js
@@ -194,29 +194,54 @@ 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");
     }
-    const regionBundle = Services.strings.createBundle(
-          "chrome://global/locale/regionNames.properties");
+
+    if (!this._cache.hasOwnProperty("regionBundle")) {
+      const regionBundle = Services.strings.createBundle(
+        "chrome://global/locale/regionNames.properties");
+      this._cache.regionBundle = regionBundle;
+    }
 
     return regionCodes.map(regionCode => {
       if (typeof regionCode !== "string") {
         throw new TypeError("All region codes must be strings.");
       }
       try {
-        return regionBundle.GetStringFromName(regionCode.toLowerCase());
+        return this._cache.regionBundle.GetStringFromName(regionCode.toLowerCase());
       } catch (e) {
         return regionCode.toUpperCase(); // Fall back to raw region subtag.
       }
     });
   }
 
   getLocaleDisplayNames(locales, localeCodes) {
     if (locales !== undefined) {
--- a/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js
+++ b/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js
@@ -1,15 +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 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();
@@ -76,8 +77,15 @@ add_test(function test_region_only() {
 add_test(function test_invalid_regions() {
   deepEqual(gRegDN(["2"]), ["2"]);
   deepEqual(gRegDN([""]), [""]);
   Assert.throws(() => gRegDN([2]), /All region codes must be strings/);
   Assert.throws(() => gRegDN([{}]), /All region codes must be strings/);
   Assert.throws(() => gRegDN([true]), /All region codes must be strings/);
   run_next_test();
 });
+
+add_test(function test_region() {
+  let regions = gReg(undefined);
+  equal(regions[Symbol.toStringTag], "Map", "Check type is Map");
+  equal(regions.get("US"), "United States", "Check US name");
+  run_next_test();
+});
--- a/widget/tests/test_bug596600.xul
+++ b/widget/tests/test_bug596600.xul
@@ -144,21 +144,18 @@ function test2() {
         ok(!gIFrame.matches(":hover"), "iframe shouldn't be hovered");
         ok(!box.matches(":hover"), "Box shouldn't be hovered");
         // Re-activate it.
         changeFocusAndAwaitSyntheticMouse(function () {
           ok(gIFrame.matches(":hover"), "iframe should be hovered");
           ok(box.matches(":hover"), "Box should be hovered");
           // Unhover box and iframe by moving the mouse outside the window.
           moveMouseTo(0, 150, function () {
-            const isOSXSnowLeopard = navigator.userAgent.includes("Mac OS X 10.6");
-            if (!isOSXSnowLeopard) {
-              ok(!gIFrame.matches(":hover"), "iframe shouldn't be hovered");
-              ok(!box.matches(":hover"), "box shouldn't be hovered");
-            }
+            ok(!gIFrame.matches(":hover"), "iframe shouldn't be hovered");
+            ok(!box.matches(":hover"), "box shouldn't be hovered");
             finalize();
           });
         }, gLeftWindow, box);
       }, gRightWindow, box);
     }, gLeftWindow, box);
   });
 }