diff --git a/accessible/tests/mochitest/states/test_tree.xul b/accessible/tests/mochitest/states/test_tree.xul index 30f17c77d80b600b14d198d3aa78bab4ade00898..5aefabf37a2df6298de4bcdd1ad9bbb7171e7138 100644 --- a/accessible/tests/mochitest/states/test_tree.xul +++ b/accessible/tests/mochitest/states/test_tree.xul @@ -95,13 +95,8 @@ 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> diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index a104abd5ca3ca0f7b9a39261ce5d3f37c982863b..c50b0250cc2ccdbc596aca2ed7db71181d6c8831 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1684,8 +1684,7 @@ 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 diff --git a/browser/components/payments/content/paymentDialogFrameScript.js b/browser/components/payments/content/paymentDialogFrameScript.js index 024618ddd6d531186cd1585ac591a183f81a8f9c..ee0dfb8b80105b66f4234ab2fbebaef702ac789f 100644 --- a/browser/components/payments/content/paymentDialogFrameScript.js +++ b/browser/components/payments/content/paymentDialogFrameScript.js @@ -74,7 +74,7 @@ let PaymentFrameScript = { 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); diff --git a/browser/components/payments/content/paymentDialogWrapper.js b/browser/components/payments/content/paymentDialogWrapper.js index 7f1c6f6232044e262266885556f7c92a1f51686c..1f71ace0afd57d286fc89aeba170ad967c37bb12 100644 --- a/browser/components/payments/content/paymentDialogWrapper.js +++ b/browser/components/payments/content/paymentDialogWrapper.js @@ -136,6 +136,7 @@ var paymentDialogWrapper = { 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, diff --git a/browser/components/payments/res/containers/address-form.js b/browser/components/payments/res/containers/address-form.js index a9a31f46f9e87e2b0cde6c0c20f5fe263121956f..7b7bb51e8ed94c78ab148a40308b8fbc46414c73 100644 --- a/browser/components/payments/res/containers/address-form.js +++ b/browser/components/payments/res/containers/address-form.js @@ -88,7 +88,7 @@ export default class AddressForm extends PaymentStateSubscriberMixin(PaymentRequ }, 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, diff --git a/browser/components/payments/res/unprivileged-fallbacks.js b/browser/components/payments/res/unprivileged-fallbacks.js index 6a08e3bb07d3b2ade9159d811f781bff503745d8..c7ac612bc6c60bf3663e3827b5beec8d1b235e75 100644 --- a/browser/components/payments/res/unprivileged-fallbacks.js +++ b/browser/components/payments/res/unprivileged-fallbacks.js @@ -50,10 +50,12 @@ var PaymentDialogUtils = { 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: [ @@ -77,9 +79,11 @@ var PaymentDialogUtils = { } 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"}, @@ -89,7 +93,7 @@ var PaymentDialogUtils = { ], // 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() { diff --git a/browser/components/payments/test/browser/head.js b/browser/components/payments/test/browser/head.js index 078a4a85386260652968339b439eb5162d68dedc..1f0243829fd96c9c5acefefa450eab3142407fa5 100644 --- a/browser/components/payments/test/browser/head.js +++ b/browser/components/payments/test/browser/head.js @@ -387,7 +387,7 @@ async function navigateToAddAddressPage(frame, aOptions = { 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; diff --git a/browser/extensions/formautofill/FormAutofill.jsm b/browser/extensions/formautofill/FormAutofill.jsm index 96855168c2772742c473f6c3fb212ba13a9d321d..7725c3f171945fc7a9a57956147a09dfa4a4ed77 100644 --- a/browser/extensions/formautofill/FormAutofill.jsm +++ b/browser/extensions/formautofill/FormAutofill.jsm @@ -7,6 +7,7 @@ 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"; @@ -73,3 +74,7 @@ XPCOMUtils.defineLazyPreferenceGetter(FormAutofill, XPCOMUtils.defineLazyPreferenceGetter(FormAutofill, "supportedCountries", SUPPORTED_COUNTRIES_PREF, null, null, val => val.split(",")); + +XPCOMUtils.defineLazyGetter(FormAutofill, "countries", () => { + return Services.intl.getRegions(undefined); +}); diff --git a/browser/extensions/formautofill/FormAutofillHandler.jsm b/browser/extensions/formautofill/FormAutofillHandler.jsm index 8e622bac798543c322b571abaf2c1c010a5bf313..edf4bd81945a33208f24caa7c1b43cb7cce5d795 100644 --- a/browser/extensions/formautofill/FormAutofillHandler.jsm +++ b/browser/extensions/formautofill/FormAutofillHandler.jsm @@ -555,6 +555,13 @@ class FormAutofillAddressSection extends FormAutofillSection { } 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)) { diff --git a/browser/extensions/formautofill/FormAutofillParent.jsm b/browser/extensions/formautofill/FormAutofillParent.jsm index 57c558a6b566d02c9dbb8ea4cfb5f4b433a6ed1c..bbafb63b5bb5b829b58ffe4dd9118e16bef306d6 100644 --- a/browser/extensions/formautofill/FormAutofillParent.jsm +++ b/browser/extensions/formautofill/FormAutofillParent.jsm @@ -54,6 +54,7 @@ const { } = FormAutofill; const { + ADDRESSES_COLLECTION_NAME, CREDITCARDS_COLLECTION_NAME, } = FormAutofillUtils; @@ -345,9 +346,17 @@ FormAutofillParent.prototype = { 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); diff --git a/browser/extensions/formautofill/FormAutofillStorage.jsm b/browser/extensions/formautofill/FormAutofillStorage.jsm index 21f72761b2558629c0db24ef05ca791a57982280..84b08595f9062b48c05a579d7d834c565480dc2b 100644 --- a/browser/extensions/formautofill/FormAutofillStorage.jsm +++ b/browser/extensions/formautofill/FormAutofillStorage.jsm @@ -22,6 +22,7 @@ * family-name, * organization, // Company * street-address, // (Multiline) + * address-level3, // Suburb/Sublocality * address-level2, // City/Town * address-level1, // Province (Standardized code if possible) * postal-code, @@ -165,6 +166,7 @@ const VALID_ADDRESS_FIELDS = [ "family-name", "organization", "street-address", + "address-level3", "address-level2", "address-level1", "postal-code", @@ -1297,7 +1299,7 @@ class Addresses extends AutofillRecords { } _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"]; } diff --git a/browser/extensions/formautofill/FormAutofillUtils.jsm b/browser/extensions/formautofill/FormAutofillUtils.jsm index dc44a9fca2668a53580605750ede56550e5ba0cb..9896ccefea4f543e025343f40f53af144a0e921e 100644 --- a/browser/extensions/formautofill/FormAutofillUtils.jsm +++ b/browser/extensions/formautofill/FormAutofillUtils.jsm @@ -72,7 +72,12 @@ let AddressDataLoader = { 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; @@ -270,6 +275,7 @@ this.FormAutofillUtils = { 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) @@ -371,10 +377,10 @@ this.FormAutofillUtils = { * 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) { @@ -402,6 +408,9 @@ this.FormAutofillUtils = { * @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); @@ -414,6 +423,9 @@ this.FormAutofillUtils = { * @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); @@ -464,6 +476,7 @@ this.FormAutofillUtils = { A: "street-address", S: "address-level1", C: "address-level2", + D: "address-level3", Z: "postal-code", n: "newLine", }; @@ -496,12 +509,20 @@ this.FormAutofillUtils = { * @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) { @@ -776,18 +797,27 @@ this.FormAutofillUtils = { * @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, }; }, diff --git a/browser/extensions/formautofill/ProfileAutoCompleteResult.jsm b/browser/extensions/formautofill/ProfileAutoCompleteResult.jsm index cc76daed226250674ffd4373b9fbeae841994603..522be57e3784020f73e26869c6dcf96481c3f66f 100644 --- a/browser/extensions/formautofill/ProfileAutoCompleteResult.jsm +++ b/browser/extensions/formautofill/ProfileAutoCompleteResult.jsm @@ -220,6 +220,7 @@ class AddressResult extends ProfileAutoCompleteResult { 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) diff --git a/browser/extensions/formautofill/addressmetadata/addressReferences.js b/browser/extensions/formautofill/addressmetadata/addressReferences.js index 794c9b8c07246691ac533428e679f02063169a8d..b378b7754de622dce90359bbbca33649c5c7f64e 100644 --- a/browser/extensions/formautofill/addressmetadata/addressReferences.js +++ b/browser/extensions/formautofill/addressmetadata/addressReferences.js @@ -10,14 +10,265 @@ // 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"}, }; diff --git a/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js b/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js index 04bc62af33ef9155fcf8d3d7c6f2805342d6ed5a..68a8ea7aed3157eeae3c5c5282b27bdccdbefc06 100644 --- a/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js +++ b/browser/extensions/formautofill/addressmetadata/addressReferencesExt.js @@ -7,7 +7,7 @@ "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 diff --git a/browser/extensions/formautofill/content/autofillEditForms.js b/browser/extensions/formautofill/content/autofillEditForms.js index 37ad5957f409e8962433e9b089fef36623a02133..610a349a775825cbed0ebb28b12b6ad1400c8918 100644 --- a/browser/extensions/formautofill/content/autofillEditForms.js +++ b/browser/extensions/formautofill/content/autofillEditForms.js @@ -122,16 +122,19 @@ class EditAddress extends EditAutofillForm { * @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(); @@ -149,7 +152,7 @@ class EditAddress extends EditAutofillForm { this._record = record; if (!record) { record = { - country: this.supportedCountries.find(supported => supported == this.DEFAULT_REGION), + country: this.DEFAULT_REGION, }; } super.loadRecord(record); @@ -205,11 +208,15 @@ class EditAddress extends EditAutofillForm { */ 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; @@ -228,6 +235,7 @@ class EditAddress extends EditAutofillForm { "name", "organization", "street-address", + "address-level3", "address-level2", "address-level1", "postal-code", @@ -273,10 +281,12 @@ class EditAddress extends EditAutofillForm { 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); diff --git a/browser/extensions/formautofill/content/editAddress.xhtml b/browser/extensions/formautofill/content/editAddress.xhtml index b60263b7ff6441daee2a0ef1a82367ff4094ad6b..2e01e8728a50d898f1c5a5071519d625aa252021 100644 --- a/browser/extensions/formautofill/content/editAddress.xhtml +++ b/browser/extensions/formautofill/content/editAddress.xhtml @@ -44,9 +44,13 @@ <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"/> @@ -81,7 +85,7 @@ let { DEFAULT_REGION, - supportedCountries, + countries, } = FormAutofill; let { getFormFormat, @@ -90,12 +94,12 @@ 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, }); diff --git a/browser/extensions/formautofill/locales/en-US/formautofill.properties b/browser/extensions/formautofill/locales/en-US/formautofill.properties index ed76f3802012a75404e571941b935d187fc0c179..5dd57459b77d08ec2722e2ff06a5d7a7b36e9787 100644 --- a/browser/extensions/formautofill/locales/en-US/formautofill.properties +++ b/browser/extensions/formautofill/locales/en-US/formautofill.properties @@ -119,11 +119,54 @@ 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 diff --git a/browser/extensions/formautofill/skin/shared/editAddress.css b/browser/extensions/formautofill/skin/shared/editAddress.css index db6903a09feeb5c379f6f0fd968434749c00f453..19d4992e93b9c86bc60a46848968c4a50c5d65de 100644 --- a/browser/extensions/formautofill/skin/shared/editAddress.css +++ b/browser/extensions/formautofill/skin/shared/editAddress.css @@ -27,6 +27,8 @@ 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)); } diff --git a/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js index ac4105941cddc255c01a1b65f7aa1fb2da776b70..e73e39ebbbb25dfdd29e312dfd81e1321a369314 100644 --- a/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js +++ b/browser/extensions/formautofill/test/browser/browser_editAddressDialog.js @@ -1,5 +1,7 @@ "use strict"; +requestLongerTimeout(6); + add_task(async function setup_supportedCountries() { await SpecialPowers.pushPrefEnv({set: [ [SUPPORTED_COUNTRIES_PREF, "US,CA,DE"], @@ -49,9 +51,9 @@ 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 = [ @@ -72,7 +74,7 @@ add_task(async function test_saveAddress() { "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", @@ -118,12 +120,15 @@ add_task(async function test_saveAddressCA() { 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 = [ @@ -143,7 +148,7 @@ add_task(async function test_saveAddressCA() { "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", @@ -168,12 +173,14 @@ add_task(async function test_saveAddressDE() { 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 = [ @@ -191,7 +198,7 @@ add_task(async function test_saveAddressDE() { "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", @@ -209,6 +216,105 @@ add_task(async function test_saveAddressDE() { 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; diff --git a/browser/extensions/formautofill/test/browser/head.js b/browser/extensions/formautofill/test/browser/head.js index b9fb721bc821bbc98af8aa1c65798d684d4669db..bdd3bda08897bc9885f387c9db0834106db78c3a 100644 --- a/browser/extensions/formautofill/test/browser/head.js +++ b/browser/extensions/formautofill/test/browser/head.js @@ -1,5 +1,6 @@ /* 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, @@ -99,6 +100,21 @@ const TEST_ADDRESS_DE_1 = { 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", diff --git a/browser/extensions/formautofill/test/unit/test_createRecords.js b/browser/extensions/formautofill/test/unit/test_createRecords.js index c3254cd72ae14d6bb19ca1e0c772a47e7a625327..db150fb42a7255164abedbfed709c23eaa6b1923 100644 --- a/browser/extensions/formautofill/test/unit/test_createRecords.js +++ b/browser/extensions/formautofill/test/unit/test_createRecords.js @@ -69,11 +69,8 @@ const TESTCASES = [ "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: [], }, }, @@ -132,14 +129,14 @@ const TESTCASES = [ 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: [], @@ -156,14 +153,14 @@ const TESTCASES = [ 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: [], @@ -180,14 +177,14 @@ const TESTCASES = [ 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: [], diff --git a/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js b/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js index 4634f2c500fbe9ee21b37f6ad63f37feaa265977..773ad126a8e2f5a40f365336a72d968d7253bd6a 100644 --- a/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js +++ b/browser/extensions/formautofill/test/unit/test_onFormSubmitted.js @@ -58,7 +58,7 @@ const TESTCASES = [ description: "Trigger address saving", formValue: { "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "tel": "1-650-903-0800", }, expectedResult: { @@ -70,7 +70,7 @@ const TESTCASES = [ "street-address": "331 E. Evelyn Avenue", "address-level1": "", "address-level2": "", - "country": "USA", + "country": "US", "email": "", "tel": "1-650-903-0800", }, @@ -109,7 +109,7 @@ 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", @@ -125,7 +125,7 @@ const TESTCASES = [ "street-address": "331 E. Evelyn Avenue", "address-level1": "", "address-level2": "", - "country": "USA", + "country": "US", "email": "", "tel": "1-650-903-0800", }, @@ -148,7 +148,7 @@ 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: { @@ -160,7 +160,7 @@ const TESTCASES = [ "street-address": "331 E. Evelyn Avenue", "address-level1": "", "address-level2": "", - "country": "USA", + "country": "US", "email": "", "tel": "1-650-903-0800", }, @@ -174,7 +174,7 @@ const TESTCASES = [ 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", }, @@ -187,7 +187,7 @@ const TESTCASES = [ "street-address": "331 E. Evelyn Avenue", "address-level1": "", "address-level2": "", - "country": "USA", + "country": "US", "email": "", "tel": "1-650-903-0800", }, @@ -202,7 +202,7 @@ const TESTCASES = [ formValue: { "address-level1": "CA", "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", }, expectedResult: { formSubmission: true, @@ -213,7 +213,7 @@ const TESTCASES = [ "address-level1": "CA", "address-level2": "", "street-address": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "email": "", "tel": "", }, @@ -228,7 +228,7 @@ const TESTCASES = [ formValue: { "address-level1": "ca", "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", }, expectedResult: { formSubmission: true, @@ -239,7 +239,7 @@ const TESTCASES = [ "address-level1": "CA", "address-level2": "", "street-address": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "email": "", "tel": "", }, @@ -254,7 +254,7 @@ const TESTCASES = [ formValue: { "address-level1": "AR", "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", }, expectedResult: { formSubmission: true, @@ -265,7 +265,7 @@ const TESTCASES = [ "address-level1": "AR", "address-level2": "", "street-address": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "email": "", "tel": "", }, @@ -280,7 +280,7 @@ const TESTCASES = [ formValue: { "address-level1": "US-CA", "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", }, expectedResult: { formSubmission: true, @@ -291,7 +291,7 @@ const TESTCASES = [ "address-level1": "CA", "address-level2": "", "street-address": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "email": "", "tel": "", }, @@ -306,7 +306,7 @@ const TESTCASES = [ formValue: { "address-level1": "US-AZ", "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", }, expectedResult: { formSubmission: true, @@ -317,7 +317,7 @@ const TESTCASES = [ "address-level1": "AZ", "address-level2": "", "street-address": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "email": "", "tel": "", }, @@ -332,7 +332,7 @@ const TESTCASES = [ formValue: { "address-level1": "Ariz", "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", }, expectedResult: { formSubmission: true, @@ -343,7 +343,7 @@ const TESTCASES = [ "address-level1": "Arizonac", "address-level2": "", "street-address": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "email": "", "tel": "", }, @@ -358,7 +358,7 @@ const TESTCASES = [ formValue: { "address-level1": ["AL", "AK", "AP"], "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "tel": "1-650-903-0800", }, expectedResult: { @@ -370,7 +370,7 @@ const TESTCASES = [ "street-address": "331 E. Evelyn Avenue", "address-level1": "", "address-level2": "", - "country": "USA", + "country": "US", "tel": "1-650-903-0800", "email": "", }, @@ -385,7 +385,7 @@ const TESTCASES = [ formValue: { "address-level1": "", "street-addr": "331 E. Evelyn Avenue", - "country": "USA", + "country": "US", "tel": "1-650-903-0800", }, expectedResult: { @@ -397,7 +397,7 @@ const TESTCASES = [ "street-address": "331 E. Evelyn Avenue", "address-level1": "", "address-level2": "", - "country": "USA", + "country": "US", "tel": "1-650-903-0800", "email": "", }, @@ -584,7 +584,8 @@ TESTCASES.forEach(testcase => { 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); diff --git a/browser/extensions/formautofill/test/unit/test_parseAddressFormat.js b/browser/extensions/formautofill/test/unit/test_parseAddressFormat.js index e3573ab14ff50aa8f80cd5eb581dface848b9e0b..e592db003ce08e09ac17919ae9a6236c48280d3e 100644 --- a/browser/extensions/formautofill/test/unit/test_parseAddressFormat.js +++ b/browser/extensions/formautofill/test/unit/test_parseAddressFormat.js @@ -38,6 +38,18 @@ add_task(async function test_parseAddressFormat() { {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(), diff --git a/browser/extensions/formautofill/test/unit/test_transformFields.js b/browser/extensions/formautofill/test/unit/test_transformFields.js index 61003f17b89a3a80e4045d6a7db3229a8efd92b6..8a3f345ba37510066cad9b48cfabae7dc32de319 100644 --- a/browser/extensions/formautofill/test/unit/test_transformFields.js +++ b/browser/extensions/formautofill/test/unit/test_transformFields.js @@ -414,7 +414,7 @@ const ADDRESS_NORMALIZE_TESTCASES = [ description: "Has unsupported \"country\"", address: { "given-name": "John", // Make sure it won't be an empty record. - "country": "TV", + "country": "XX", }, expectedResult: { "country": undefined, diff --git a/dom/canvas/test/test_canvas.html b/dom/canvas/test/test_canvas.html index b408375f4adfc112c1e17e6e6a0be4504cdb5ce6..03c690d48cab23d05fc386b2f46c85249c44bee3 100644 --- a/dom/canvas/test/test_canvas.html +++ b/dom/canvas/test/test_canvas.html @@ -32,22 +32,6 @@ function IsLinux() { !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; @@ -5767,7 +5751,7 @@ 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. @@ -5827,14 +5811,11 @@ for (var p = 0; p < ps.length; ++p) 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> diff --git a/dom/canvas/test/webgl-conf/generated-mochitest.ini b/dom/canvas/test/webgl-conf/generated-mochitest.ini index 5d53fda416cb4cf76d8a94efe82e5f0fd5652729..642dbca670545f9d353c88e3259c2cc02538f421 100644 --- a/dom/canvas/test/webgl-conf/generated-mochitest.ini +++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini @@ -10767,7 +10767,6 @@ subsuite = webgl1-core 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] @@ -11346,7 +11345,6 @@ subsuite = webgl1-ext 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] @@ -11607,7 +11605,6 @@ 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] @@ -11671,7 +11668,6 @@ subsuite = webgl1-core 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] @@ -11680,16 +11676,12 @@ subsuite = webgl1-core 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] @@ -11702,13 +11694,10 @@ subsuite = webgl1-core 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] @@ -12094,7 +12083,6 @@ subsuite = webgl1-core 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] diff --git a/dom/canvas/test/webgl-conf/mochitest-errata.ini b/dom/canvas/test/webgl-conf/mochitest-errata.ini index 00c0a4372a624ff190600f69517c485717d8528b..8a4b24088517c1721f6d8de838287d03a6a7629c 100644 --- a/dom/canvas/test/webgl-conf/mochitest-errata.ini +++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini @@ -7,11 +7,10 @@ ########## # 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 @@ -410,11 +409,6 @@ 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') @@ -536,12 +530,6 @@ 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') #################### @@ -561,27 +549,6 @@ 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] diff --git a/dom/media/mediasource/test/mochitest.ini b/dom/media/mediasource/test/mochitest.ini index 7d7b4c053a85643107294d7b97063902dc13b141..7cde7bf8c585624aeab987563a9723a71bb428c5 100644 --- a/dom/media/mediasource/test/mochitest.ini +++ b/dom/media/mediasource/test/mochitest.ini @@ -80,7 +80,6 @@ skip-if = android_version == '22' || toolkit == 'android' # bug 1358640, bug 140 [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] diff --git a/dom/media/test/mochitest.ini b/dom/media/test/mochitest.ini index 3306d181e96f9c3f4101879ac66e34f4484c6d14..e7f18694c50d2f795a552859d15f9cc0c629dfb2 100644 --- a/dom/media/test/mochitest.ini +++ b/dom/media/test/mochitest.ini @@ -697,18 +697,17 @@ support-files = 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] @@ -724,7 +723,7 @@ 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] @@ -747,7 +746,7 @@ 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] @@ -758,7 +757,7 @@ skip-if = (android_version == '23' && debug) || (android_version == '25' && debu 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) @@ -769,7 +768,7 @@ 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] @@ -873,7 +872,7 @@ skip-if = android_version == '17' # android(bug 1232305) 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) @@ -885,7 +884,7 @@ skip-if = toolkit == 'android' # android(bug 1232305) 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 @@ -1069,14 +1068,13 @@ 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] @@ -1133,7 +1131,7 @@ 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 @@ -1161,10 +1159,10 @@ tags=msg capturestream 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) @@ -1221,7 +1219,7 @@ 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] @@ -1239,11 +1237,11 @@ tags = webvtt [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 @@ -1296,7 +1294,7 @@ skip-if = (os == 'win' || android_version == '19') # bug 1374189 # 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] diff --git a/dom/media/test/test_eme_request_notifications.html b/dom/media/test/test_eme_request_notifications.html index 8d5233e5bdc6d1118231ee9987038481cd0dd4e1..5275322965dba59da4b1ad96d446b6002a56da8b 100644 --- a/dom/media/test/test_eme_request_notifications.html +++ b/dom/media/test/test_eme_request_notifications.html @@ -41,8 +41,6 @@ function Test(test) { return res; } -const isWinXP = navigator.userAgent.includes("Windows NT 5.1"); - var tests = [ { keySystem: CLEARKEY_KEYSYSTEM, @@ -56,12 +54,12 @@ var tests = [ }, { 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]] }, { diff --git a/dom/media/tests/mochitest/head.js b/dom/media/tests/mochitest/head.js index 7d6829a49942a0120678f795608fcfdb84044677..24ac9ed42c412ad789fd6526e7054932960a91f5 100644 --- a/dom/media/tests/mochitest/head.js +++ b/dom/media/tests/mochitest/head.js @@ -1140,21 +1140,6 @@ class VideoStreamHelper { } } - -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"; diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html b/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html index 05fa85ee884ecac24887774af0de8e84dd697982..1f25f07e1db494b70699ef6c954a9379f8fde221 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicScreenshare.html @@ -67,12 +67,6 @@ * 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], diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html b/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html index 4a6b8ee7e622b6f69bbb8f9b677459e9983176f0..8099250246357917eb7e861215218caa5a4fa895 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicTabshare.html @@ -17,11 +17,6 @@ * 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() diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html b/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html index ca3a9a5cd6a8b53666611a82d3024fb7b40c21ea..13221e64fde2b867d0321ff371c3ddcbc5603717 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicWindowshare.html @@ -15,11 +15,6 @@ * 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: { diff --git a/dom/media/tests/mochitest/test_getUserMedia_scarySources.html b/dom/media/tests/mochitest/test_getUserMedia_scarySources.html index 5a54bf3bb8b616692a8bcb63de36aaaab12b3589..caeab57f0ee7b369628d4dbf6e189f753f9d6013 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_scarySources.html +++ b/dom/media/tests/mochitest/test_getUserMedia_scarySources.html @@ -29,12 +29,6 @@ let getDevices = async constraints => { }; 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]); diff --git a/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html b/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html index afc2cd76a7a7c1d6788c3236d3f4bf9e1c829c4e..9bbbd912bcf023b75f7df52f1561730ec72ec451 100644 --- a/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html +++ b/dom/media/tests/mochitest/test_peerConnection_basicScreenshare.html @@ -13,12 +13,6 @@ 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: { diff --git a/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html b/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html index 0ca94ec57eb86a5d570d6d120575a7ceeb61081b..7348977dd547c56bf96e39542ad86eae35bb3c3d 100644 --- a/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html +++ b/dom/media/tests/mochitest/test_peerConnection_basicWindowshare.html @@ -13,12 +13,6 @@ 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: { diff --git a/netwerk/test/unit/test_udp_multicast.js b/netwerk/test/unit/test_udp_multicast.js index 1bed33f75b438a220d927b874b11524e088d98d9..db127e033bf5d8a6479ba4939d83ddeeb04be5fd 100644 --- a/netwerk/test/unit/test_udp_multicast.js +++ b/netwerk/test/unit/test_udp_multicast.js @@ -16,7 +16,6 @@ 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; @@ -85,19 +84,15 @@ add_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"); @@ -108,4 +103,3 @@ add_test(() => { run_next_test ); }); -} diff --git a/python/mozbuild/mozbuild/base.py b/python/mozbuild/mozbuild/base.py index 7c56e51b387c1c33b43988b5ae3d327e218c5d1d..ea595d84a323ffd7d0b25d148e71227c1676762e 100644 --- a/python/mozbuild/mozbuild/base.py +++ b/python/mozbuild/mozbuild/base.py @@ -885,6 +885,11 @@ class MachCommandConditions(object): 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.""" diff --git a/testing/marionette/mach_commands.py b/testing/marionette/mach_commands.py index 55bf0022186cc71b0c2536118d711f296f922f89..d9def3a315d74ed52115b01d9d84e9b8b84d0597 100644 --- a/testing/marionette/mach_commands.py +++ b/testing/marionette/mach_commands.py @@ -21,11 +21,6 @@ from mozbuild.base import ( ) -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 @@ -74,7 +69,7 @@ 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): @@ -99,7 +94,7 @@ class Marionette(MachCommandBase): @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() diff --git a/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py index 9ad54e8a7fcf601b9282eea50bd71b509344ae01..e38996251eceb3788ee448a7aa14b5fb468fcacf 100644 --- a/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py +++ b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py @@ -74,6 +74,26 @@ def get_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. @@ -98,7 +118,7 @@ def _collect(pipe, poll_interval): 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) @@ -258,7 +278,7 @@ class SystemResourceMonitor(object): 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): @@ -308,21 +328,7 @@ class SystemResourceMonitor(object): # 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() diff --git a/testing/mozharness/mach_commands.py b/testing/mozharness/mach_commands.py index 649844629522481877654323ba120c9fc4969020..83a70a26c3e49f9456d6b57586f1393a593c4ceb 100644 --- a/testing/mozharness/mach_commands.py +++ b/testing/mozharness/mach_commands.py @@ -183,7 +183,7 @@ class MozharnessRunner(MozbuildObject): 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) diff --git a/testing/web-platform/mach_commands.py b/testing/web-platform/mach_commands.py index ca187db0309e51a3cd8bdeac60c56dd4318980f9..32bd91a576084ceee7633fb68cbc4a1cec273f21 100644 --- a/testing/web-platform/mach_commands.py +++ b/testing/web-platform/mach_commands.py @@ -23,11 +23,6 @@ from mach.decorators import ( 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" @@ -358,7 +353,7 @@ class MachCommands(MachCommandBase): @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() @@ -380,7 +375,7 @@ class MachCommands(MachCommandBase): @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) diff --git a/toolkit/components/mozintl/mozIMozIntl.idl b/toolkit/components/mozintl/mozIMozIntl.idl index d195fb439f28448008fd74d6b23405abd4d6f7aa..8499a905d3ff2cb05275e818ebe75bf598fdf236 100644 --- a/toolkit/components/mozintl/mozIMozIntl.idl +++ b/toolkit/components/mozintl/mozIMozIntl.idl @@ -50,11 +50,20 @@ interface mozIMozIntl : nsISupports */ 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); @@ -63,7 +72,7 @@ interface mozIMozIntl : nsISupports * 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); diff --git a/toolkit/components/mozintl/mozIntl.js b/toolkit/components/mozintl/mozIntl.js index eca985fcdb3e290387cf3d49f29e4ce6e54cec04..927623fffa27853252ab86a01e4c086d7336aaa1 100644 --- a/toolkit/components/mozintl/mozIntl.js +++ b/toolkit/components/mozintl/mozIntl.js @@ -199,19 +199,44 @@ class MozIntl { }); } + 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. } diff --git a/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js b/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js index b8027f55ad7af5e10e2c353163b3dfbcaa351a0f..47d0af6443edebd81d29b50aa866635adc4d4248 100644 --- a/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js +++ b/toolkit/components/mozintl/test/test_mozintl_getLocaleDisplayNames.js @@ -5,6 +5,7 @@ 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); @@ -81,3 +82,10 @@ add_test(function test_invalid_regions() { 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(); +}); diff --git a/widget/tests/test_bug596600.xul b/widget/tests/test_bug596600.xul index a9f46d22dc650374a226a91b23c7a3e52e5ccaef..387f845dd5fca0f39c034e4b9360448950cea0c9 100644 --- a/widget/tests/test_bug596600.xul +++ b/widget/tests/test_bug596600.xul @@ -149,11 +149,8 @@ function test2() { 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);