From 86771e90cf44a7f5754f1a8cd041c8cbb37e5c10 Mon Sep 17 00:00:00 2001 From: Nikolaos Trogkanis Date: Thu, 21 Apr 2011 08:01:27 +0000 Subject: [PATCH] JS: libphonenumber v3.2. --- .../BuildMetadataJsonFromXml.java | 18 +- javascript/README | 12 +- .../i18n/phonenumbers/asyoutypeformatter.js | 260 ++-- .../phonenumbers/asyoutypeformatter_test.js | 10 +- javascript/i18n/phonenumbers/metadata.js | 347 ++--- .../i18n/phonenumbers/metadatafortesting.js | 20 +- javascript/i18n/phonenumbers/metadatalite.js | 347 ++--- .../i18n/phonenumbers/phonemetadata.pb.js | 59 +- .../i18n/phonenumbers/phonenumber.pb.js | 2 +- .../i18n/phonenumbers/phonenumberutil.js | 1192 ++++++++++------- .../i18n/phonenumbers/phonenumberutil_test.js | 698 ++++++---- 11 files changed, 1806 insertions(+), 1159 deletions(-) diff --git a/java/resources/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java b/java/resources/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java index 5120311dd..f00ea3aed 100644 --- a/java/resources/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java +++ b/java/resources/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java @@ -51,7 +51,7 @@ public class BuildMetadataJsonFromXml { "BuildMetadataJsonFromXml PhoneNumberMetadata.xml metadatalite.js true\n"; static final String COPYRIGHT_NOTICE = - "/*\n" + + "/**\n" + " * @license\n" + " * Copyright (C) 2010 Google Inc.\n" + " *\n" + @@ -77,9 +77,9 @@ public class BuildMetadataJsonFromXml { private static final String COUNTRY_CODE_TO_REGION_CODE_MAP_COMMENT = "/**\n" + - " * A mapping from a country code to the region codes which denote the\n" + - " * country/region represented by that country code. In the case of multiple\n" + - " * countries sharing a calling code, such as the NANPA countries, the one\n" + + " * A mapping from a country calling code to the region codes which denote the\n" + + " * region represented by that country calling code. In the case of multiple\n" + + " * countries sharing a calling code, such as the NANPA regions, the one\n" + " * indicated with \"isMainCountryForCode\" in the metadata should be first.\n" + " * @type {Object.>}\n" + " */\n"; @@ -114,7 +114,7 @@ public class BuildMetadataJsonFromXml { writer.write(COUNTRY_CODE_TO_REGION_CODE_MAP_COMMENT); writer.write(NAMESPACE + ".countryCodeToRegionCodeMap = "); - writeCountryCodeCodeToRegionCodeMap(countryCodeToRegionCodeMap, writer); + writeCountryCodeToRegionCodeMap(countryCodeToRegionCodeMap, writer); writer.write(";\n\n"); writer.write(COUNTRY_TO_METADATA_COMMENT); @@ -149,7 +149,7 @@ public class BuildMetadataJsonFromXml { } // Writes a Map> in JSON format. - private static void writeCountryCodeCodeToRegionCodeMap( + private static void writeCountryCodeToRegionCodeMap( Map> countryCodeToRegionCodeMap, BufferedWriter writer) throws IOException { writer.write("{\n"); @@ -349,6 +349,12 @@ public class BuildMetadataJsonFromXml { toJsArray(metadata.getNoInternationalDialling(), jsArrayBuilder); // required PhoneNumberDesc uan = 25; toJsArray(metadata.getUan(), jsArrayBuilder); + // optional bool leading_zero_possible = 26 [default=false]; + if (metadata.isLeadingZeroPossible()) { + jsArrayBuilder.append(1); + } else { + jsArrayBuilder.append(null); + } jsArrayBuilder.endArray(); } diff --git a/javascript/README b/javascript/README index e75e583b4..d8bfdfc11 100644 --- a/javascript/README +++ b/javascript/README @@ -25,7 +25,7 @@ pages with your web browser: How to update: ============== -The JavaScript library is ported from the Java implementation (revision 107). +The JavaScript library is ported from the Java implementation (revision 166). When the Java project gets updated follow these steps to update the JavaScript project: @@ -33,25 +33,25 @@ project: have changed: a. Manually update the .pb.js files with the changes of the .proto files. b. Manually update the toJsArray() Java methods in - /java/resources/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java + java/resources/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java 2. If the phone number metadata in the XML format has changed - (java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml) + (resources/PhoneNumberMetaData.xml) run the following commands to regenerate metadata.js and metadatafortesting.js: ant -f java/build.xml java -cp java/build/classes \ com.google.i18n.phonenumbers.BuildMetadataJsonFromXml \ - java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml \ + resources/PhoneNumberMetaData.xml \ javascript/i18n/phonenumbers/metadata.js false java -cp java/build/classes \ com.google.i18n.phonenumbers.BuildMetadataJsonFromXml \ - java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml \ + resources/PhoneNumberMetaData.xml \ javascript/i18n/phonenumbers/metadatalite.js true java -cp java/build/classes \ com.google.i18n.phonenumbers.BuildMetadataJsonFromXml \ - java/resources/com/google/i18n/phonenumbers/test/PhoneNumberMetaDataForTesting.xml \ + resources/PhoneNumberMetaDataForTesting.xml \ javascript/i18n/phonenumbers/metadatafortesting.js false 3. Manually port any changes of the Java code to the JavaScript code: diff --git a/javascript/i18n/phonenumbers/asyoutypeformatter.js b/javascript/i18n/phonenumbers/asyoutypeformatter.js index f1e1be256..ae42cefcc 100644 --- a/javascript/i18n/phonenumbers/asyoutypeformatter.js +++ b/javascript/i18n/phonenumbers/asyoutypeformatter.js @@ -1,4 +1,4 @@ -/* +/** * @license * Copyright (C) 2010 Google Inc. * @@ -19,15 +19,13 @@ * @fileoverview A formatter which formats phone numbers as they are entered. * (based on the java implementation). * - * An AsYouTypeFormatter could be created by new AsYouTypeFormatter(). After - * that digits could be added by invoking the inputDigit method on the formatter + *

An AsYouTypeFormatter could be created by new AsYouTypeFormatter(). After + * that digits could be added by invoking {@link #inputDigit} on the formatter * instance, and the partially formatted phone number will be returned each time - * a digit is added. The clear method should be invoked before a new number - * needs to be formatted. + * a digit is added. {@link #clear} could be invoked before a new number needs + * to be formatted. * - * See testAsYouTypeFormatterUS(), testAsYouTestFormatterGB() and - * testAsYouTypeFormatterDE() in asyoutypeformatter_test.js for more details - * on how the formatter is to be used. + *

See the unittests for more details on how the formatter is to be used. * * @author Nikolaos Trogkanis */ @@ -47,43 +45,13 @@ goog.require('i18n.phonenumbers.metadata'); /** - * Constructs a light-weight formatter which does no formatting, but outputs - * exactly what is fed into the inputDigit method. + * Constructs an AsYouTypeFormatter for the specific region. * - * @param {string} regionCode the country/region where the phone number is being - * entered. + * @param {string} regionCode the ISO 3166-1 two-letter region code that denotes + * the region where the phone number is being entered. * @constructor */ i18n.phonenumbers.AsYouTypeFormatter = function(regionCode) { - /** - * A pattern that is used to match character classes in regular expressions. - * An example of a character class is [1-4]. - * @const - * @type {RegExp} - * @private - */ - this.CHARACTER_CLASS_PATTERN_ = /\[([^\[\]])*\]/g; - /** - * Any digit in a regular expression that actually denotes a digit. For - * example, in the regular expression 80[0-2]\d{6,10}, the first 2 digits - * (8 and 0) are standalone digits, but the rest are not. - * Two look-aheads are needed because the number following \\d could be a - * two-digit number, since the phone number can be as long as 15 digits. - * @const - * @type {RegExp} - * @private - */ - this.STANDALONE_DIGIT_PATTERN_ = /\d(?=[^,}][^,}])/g; - /** - * This is the minimum length of national number accrued that is required to - * trigger the formatter. The first element of the leadingDigitsPattern of - * each numberFormat contains a regular expression that matches up to this - * number of digits. - * @const - * @type {number} - * @private - */ - this.MIN_LEADING_DIGITS_LENGTH_ = 3; /** * The digits that have not been entered yet will be represented by a \u2008, * the punctuation space. @@ -138,7 +106,7 @@ i18n.phonenumbers.AsYouTypeFormatter = function(regionCode) { * @type {boolean} * @private */ - this.isExpectingCountryCode_ = false; + this.isExpectingCountryCallingCode_ = false; /** * @type {i18n.phonenumbers.PhoneNumberUtil} * @private @@ -185,7 +153,7 @@ i18n.phonenumbers.AsYouTypeFormatter = function(regionCode) { * @private */ this.defaultCountry_ = regionCode; - this.initializeCountrySpecificInfo_(this.defaultCountry_); + this.currentMetaData_ = this.getMetadataForRegion_(this.defaultCountry_); /** * @type {i18n.phonenumbers.PhoneMetadata} * @private @@ -194,28 +162,71 @@ i18n.phonenumbers.AsYouTypeFormatter = function(regionCode) { }; +/** + * @const + * @type {i18n.phonenumbers.PhoneMetadata} + * @private + */ +i18n.phonenumbers.AsYouTypeFormatter.EMPTY_METADATA_ = + new i18n.phonenumbers.PhoneMetadata(); +i18n.phonenumbers.AsYouTypeFormatter.EMPTY_METADATA_ + .setInternationalPrefix('NA'); + + +/** + * A pattern that is used to match character classes in regular expressions. + * An example of a character class is [1-4]. + * @const + * @type {RegExp} + * @private + */ +i18n.phonenumbers.AsYouTypeFormatter.CHARACTER_CLASS_PATTERN_ = + /\[([^\[\]])*\]/g; + + +/** + * Any digit in a regular expression that actually denotes a digit. For + * example, in the regular expression 80[0-2]\d{6,10}, the first 2 digits + * (8 and 0) are standalone digits, but the rest are not. + * Two look-aheads are needed because the number following \\d could be a + * two-digit number, since the phone number can be as long as 15 digits. + * @const + * @type {RegExp} + * @private + */ +i18n.phonenumbers.AsYouTypeFormatter.STANDALONE_DIGIT_PATTERN_ = + /\d(?=[^,}][^,}])/g; + + +/** + * This is the minimum length of national number accrued that is required to + * trigger the formatter. The first element of the leadingDigitsPattern of + * each numberFormat contains a regular expression that matches up to this + * number of digits. + * @const + * @type {number} + * @private + */ +i18n.phonenumbers.AsYouTypeFormatter.MIN_LEADING_DIGITS_LENGTH_ = 3; + + /** * @param {string} regionCode + * @return {i18n.phonenumbers.PhoneMetadata} * @private */ -i18n.phonenumbers.AsYouTypeFormatter.prototype.initializeCountrySpecificInfo_ = +i18n.phonenumbers.AsYouTypeFormatter.prototype.getMetadataForRegion_ = function(regionCode) { /** @type {i18n.phonenumbers.PhoneMetadata} */ - this.currentMetaData_ = this.phoneUtil_.getMetadataForRegion(regionCode); - if (this.currentMetaData_ == null) { - // Set to a default instance of the metadata. This allows us to function - // with an incorrect region code, even if formatting only works for numbers - // specified with '+'. - this.currentMetaData_ = new i18n.phonenumbers.PhoneMetadata(); - this.currentMetaData_.setInternationalPrefix('NA'); + var metadata = this.phoneUtil_.getMetadataForRegion(regionCode); + if (metadata != null) { + return metadata; } - /** @type {RegExp} */ - this.nationalPrefixForParsing_ = new RegExp('^(' + this.currentMetaData_ - .getNationalPrefixForParsing() + ')'); - /** @type {RegExp} */ - this.internationalPrefix_ = new RegExp('^(' + '\\+|' + - this.currentMetaData_.getInternationalPrefix() + ')'); + // Set to a default instance of the metadata. This allows us to function with + // an incorrect region code, even if formatting only works for numbers + // specified with '+'. + return i18n.phonenumbers.AsYouTypeFormatter.EMPTY_METADATA_; }; @@ -275,20 +286,19 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.narrowDownPossibleFormats_ = /** @type {Array.} */ var possibleFormats = []; /** @type {number} */ - var lengthOfLeadingDigits = leadingDigits.length; - /** @type {number} */ var indexOfLeadingDigitsPattern = - lengthOfLeadingDigits - this.MIN_LEADING_DIGITS_LENGTH_; + leadingDigits.length - + i18n.phonenumbers.AsYouTypeFormatter.MIN_LEADING_DIGITS_LENGTH_; /** @type {number} */ var possibleFormatsLength = this.possibleFormats_.length; for (var i = 0; i < possibleFormatsLength; ++i) { /** @type {i18n.phonenumbers.NumberFormat} */ var format = this.possibleFormats_[i]; if (format.leadingDigitsPatternCount() > indexOfLeadingDigitsPattern) { - /** @type {RegExp} */ - var leadingDigitsPattern = new RegExp('^(' + - format.getLeadingDigitsPattern(indexOfLeadingDigitsPattern) + ')'); - if (leadingDigitsPattern.test(leadingDigits)) { + /** @type {string} */ + var leadingDigitsPattern = + format.getLeadingDigitsPatternOrDefault(indexOfLeadingDigitsPattern); + if (leadingDigits.search(leadingDigitsPattern) == 0) { possibleFormats.push(this.possibleFormats_[i]); } } else { @@ -309,8 +319,6 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.narrowDownPossibleFormats_ = i18n.phonenumbers.AsYouTypeFormatter.prototype.createFormattingTemplate_ = function(format) { - /** @type {string} */ - var numberFormat = format.getFormatOrDefault(); /** @type {string} */ var numberPattern = format.getPatternOrDefault(); @@ -321,13 +329,16 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.createFormattingTemplate_ = } // Replace anything in the form of [..] with \d - numberPattern = numberPattern.replace(this.CHARACTER_CLASS_PATTERN_, '\\d'); + numberPattern = numberPattern.replace( + i18n.phonenumbers.AsYouTypeFormatter.CHARACTER_CLASS_PATTERN_, '\\d'); // Replace any standalone digit (not the one in d{}) with \d - numberPattern = numberPattern.replace(this.STANDALONE_DIGIT_PATTERN_, '\\d'); + numberPattern = numberPattern.replace( + i18n.phonenumbers.AsYouTypeFormatter.STANDALONE_DIGIT_PATTERN_, '\\d'); this.formattingTemplate_.clear(); /** @type {string} */ - var tempTemplate = this.getFormattingTemplate_(numberPattern, numberFormat); + var tempTemplate = this.getFormattingTemplate_(numberPattern, + format.getFormatOrDefault()); if (tempTemplate.length > this.nationalNumber_.getLength()) { this.formattingTemplate_.append(tempTemplate); return true; @@ -383,10 +394,10 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.clear = function() { this.positionToRemember_ = 0; this.originalPosition_ = 0; this.isInternationalFormatting_ = false; - this.isExpectingCountryCode_ = false; + this.isExpectingCountryCallingCode_ = false; this.possibleFormats_ = []; if (this.currentMetaData_ != this.defaultMetaData_) { - this.initializeCountrySpecificInfo_(this.defaultCountry_); + this.currentMetaData_ = this.getMetadataForRegion_(this.defaultCountry_); } }; @@ -395,7 +406,10 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.clear = function() { * Formats a phone number on-the-fly as each digit is entered. * * @param {string} nextChar the most recently entered digit of a phone number. - * Formatting characters are allowed, but they are removed from the result. + * Formatting characters are allowed, but as soon as they are encountered + * this method formats the number as entered and not 'as you type' anymore. + * Full width digits and Arabic-indic digits are allowed, and will be shown + * as they are. * @return {string} the partially formatted phone number. */ i18n.phonenumbers.AsYouTypeFormatter.prototype.inputDigit = function(nextChar) { @@ -406,10 +420,11 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.inputDigit = function(nextChar) { /** - * Same as inputDigit, but remembers the position where nextChar is inserted, so - * that it could be retrieved later by using getRememberedPosition(). The - * remembered position will be automatically adjusted if additional formatting - * characters are later inserted/removed in front of nextChar. + * Same as {@link #inputDigit}, but remembers the position where + * {@code nextChar} is inserted, so that it could be retrieved later by using + * {@link #getRememberedPosition}. The remembered position will be automatically + * adjusted if additional formatting characters are later inserted/removed in + * front of {@code nextChar}. * * @param {string} nextChar * @return {string} @@ -454,13 +469,13 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype. // digits (the plus sign is counted as a digit as well for this purpose) have // been entered. switch (this.accruedInputWithoutFormatting_.getLength()) { - case 0: // when the first few inputs are neither digits nor the plus sign. + case 0: case 1: case 2: return this.accruedInput_.toString(); case 3: if (this.attemptToExtractIdd_()) { - this.isExpectingCountryCode_ = true; + this.isExpectingCountryCallingCode_ = true; } else { // No IDD or plus sign is found, must be entering in national format. this.removeNationalPrefixFromNationalNumber_(); @@ -468,18 +483,18 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype. } case 4: case 5: - if (this.isExpectingCountryCode_) { - if (this.attemptToExtractCountryCode_()) { - this.isExpectingCountryCode_ = false; + if (this.isExpectingCountryCallingCode_) { + if (this.attemptToExtractCountryCallingCode_()) { + this.isExpectingCountryCallingCode_ = false; } return this.prefixBeforeNationalNumber_.toString() + this.nationalNumber_.toString(); } - // We make a last attempt to extract a country code at the 6th digit because - // the maximum length of IDD and country code are both 3. + // We make a last attempt to extract a country calling code at the 6th digit + // because the maximum length of IDD and country calling code are both 3. case 6: - if (this.isExpectingCountryCode_ && - !this.attemptToExtractCountryCode_()) { + if (this.isExpectingCountryCallingCode_ && + !this.attemptToExtractCountryCallingCode_()) { this.ableToFormat_ = false; return this.accruedInput_.toString(); } @@ -527,7 +542,7 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.attemptToFormatAccruedDigits_ = /** @type {string} */ var pattern = numFormat.getPatternOrDefault(); /** @type {RegExp} */ - var patternRegExp = new RegExp('^(' + pattern + ')$'); + var patternRegExp = new RegExp('^(?:' + pattern + ')$'); if (patternRegExp.test(nationalNumber)) { /** @type {string} */ var formattedNumber = nationalNumber.replace(new RegExp(pattern, 'g'), @@ -542,7 +557,7 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.attemptToFormatAccruedDigits_ = /** * Returns the current position in the partially formatted phone number of the * character which was previously passed in as the parameter of - * inputDigitAndRememberPosition(). + * {@link #inputDigitAndRememberPosition}. * * @return {number} */ @@ -561,17 +576,13 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.getRememberedPosition = this.accruedInputWithoutFormatting_.toString(); /** @type {string} */ var currentOutput = this.currentOutput_.toString(); - /** @type {number} */ - var currentOutputLength = currentOutput.length; while (accruedInputIndex < this.positionToRemember_ && - currentOutputIndex < currentOutputLength) { + currentOutputIndex < currentOutput.length) { if (accruedInputWithoutFormatting.charAt(accruedInputIndex) == currentOutput.charAt(currentOutputIndex)) { accruedInputIndex++; - currentOutputIndex++; - } else { - currentOutputIndex++; } + currentOutputIndex++; } return currentOutputIndex; }; @@ -591,9 +602,11 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype. var nationalNumber = this.nationalNumber_.toString(); // We start to attempt to format only when as least MIN_LEADING_DIGITS_LENGTH // digits of national number (excluding national prefix) have been entered. - if (nationalNumber.length >= this.MIN_LEADING_DIGITS_LENGTH_) { + if (nationalNumber.length >= + i18n.phonenumbers.AsYouTypeFormatter.MIN_LEADING_DIGITS_LENGTH_) { this.getAvailableFormats_( - nationalNumber.substring(0, this.MIN_LEADING_DIGITS_LENGTH_)); + nationalNumber.substring(0, + i18n.phonenumbers.AsYouTypeFormatter.MIN_LEADING_DIGITS_LENGTH_)); this.maybeCreateNewTemplate_(); return this.inputAccruedNationalNumber_(); } else { @@ -648,8 +661,11 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype. this.prefixBeforeNationalNumber_.append('1 '); this.isInternationalFormatting_ = true; } else if (this.currentMetaData_.hasNationalPrefix()) { + /** @type {RegExp} */ + var nationalPrefixForParsing = new RegExp( + '^(?:' + this.currentMetaData_.getNationalPrefixForParsing() + ')'); /** @type {Array.} */ - var m = nationalNumber.match(this.nationalPrefixForParsing_); + var m = nationalNumber.match(nationalPrefixForParsing); if (m != null && m[0] != null && m[0].length > 0) { // When the national prefix is detected, we use international formatting // rules instead of national ones, because national formatting rules could @@ -679,17 +695,21 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.attemptToExtractIdd_ = /** @type {string} */ var accruedInputWithoutFormatting = this.accruedInputWithoutFormatting_.toString(); + /** @type {RegExp} */ + var internationalPrefix = new RegExp( + '^(?:' + '\\' + i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + '|' + + this.currentMetaData_.getInternationalPrefix() + ')'); /** @type {Array.} */ - var m = accruedInputWithoutFormatting.match(this.internationalPrefix_); + var m = accruedInputWithoutFormatting.match(internationalPrefix); if (m != null && m[0] != null && m[0].length > 0) { this.isInternationalFormatting_ = true; /** @type {number} */ - var startOfCountryCode = m[0].length; + var startOfCountryCallingCode = m[0].length; this.nationalNumber_.clear(); this.nationalNumber_.append( - accruedInputWithoutFormatting.substring(startOfCountryCode)); + accruedInputWithoutFormatting.substring(startOfCountryCallingCode)); this.prefixBeforeNationalNumber_.append( - accruedInputWithoutFormatting.substring(0, startOfCountryCode)); + accruedInputWithoutFormatting.substring(0, startOfCountryCallingCode)); if (accruedInputWithoutFormatting.charAt(0) != i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) { this.prefixBeforeNationalNumber_.append(' '); @@ -701,39 +721,37 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.attemptToExtractIdd_ = /** - * Extracts country code from the beginning of nationalNumber to + * Extracts the country calling code from the beginning of nationalNumber to * prefixBeforeNationalNumber when they are available, and places the remaining * input into nationalNumber. * - * @return {boolean} true when a valid country code can be found. + * @return {boolean} true when a valid country calling code can be found. * @private */ -i18n.phonenumbers.AsYouTypeFormatter.prototype.attemptToExtractCountryCode_ = - function() { +i18n.phonenumbers.AsYouTypeFormatter.prototype. + attemptToExtractCountryCallingCode_ = function() { if (this.nationalNumber_.getLength() == 0) { return false; } /** @type {!goog.string.StringBuffer} */ - var numberWithoutCountryCode = new goog.string.StringBuffer(); + var numberWithoutCountryCallingCode = new goog.string.StringBuffer(); /** @type {number} */ var countryCode = this.phoneUtil_.extractCountryCode( - this.nationalNumber_, numberWithoutCountryCode); + this.nationalNumber_, numberWithoutCountryCallingCode); if (countryCode == 0) { return false; - } else { - this.nationalNumber_.clear(); - this.nationalNumber_.append(numberWithoutCountryCode.toString()); - /** @type {string} */ - var newRegionCode = - this.phoneUtil_.getRegionCodeForCountryCode(countryCode); - if (newRegionCode != this.defaultCountry_) { - this.initializeCountrySpecificInfo_(newRegionCode); - } - /** @type {string} */ - var countryCodeString = '' + countryCode; - this.prefixBeforeNationalNumber_.append(countryCodeString).append(' '); } + this.nationalNumber_.clear(); + this.nationalNumber_.append(numberWithoutCountryCallingCode.toString()); + /** @type {string} */ + var newRegionCode = this.phoneUtil_.getRegionCodeForCountryCode(countryCode); + if (newRegionCode != this.defaultCountry_) { + this.currentMetaData_ = this.getMetadataForRegion_(newRegionCode); + } + /** @type {string} */ + var countryCodeString = '' + countryCode; + this.prefixBeforeNationalNumber_.append(countryCodeString).append(' '); return true; }; @@ -743,7 +761,8 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.attemptToExtractCountryCode_ = * use. If nextChar contains a digit in non-ASCII format (e.g. the full-width * version of digits), it is first normalized to the ASCII version. The return * value is nextChar itself, or its normalized version, if nextChar is a digit - * in non-ASCII format. + * in non-ASCII format. This method assumes its input is either a digit or the + * plus sign. * * @param {string} nextChar * @param {boolean} rememberPosition @@ -756,8 +775,7 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype. if (nextChar == i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) { this.accruedInputWithoutFormatting_.append(nextChar); - } - if (nextChar in i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS) { + } else { nextChar = i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS[nextChar]; this.accruedInputWithoutFormatting_.append(nextChar); this.nationalNumber_.append(nextChar); diff --git a/javascript/i18n/phonenumbers/asyoutypeformatter_test.js b/javascript/i18n/phonenumbers/asyoutypeformatter_test.js index ee12daf6a..407abaa85 100644 --- a/javascript/i18n/phonenumbers/asyoutypeformatter_test.js +++ b/javascript/i18n/phonenumbers/asyoutypeformatter_test.js @@ -1,4 +1,4 @@ -/* +/** * @license * Copyright (C) 2010 Google Inc. * @@ -393,10 +393,10 @@ function testAYTFDE() { assertEquals('0', f.inputDigit('0')); assertEquals('03', f.inputDigit('3')); assertEquals('030', f.inputDigit('0')); - assertEquals('030 1', f.inputDigit('1')); - assertEquals('030 12', f.inputDigit('2')); - assertEquals('030 123', f.inputDigit('3')); - assertEquals('030 1234', f.inputDigit('4')); + assertEquals('030/1', f.inputDigit('1')); + assertEquals('030/12', f.inputDigit('2')); + assertEquals('030/123', f.inputDigit('3')); + assertEquals('030/1234', f.inputDigit('4')); // 04134 1234 f.clear(); diff --git a/javascript/i18n/phonenumbers/metadata.js b/javascript/i18n/phonenumbers/metadata.js index 839e9575e..444098608 100644 --- a/javascript/i18n/phonenumbers/metadata.js +++ b/javascript/i18n/phonenumbers/metadata.js @@ -1,4 +1,4 @@ -/* +/** * @license * Copyright (C) 2010 Google Inc. * @@ -17,15 +17,15 @@ /** * @fileoverview Generated metadata for file - * java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml + * resources/PhoneNumberMetaData.xml * @author Nikolaos Trogkanis */ goog.provide('i18n.phonenumbers.metadata'); /** - * A mapping from a country code to the region codes which denote the - * country/region represented by that country code. In the case of multiple + * A mapping from a country calling code to the region codes which denote the + * region represented by that country calling code. In the case of multiple * countries sharing a calling code, such as the NANPA countries, the one * indicated with "isMainCountryForCode" in the metadata should be first. * @type {Object.>} @@ -48,7 +48,7 @@ i18n.phonenumbers.metadata.countryCodeToRegionCodeMap = { ,44:["GB","GG","IM","JE"] ,45:["DK"] ,46:["SE"] -,47:["NO"] +,47:["NO","SJ"] ,48:["PL"] ,49:["DE"] ,51:["PE"] @@ -307,8 +307,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"AG":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"268(?:4(?:6[0-38]|84)|56[0-2])\\d{4}","\\d{7,10}",,,"2684601234"] +,"AG":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"268(?:4(?:6[0-38]|84)|56[0-2])\\d{4}","\\d{7}(?:\\d{3})?",,,"2684601234"] ,[,,"268(?:464|7(?:2[0-9]|64|7[0-689]|8[02-68]))\\d{4}","\\d{10}",,,"2684641234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -319,8 +319,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"268",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"AI":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"2644(?:6[12]|9[78])\\d{4}","\\d{7,10}",,,"2644612345"] +,"AI":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"2644(?:6[12]|9[78])\\d{4}","\\d{7}(?:\\d{3})?",,,"2644612345"] ,[,,"264(?:235|476|5(?:3[6-9]|8[1-4])|7(?:29|72))\\d{4}","\\d{10}",,,"2642351234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -444,8 +444,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"AS":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"6846(?:22|33|44|55|77|88|9[19])\\d{4}","\\d{7,10}",,,"6846221234"] +,"AS":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"6846(?:22|33|44|55|77|88|9[19])\\d{4}","\\d{7}(?:\\d{3})?",,,"6846221234"] ,[,,"684(?:733|258)\\d{4}","\\d{10}",,,"6847331234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -477,7 +477,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,"AU":[,[,,"[1-578]\\d{5,9}","\\d{6,10}"] ,[,,"[2378]\\d{8}","\\d{8,9}",,,"212345678"] -,[,,"4[0-68]\\d{7}","\\d{9}",,,"412345678"] +,[,,"4(?:[0-2]\\d|3[0-57-9]|4[47-9]|5[0-37-9]|6[6-9]|7[07-9]|8[7-9])\\d{6}","\\d{9}",,,"412345678"] ,[,,"1(?:80(?:0\\d{2})?|3(?:00\\d{2})?)\\d{4}","\\d{6,10}",,,"1800123456"] ,[,,"190[0126]\\d{6}","\\d{10}",,,"1900123456"] ,[,,"NA","NA"] @@ -515,8 +515,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ] ,"AZ":[,[,,"[1-8]\\d{7,8}","\\d{5,9}"] -,[,,"(?:1(?:(?:[28]\\d|9)\\d|02|1[0-589]|3[358]|4[013-79]|5[0-479]|6[02346-9]|7[0-24-8])|2(?:16|2\\d|3[0-24]|4[1468]|55|6[56]|79)|365?\\d)\\d{5}","\\d{5,9}",,,"123123456"] -,[,,"(?:4[04]|5[015]|60|7[07])\\d{7}","\\d{9}",,,"401234567"] +,[,,"(?:1(?:(?:[28]\\d|9)\\d|02|1[0-589]|3[358]|4[013-79]|5[0-479]|6[02346-9]|7[0-24-8])|2(?:16|2\\d|3[0-24]|4[1468]|55|6[56]|79)|365?\\d|44\\d{2})\\d{5}","\\d{5,9}",,,"123123456"] +,[,,"(?:[46]0|5[015]|7[07])\\d{7}","\\d{9}",,,"401234567"] ,[,,"88\\d{7}","\\d{9}",,,"881234567"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -551,8 +551,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"81\\d{6}","\\d{8}",,,"81123456"] ] -,"BB":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"246[2-9]\\d{6}","\\d{7,10}",,,"2462345678"] +,"BB":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"246[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"2462345678"] ,[,,"246(?:(?:2[346]|45|82)\\d|25[0-4])\\d{4}","\\d{10}",,,"2462501234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -698,8 +698,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"BM":[,[,,"[489]\\d{9}","\\d{7,10}"] -,[,,"441(?:2(?:02|23|61|[3479]\\d)|[46]\\d{2}|5(?:4\\d|60|89)|824)\\d{4}","\\d{7,10}",,,"4412345678"] +,"BM":[,[,,"[4589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"441(?:2(?:02|23|61|[3479]\\d)|[46]\\d{2}|5(?:4\\d|60|89)|824)\\d{4}","\\d{7}(?:\\d{3})?",,,"4412345678"] ,[,,"441(?:[37]\\d|5[0-39])\\d{5}","\\d{10}",,,"4413701234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -760,8 +760,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"BS":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3467]|8[0-4]|9[2-467])|461|502|6(?:12|7[67]|8[78]|9[89])|702)\\d{4}","\\d{7,10}",,,"2423456789"] +,"BS":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3467]|8[0-4]|9[2-467])|461|502|6(?:12|7[67]|8[78]|9[89])|702)\\d{4}","\\d{7}(?:\\d{3})?",,,"2423456789"] ,[,,"242(?:3(?:5[79]|[79]5)|4(?:[2-4][1-9]|5[1-8]|6[2-8]|7\\d|81)|5(?:2[34]|3[35]|44|5[1-9]|65|77)|6[34]6|727)\\d{4}","\\d{10}",,,"2423591234"] ,[,,"242300\\d{4}|8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -839,11 +839,11 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] -,"CA":[,[,,"[2-9]\\d{9}|3\\d{6}","\\d{7,10}"] -,[,,"(?:2(?:04|26|50|89)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}|310\\d{4}","\\d{7,10}",,,"2042345678"] -,[,,"(?:2(?:04|26|50|89)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}","\\d{7,10}",,,"2042345678"] -,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}|310\\d{4}","\\d{7,10}",,,"8002123456"] +,1] +,"CA":[,[,,"[2-9]\\d{9}|3\\d{6}","\\d{7}(?:\\d{3})?"] +,[,,"(?:2(?:04|26|[48]9|50)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}|310\\d{4}","\\d{7}(?:\\d{3})?",,,"2042345678"] +,[,,"(?:2(?:04|26|[48]9|50)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"2042345678"] +,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}|310\\d{4}","\\d{7}(?:\\d{3})?",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] ,[,,"NA","NA"] ,[,,"5(?:00|33|44)[2-9]\\d{6}","\\d{10}",,,"5002345678"] @@ -899,7 +899,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"CH":[,[,,"[2-9]\\d{8}","\\d{9}"] ,[,,"(?:2[12467]|3[1-4]|4[134]|5[12568]|6[12]|[7-9]1)\\d{7}","\\d{9}",,,"212345678"] ,[,,"7[46-9]\\d{7}","\\d{9}",,,"741234567"] @@ -930,16 +930,18 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] -,"CK":[,[] -,[] -,[] +,1] +,"CK":[,[,,"[2-57]\\d{4}","\\d{5}"] +,[,,"(?:2\\d|3[13-7]|4[1-5])\\d{3}","\\d{5}",,,"21234"] +,[,,"(?:5[0-68]|7\\d)\\d{3}","\\d{5}",,,"71234"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"CK",682,"00","00",,,"00",,,1,,,[,,"NA","NA"] +,"CK",682,"00",,,,,,,,[[,"(\\d{2})(\\d{3})","$1 $2",,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -1194,8 +1196,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"DM":[,[,,"[7-9]\\d{9}","\\d{7,10}"] -,[,,"767(?:2(?:55|66)|4(?:2[01]|4[0-25-9])|50[0-4])\\d{4}","\\d{7,10}",,,"7674201234"] +,"DM":[,[,,"[57-9]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"767(?:2(?:55|66)|4(?:2[01]|4[0-25-9])|50[0-4])\\d{4}","\\d{7}(?:\\d{3})?",,,"7674201234"] ,[,,"767(?:2(?:[2346]5|7[5-7])|31[5-7]|61[4-6])\\d{4}","\\d{10}",,,"7672251234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -1206,9 +1208,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"767",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"DO":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"8[024]9[2-9]\\d{6}","\\d{7,10}",,,"8092345678"] -,[,,"8[024]9[2-9]\\d{6}","\\d{7,10}",,,"8092345678"] +,"DO":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"8[024]9[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"8092345678"] +,[,,"8[024]9[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"8092345678"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] ,[,,"NA","NA"] @@ -1263,15 +1265,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"EE":[,[,,"[3-9]\\d{6,7}|800\\d{6,7}","\\d{6,10}"] +,"EE":[,[,,"[3-9]\\d{6,7}|800\\d{6,7}","\\d{7,10}"] ,[,,"(?:3[23589]|4(?:0\\d|[3-8])|6\\d|7[1-9]|88)\\d{5}","\\d{7,8}",,,"3212345"] ,[,,"(?:5\\d|8[1-5])\\d{6}|5(?:[02]\\d{2}|1(?:[0-8]\\d|95)|5[0-478]\\d|64[0-4]|65[1-589])\\d{3}","\\d{7,8}",,,"51234567"] ,[,,"800(?:0\\d{3}|1\\d|[2-9])\\d{3}","\\d{7,10}",,,"80012345"] ,[,,"900\\d{4}","\\d{7}",,,"9001234"] ,[,,"NA","NA"] -,[,,"70[0-2]?\\d{5}","\\d{7,8}",,,"70012345"] +,[,,"70[0-2]\\d{5}","\\d{8}",,,"70012345"] ,[,,"NA","NA"] -,"EE",372,"00",,,,,,,,[[,"([34-79]\\d{2})(\\d{4})","$1 $2",["[3679]|4[3-8]|5(?:[0-2]|5[0-478]|6[45])","[3679]|4[3-8]|5(?:[02]|1(?:[0-8]|95)|5[0-478]|6(?:4[0-4]|5[1-589]))"] +,"EE",372,"00",,,,,,,,[[,"([34-79]\\d{2})(\\d{4})","$1 $2",["[369]|4[3-8]|5(?:[0-2]|5[0-478]|6[45])|7[1-9]","[369]|4[3-8]|5(?:[02]|1(?:[0-8]|95)|5[0-478]|6(?:4[0-4]|5[1-589]))|7[1-9]"] ,"",""] ,[,"(70)(\\d{2})(\\d{4})","$1 $2 $3",["70"] ,"",""] @@ -1333,7 +1335,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,"ET":[,[,,"[1-59]\\d{8}","\\d{7,9}"] ,[,,"(?:11(?:1(?:1[124]|2[2-57]|3[1-5]|5[5-8]|8[6-8])|2(?:13|3[6-8]|5[89]|7[05-9]|8[2-6])|3(?:2[01]|3[0-289]|4[1289]|7[1-4]|87)|4(?:1[69]|3[2-49]|4[0-23]|6[5-8])|5(?:1[57]|44|5[0-4])|6(?:18|2[69]|4[5-7]|5[1-5]|6[0-59]|8[015-8]))|2(?:2(?:11[1-9]|22[0-7]|33\\d|44[1467]|66[1-68])|5(?:11[124-6]|33[2-8]|44[1467]|55[14]|66[1-3679]|77[124-79]|880))|3(?:3(?:11[0-46-8]|22[0-6]|33[0134689]|44[04]|55[0-6]|66[01467])|4(?:44[0-8]|55[0-69]|66[0-3]|77[1-5]))|4(?:6(?:22[0-24-7]|33[1-5]|44[13-69]|55[14-689]|660|88[1-4])|7(?:11[1-9]|22[1-9]|33[13-7]|44[13-6]|55[1-689]))|5(?:7(?:227|55[05]|(?:66|77)[14-8])|8(?:11[149]|22[013-79]|33[0-68]|44[013-8]|550|66[1-5]|77\\d)))\\d{4}","\\d{7,9}",,,"111112345"] -,[,,"91(?:1(?:[146]\\d|2[0-5]|3[4-6]|50|7[2-6]|8[46-9])|31\\d|4(?:3[0-2489]|7[0-3])|5(?:3[23]|7[3-5])|6(?:58|8[23])|7(?:5[57]|8[01])|8(?:3[45]|7[67]))\\d{4}","\\d{9}",,,"911123456"] +,[,,"91[0-8]\\d{6}","\\d{9}",,,"911234567"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -1345,7 +1347,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"FI":[,[,,"[1-9]\\d{4,11}","\\d{5,12}"] +,"FI":[,[,,"1\\d{4,11}|[2-9]\\d{4,10}","\\d{5,12}"] ,[,,"1(?:[35689][1-8]\\d{3,9}|[47]\\d{5,10})|2[1-8]\\d{3,9}|3(?:[1-8]\\d{3,9}|9\\d{4,8})|[5689][1-8]\\d{3,9}|","\\d{5,12}",,,"1312345678"] ,[,,"4\\d{5,10}|50\\d{4,8}","\\d{6,11}",,,"412345678"] ,[,,"800\\d{4,7}","\\d{7,10}",,,"8001234567"] @@ -1376,15 +1378,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"FK":[,[] -,[] -,[] +,"FK":[,[,,"[2-7]\\d{4}","\\d{5}"] +,[,,"[2-47]\\d{4}","\\d{5}",,,"31234"] +,[,,"[56]\\d{4}","\\d{5}",,,"51234"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"FK",500,"00","0",,,"0",,,1,,,[,,"NA","NA"] +,"FK",500,"00",,,,,,,,,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -1447,7 +1449,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"GB":[,[,,"\\d{7,10}","\\d{4,10}"] ,[,,"2(?:0[01378]|3[0189]|4[017]|8[0-46-9]|9[012])\\d{7}|1(?:(?:1(?:3[0-48]|[46][0-4]|5[012789]|7[0-39]|8[01349])|21[0-7]|31[0-8]|[459]1\\d|61[0-46-9]))\\d{6}|1(?:2(?:0[024-9]|2[3-9]|3[3-79]|4[1-689]|[58][02-9]|6[0-4789]|7[013-9]|9\\d)|3(?:0\\d|[25][02-9]|3[02-579]|[468][0-46-9]|7[1235679]|9[24578])|4(?:0[03-9]|[28][02-5789]|[37]\\d|4[02-69]|5[0-8]|[69][0-79])|5(?:0[1235-9]|2[024-9]|3[015689]|4[02-9]|5[03-9]|6\\d|7[0-35-9]|8[0-468]|9[0-5789])|6(?:0[034689]|2[0-35689]|[38][013-9]|4[1-467]|5[0-69]|6[13-9]|7[0-8]|9[0124578])|7(?:0[0246-9]|2\\d|3[023678]|4[03-9]|5[0-46-9]|6[013-9]|7[0-35-9]|8[024-9]|9[02-9])|8(?:0[35-9]|2[1-5789]|3[02-578]|4[0-578]|5[124-9]|6[2-69]|7\\d|8[02-9]|9[02569])|9(?:0[02-589]|2[02-689]|3[1-5789]|4[2-9]|5[0-579]|6[234789]|7[0124578]|8\\d|9[2-57]))\\d{6}|1(?:2(?:0(?:46[1-4]|87[2-9])|545[1-79]|76(?:2\\d|3[1-8]|6[1-6])|9(?:7(?:2[0-4]|3[2-5])|8(?:2[2-8]|7[0-4789]|8[345])))|3(?:638[2-5]|647[23]|8(?:47[04-9]|64[015789]))|4(?:044[1-7]|20(?:2[23]|8\\d)|6(?:0(?:30|5[2-57]|6[1-8]|7[2-8])|140)|8(?:052|87[123]))|5(?:24(?:3[2-79]|6\\d)|276\\d|6(?:26[06-9]|686))|6(?:06(?:4\\d|7[4-79])|295[567]|35[34]\\d|47(?:24|61)|59(?:5[08]|6[67]|74)|955[0-4])|7(?:26(?:6[13-9]|7[0-7])|442\\d|50(?:2[0-3]|[3-68]2|76))|8(?:27[56]\\d|37(?:5[2-5]|8[239])|84(?:3[2-58]))|9(?:0(?:0(?:6[1-8]|85)|52\\d)|3583|4(?:66[1-8]|9(?:2[01]|81))|63(?:23|3[1-4])|9561))\\d{3}|176888[234678]\\d{2}|16977[23]\\d{3}","\\d{4,10}",,,"1212345678"] ,[,,"7(?:[1-4]\\d\\d|5(?:0[0-8]|[13-9]\\d|2[0-35-9])|7(?:0[1-9]|[1-7]\\d|8[02-9]|9[0-689])|8(?:[014-9]\\d|[23][0-8])|9(?:[04-9]\\d|1[02-9]|2[0135-9]|3[0-689]))\\d{6}","\\d{10}",,,"7400123456"] @@ -1481,8 +1483,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,1,,[,,"NA","NA"] ,[,,"(?:3[0347]|55)\\d{8}","\\d{10}",,,"5512345678"] ] -,"GD":[,[,,"[489]\\d{9}","\\d{7,10}"] -,[,,"473(?:2(?:3[0-2]|69)|3(?:2[89]|86)|4(?:[06]8|3[5-9]|4[0-49]|5[5-79]|73|90)|63[68]|7(?:58|84)|938)\\d{4}","\\d{7,10}",,,"4732691234"] +,"GD":[,[,,"[4589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"473(?:2(?:3[0-2]|69)|3(?:2[89]|86)|4(?:[06]8|3[5-9]|4[0-49]|5[5-79]|73|90)|63[68]|7(?:58|84)|938)\\d{4}","\\d{7}(?:\\d{3})?",,,"4732691234"] ,[,,"473(?:4(?:0[3-79]|1[04-9]|20|58)|53[3-8])\\d{4}","\\d{10}",,,"4734031234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -1493,19 +1495,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"473",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"GE":[,[,,"[1-579]\\d{7}|8\\d{8}","\\d{5,9}"] -,[,,"(?:122|2(?:22|36|5[035])|3(?:1[0-35-8]|3[1-35679]|4\\d|7[0-39]|9[1-35-7])|3(?:[256]\\d|4[124-9]|7[0-4])|4(?:1\\d|2[2-7]|3[1-79]|4[2-8]|7[239]|9[1-7]))\\d{5}","\\d{5,8}",,,"32123456"] -,[,,"(?:5[1578]|6[28]|7[0147-9]|9[0135-9])\\d{6}","\\d{8}",,,"55123456"] +,"GE":[,[,,"[13-79]\\d{7}|8\\d{8}","\\d{5,9}"] +,[,,"(?:3(?:[256]\\d|4[124-9]|7[0-4])|4(?:1\\d|2[2-7]|3[1-79]|4[2-8]|7[239]|9[1-7]))\\d{5}","\\d{5,8}",,,"32123456"] +,[,,"(?:14|5[01578]|6[28]|7[0147-9]|9[0-35-9])\\d{6}","\\d{8}",,,"55123456"] ,[,,"800\\d{6}","\\d{9}",,,"800123456"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"GE",995,"8~10","8",,,"8",,,,[[,"(32)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["32"] -,"8 ($1)",""] -,[,"(\\d{3})(\\d)(\\d{2})(\\d{2})","$1 $2 $3 $4",["[24]|3[13-79]"] -,"8 ($1)",""] -,[,"(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["[5679]"] +,"GE",995,"8~10","8",,,"8",,,,[[,"(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["[13-79]"] ,"8 $1",""] ,[,"(800)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["8"] ,"8 $1",""] @@ -1656,21 +1654,26 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"GT":[,[] -,[] -,[] +,"GT":[,[,,"[2-7]\\d{7}|1[89]\\d{9}","\\d{8}(?:\\d{3})?"] +,[,,"[267][2-9]\\d{6}","\\d{8}",,,"22456789"] +,[,,"[345]\\d{7}","\\d{8}",,,"51234567"] +,[,,"18[01]\\d{8}","\\d{11}",,,"18001112222"] +,[,,"19\\d{9}","\\d{11}",,,"19001112222"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,[,,"NA","NA"] -,[,,"NA","NA"] -,"GT",502,"00",,,,,,,1,,,[,,"NA","NA"] +,"GT",502,"00",,,,,,,,[[,"(\\d{4})(\\d{4})","$1 $2",["[2-7]"] +,"",""] +,[,"(\\d{4})(\\d{3})(\\d{4})","$1 $2 $3",["1"] +,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"GU":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"671(?:3\\d{2}|47\\d|56\\d|6[3-5]\\d|7(?:3\\d|89)|828)\\d{4}","\\d{7,10}",,,"6713123456"] -,[,,"671(?:3\\d{2}|47\\d|56\\d|6[3-5]\\d|7(?:3\\d|89)|828)\\d{4}","\\d{7,10}",,,"6713123456"] +,"GU":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[23678])|5(?:55|6[2-5]|88)|6(?:3[2-578]|4[24-9]|5[34]|78|8[5-9])|7(?:[079]7|2[0167]|3[45]|8[789])|8(?:[2-5789]8|6[48])|9(?:2[29]|6[79]|7[179]|8[789]|9[78]))\\d{4}","\\d{7}(?:\\d{3})?",,,"6713001234"] +,[,,"671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[23678])|5(?:55|6[2-5]|88)|6(?:3[2-578]|4[24-9]|5[34]|78|8[5-9])|7(?:[079]7|2[0167]|3[45]|8[789])|8(?:[2-5789]8|6[48])|9(?:2[29]|6[79]|7[179]|8[789]|9[78]))\\d{4}","\\d{7}(?:\\d{3})?",,,"6713001234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] ,[,,"NA","NA"] @@ -1896,15 +1899,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"3(?:08162\\d|3\\d{5}|4(?:40[49]06|5624\\d)|7(?:0624\\d|2299\\d))\\d{3}|55\\d{8}","\\d{10}",,,"5512345678"] ] -,"IN":[,[,,"[1-9]\\d{9,10}","\\d{6,11}"] +,"IN":[,[,,"1\\d{7,11}|[2-9]\\d{9,10}","\\d{6,12}"] ,[,,"(?:11|2[02]|33|4[04]|79|80)[2-6]\\d{7}|(?:1(?:2[0-249]|3[0-25]|4[145]|[59][14]|6[014]|7[1257]|8[01346])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[126-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:[136][25]|22|4[28]|5[12]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)|7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)|8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91))[2-6]\\d{6}|(?:(?:1(?:2[35-8]|3[346-9]|4[236-9]|[59][0235-9]|6[235-9]|7[34689]|8[257-9])|2(?:1[134689]|3[24-8]|4[2-8]|5[25689]|6[2-4679]|7[13-79]|8[2-479]|9[235-9])|3(?:01|1[79]|2[1-5]|4[25-8]|5[125689]|6[235-7]|7[157-9]|8[2-467])|4(?:1[14578]|2[5689]|3[2-467]|5[4-7]|6[35]|73|8[2689]|9[2389])|5(?:[16][146-9]|2[14-8]|3[1346]|4[14-69]|5[46]|7[2-4]|8[2-8]|9[246])|6(?:1[1358]|2[2457]|3[2-4]|4[235-7]|5[2-689]|6[24-58]|7[23-689]|8[1-6])|8(?:1[1357-9]|2[235-8]|3[03-57-9]|4[0-24-9]|5\\d|6[2457-9]|7[1-6]|8[1256]|9[2-4]))\\d|7(?:(?:1[013-9]|2[0235-9]|3[2679]|4[1-35689]|5[2-46-9]|[67][02-9]|9\\d)\\d|8(?:2[0-6]|[013-8]\\d)))[2-6]\\d{5}","\\d{6,10}",,,"1123456789"] -,[,,"(?:7(?:39[89]|5(?:50|6[6-8]|79|[89][7-9])|6(?:0[027]|20|3[19]|54|65|7[67]|9[6-9])|7(?:0[89]|3[589]|42|60|9[5-9])|8(?:[03][07-9]|14|2[7-9]|4[25]|6[09]))\\d|9\\d{4}|8(?:(?:0[01589]|1[024])\\d|8(?:[079]\\d|44)|9[057-9]\\d)\\d)\\d{5}","\\d{10}",,,"9123456789"] -,[,,"1(?:800\\d?|600)\\d{6}","\\d{10,11}",,,"1800123456"] +,[,,"(?:7(?:2(?:0[04-9]|5[09]|7[568]|9[39])|3(?:07|7[3679]|9[689])|4(?:05|1[15-9]|[29][89]|39|8[389])|5(?:0[0-5]|[47]9|50|6[6-9]|[89][7-9])|6(?:0[027]|12|20|3[19]|5[45]|6[5-9]|7[67]|9[6-9])|7(?:0[289]|3[5-9]|42|60|9[5-9])|8(?:[03][07-9]|14|2[7-9]|4[25]|6[09]|7[015689]|9[0357-9]))\\d|9\\d{4}|8(?:(?:0[01589]|1[24]|2[2369]|4[023458]|52|6[0589]|7[2569])\\d|8(?:[079]\\d|44)|9[057-9]\\d)\\d)\\d{5}","\\d{10}",,,"9123456789"] +,[,,"1(?:600\\d{6}|800\\d{4,8})","\\d{8,12}",,,"1800123456"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"IN",91,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{2})(\\d{6})","$1 $2 $3",["7(?:39|5[5-9]|[67][02-9]|8[0-6])|8(?:0[01589]|1[024]|8[0479]|9[057-9])|9","7(?:39|5(?:50|[6-9])|[67][02-9]|8[0-6])|8(?:0[01589]|1[024]|8(?:[079]|44)|9[057-9])|9"] +,"IN",91,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{2})(\\d{6})","$1 $2 $3",["7(?:2[0579]|39|4[0-389]|5[04-9]|6|7[02-9]|8[0-79])|8(?:0[01589]|1[024]|8[0479]|9[057-9])|9","7(?:2[0579]|39|4[0-389]|5(?:0[0-5]|49|50|[6-9])|6|7[02-9]|8[0-79])|8(?:0[01589]|1[024]|8(?:[079]|44)|9[057-9])|9"] ,"0$1",""] ,[,"(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3",["11|2[02]|33|4[04]|79|80[2-6]"] ,"0$1",""] @@ -1928,22 +1931,26 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,"0$1",""] ,[,"(1600)(\\d{2})(\\d{4})","$1 $2 $3",["160","1600"] ,"$1",""] -,[,"(18[06]0)(\\d{2,3})(\\d{4})","$1 $2 $3",["18[06]","18[06]0"] +,[,"(1800)(\\d{4,5})","$1 $2",["180","1800"] +,"$1",""] +,[,"(18[06]0)(\\d{2,4})(\\d{4})","$1 $2 $3",["18[06]","18[06]0"] ,"$1",""] ] ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"1860345\\d{4}","\\d{11}",,,"18603451234"] ] -,"IO":[,[] -,[] -,[] +,"IO":[,[,,"3\\d{6}","\\d{7}"] +,[,,"37\\d{5}","\\d{7}",,,"3709100"] +,[,,"38\\d{5}","\\d{7}",,,"3801234"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"IO",246,"00",,,,,,,1,,,[,,"NA","NA"] +,"IO",246,"00",,,,,,,,[[,"(\\d{3})(\\d{4})","$1 $2",,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -2030,7 +2037,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"JE":[,[,,"[135789]\\d{6,9}","\\d{6,10}"] ,[,,"1534\\d{6}","\\d{6,10}",,,"1534456789"] ,[,,"7(?:509|7(?:00|97)|829|937)\\d{6}","\\d{10}",,,"7797123456"] @@ -2043,8 +2050,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"3(?:0(?:07(?:35|81)|8901)|3\\d{4}|4(?:4(?:4(?:05|42|69)|703)|5(?:041|800))|7(?:0002|1206))\\d{4}|55\\d{8}","\\d{10}",,,"5512345678"] ] -,"JM":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"876(?:(?:5[0-26]|6\\d|7[1-6]|9[2-8])\\d{5}|(?:7(?:0[2-689]|8[056]|9[45])|9(?:0[1-8]|1[02378]|9[2-468]))\\d{4})","\\d{7,10}",,,"8765123456"] +,"JM":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"876(?:(?:5[0-26]|6\\d|7[1-6]|9[2-8])\\d{5}|(?:7(?:0[2-689]|8[056]|9[45])|9(?:0[1-8]|1[02378]|9[2-468]))\\d{4})","\\d{7}(?:\\d{3})?",,,"8765123456"] ,[,,"876(?:(?:21|[348]\\d|5[78]|77)\\d|7(?:0[07]|8[1-47-9]|9[0-36-9])|9(?:[01]9|9[0579]))\\d{4}","\\d{10}",,,"8762101234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -2055,12 +2062,12 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"876",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"JO":[,[,,"[235-9]\\d{7,8}","\\d{8,9}"] +,"JO":[,[,,"[235-9]\\d{7,8}","\\d{7,9}"] ,[,,"[2356][2-8]\\d{6}","\\d{7,8}",,,"62001234"] ,[,,"7(?:[1-8]\\d|9[02-9])\\d{6}","\\d{9}",,,"790123456"] ,[,,"80\\d{6}","\\d{8}",,,"80012345"] ,[,,"900\\d{5}","\\d{8}",,,"90012345"] -,[,,"8(?:10\\d|5\\d{2}|7(?:[02]0|7[08]|9[09]))\\d{4}","\\d{8}",,,"85012345"] +,[,,"85\\d{6}","\\d{8}",,,"85012345"] ,[,,"70\\d{7}","\\d{9}",,,"700123456"] ,[,,"NA","NA"] ,"JO",962,"00","0",,,"0",,,,[[,"(\\d)(\\d{3})(\\d{4})","$1 $2 $3",["[2356]"] @@ -2072,7 +2079,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,,[,,"NA","NA"] ,,,[,,"NA","NA"] -,[,,"NA","NA"] +,[,,"8(?:10|[78]\\d)\\d{5}","\\d{8}",,,"87101234"] ] ,"JP":[,[,,"\\d{9,10}","\\d{9,10}"] ,[,,"(?:1(?:1[236-8]|2[3-6]|3[3-9]|4[2-6]|[58][2-8]|6[2-7]|7[2-9]|9[1-8])|2[2-9]\\d|[36][1-9]\\d|4(?:6[0235-8]|[2-578]\\d|9[2-59])|5(?:6[1-9]|7[2-8]|[2-589]\\d)|7(?:3[4-9]|4[02-9]|[25-9]\\d)|8(?:3[2-9]|4[5-9]|5[1-9]|8[03-9]|[2679]\\d)|9(?:[679][1-9]|[2-58]\\d))\\d{6}","\\d{9}",,,"312345678"] @@ -2154,15 +2161,17 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KI":[,[] -,[] -,[] +,"KI":[,[,,"[2-689]\\d{4}","\\d{5}"] +,[,,"(?:[234]\\d|50|8[1-5])\\d{3}","\\d{5}",,,"31234"] +,[,,"[69]\\d{4}","\\d{5}",,,"61234"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"KI",686,"00","0",,,"0",,,1,,,[,,"NA","NA"] +,"KI",686,"00","0",,,"0",,,,[[,"(\\d{5})","$1",,"0$1",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -2180,8 +2189,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KN":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"869(?:2(?:29|36)|4(?:6[5-9]|70))\\d{4}","\\d{7,10}",,,"8692361234"] +,"KN":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"869(?:2(?:29|36)|4(?:6[5-9]|70))\\d{4}","\\d{7}(?:\\d{3})?",,,"8692361234"] ,[,,"869(?:5(?:5[6-8]|6[5-7])|66[2-9]|76[2-5])\\d{4}","\\d{10}",,,"8695561234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -2241,7 +2250,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,"KW":[,[,,"[12569]\\d{6,7}","\\d{7,8}"] ,[,,"(?:18\\d|2(?:[23]\\d{2}|4[1-35-9]\\d|5(?:0[034]|[2-46]\\d|5[1-3]|7[1-7])))\\d{4}","\\d{7,8}",,,"22345678"] -,[,,"(?:5(?:0[02]|5\\d)|6(?:0[034679]|5[015-9]|6\\d|7[067])|9(?:0[09]|4[049]|[79]\\d))\\d{5}","\\d{8}",,,"50012345"] +,[,,"(?:5(?:0[0-2]|5\\d)|6(?:0[034679]|5[015-9]|6\\d|7[067]|99)|9(?:0[09]|4[049]|66|[79]\\d))\\d{5}","\\d{8}",,,"50012345"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -2256,8 +2265,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KY":[,[,,"[389]\\d{9}","\\d{7,10}"] -,[,,"345(?:2(?:22|44)|444|6(?:23|38|40)|7(?:6[6-9]|77)|8(?:00|1[45]|25|4[89]|88)|9(?:14|4[035-9]))\\d{4}","\\d{7,10}",,,"3452221234"] +,"KY":[,[,,"[3589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"345(?:2(?:22|44)|444|6(?:23|38|40)|7(?:6[6-9]|77)|8(?:00|1[45]|25|4[89]|88)|9(?:14|4[035-9]))\\d{4}","\\d{7}(?:\\d{3})?",,,"3452221234"] ,[,,"345(?:32[3-79]|5(?:1[467]|2[5-7]|4[5-9])|9(?:1[679]|2[4-9]|3[89]))\\d{4}","\\d{10}",,,"3453231234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}|345976\\d{4}","\\d{10}",,,"9002345678"] @@ -2268,16 +2277,16 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"345",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KZ":[,[,,"(?:[67]\\d{2}|80[09])\\d{7}","\\d{10}"] -,[,,"7(?:1(?:0(?:[23]\\d|4[023]|59|63)|1(?:[23]\\d|4[0-79]|59)|2(?:[23]\\d|59)|3(?:2\\d|3[1-7]|4[1235-9]|59)|4(?:2\\d|3[013-79]|4[0-58]|5[1-79])|5(?:2\\d|3[1-8]|4[1-7]|59)|6(?:22|[34]\\d|5[19])|72\\d|8(?:[27]\\d|3[1-46-9]|4[0-4]|))|2(?:1(?:[23]\\d|4[46-9]|5[3469])|2(?:2\\d|3[0679]|46|5[12679]|)|3(?:[234]\\d|5[139]|)|4(?:22|3[1235-8])|5(?:[23]\\d|4[0124-8]|59)|6(?:22|3[1-9]|4[0-4]|59)|7(?:[23]\\d|40|5[279]|7\\d)|8(?:[23]\\d|4[0-3]|59)|9(?:2\\d|3[12478]|59))|3622)\\d{5}","\\d{10}",,,"7123456789"] -,[,,"7(?:0[01257]\\d{2}|1[2-578]9[01]|2(?:[13-6]9[01]|7(?:58|9[01]))|6[02-4]\\d{2}|7[157]\\d{2})\\d{5}|6\\d{9}","\\d{10}",,,"7129012345"] +,"KZ":[,[,,"(?:7\\d{2}|80[09])\\d{7}","\\d{10}"] +,[,,"7(?:1(?:0(?:[23]\\d|4[023]|59|63)|1(?:[23]\\d|4[0-79]|59)|2(?:[23]\\d|59)|3(?:2\\d|3[1-79]|4[0-35-9]|59)|4(?:2\\d|3[013-79]|4[0-8]|5[1-79])|5(?:2\\d|3[1-8]|4[1-7]|59)|6(?:2\\d|[34]\\d|5[19]|61)|72\\d|8(?:[27]\\d|3[1-46-9]|4[0-5]|))|2(?:1(?:[23]\\d|4[46-9]|5[3469])|2(?:2\\d|3[0679]|46|5[12679]|)|3(?:[234]\\d|5[139]|)|4(?:2\\d|3[1235-9]|59)|5(?:[23]\\d|4[01246-8]|59|61)|6(?:2\\d|3[1-9]|4[0-4]|59)|7(?:[23]\\d|40|5[279]|7\\d)|8(?:[23]\\d|4[0-3]|59)|9(?:2\\d|3[124578]|59))|3622)\\d{5}","\\d{10}",,,"7123456789"] +,[,,"7(?:0[01257]\\d{2}|6[02-4]\\d{2}|7[157]\\d{2})\\d{5}","\\d{10}",,,"7710009998"] ,[,,"800\\d{7}","\\d{10}",,,"8001234567"] ,[,,"809\\d{7}","\\d{10}",,,"8091234567"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,[,,"NA","NA"] +,[,,"751\\d{7}","\\d{10}",,,"7511234567"] ,"KZ",7,"8~10","8",,,"8",,,,,,[,,"NA","NA"] -,,,[,,"NA","NA"] +,,,[,,"751\\d{7}","\\d{10}",,,"7511234567"] ,[,,"NA","NA"] ] ,"LA":[,[,,"[2-57]\\d{7,9}","\\d{6,10}"] @@ -2314,8 +2323,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"LC":[,[,,"[789]\\d{9}","\\d{7,10}"] -,[,,"758(?:234|4(?:5[0-9]|6[2-9]|8[0-2])|638|758)\\d{4}","\\d{7,10}",,,"7582345678"] +,"LC":[,[,,"[5789]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"758(?:234|4(?:5[0-9]|6[2-9]|8[0-2])|638|758)\\d{4}","\\d{7}(?:\\d{3})?",,,"7582345678"] ,[,,"758(?:28[4-7]|384|4(?:6[01]|8[4-9])|5(?:1[89]|20|84)|7(?:1[2-9]|2[0-4]))\\d{4}","\\d{10}",,,"7582845678"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -2532,17 +2541,22 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"ME":[,[] -,[] -,[] -,[,,"NA","NA"] -,[,,"NA","NA"] +,"ME":[,[,,"[2-9]\\d{7,8}","\\d{6,9}"] +,[,,"(?:20[2-8]|3(?:0[2-7]|1[35-7]|2[367]|3[4-7])|4(?:0[237]|1[2467])|5(?:0[47]|1[27]|2[378]))\\d{5}","\\d{6,8}",,,"30234567"] +,[,,"6(?:32\\d|[89]\\d{2}|7(?:[0-8]\\d|9(?:[3-9]|[0-2]\\d)))\\d{4}","\\d{8,9}",,,"67622901"] +,[,,"800[28]\\d{4}","\\d{8}",,,"80080002"] +,[,,"(?:88\\d|9(?:4[13-8]|5[16-8]))\\d{5}","\\d{8}",,,"94515151"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,[,,"NA","NA"] -,"ME",382,"99","0",,,"0",,,1,,,[,,"NA","NA"] +,[,,"78[134579]\\d{5}","\\d{8}",,,"78108780"] +,"ME",382,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3",["[2-57-9]|6[3789]","[2-57-9]|6(?:[389]|7(?:[0-8]|9[3-9]))"] +,"0$1",""] +,[,"(67)(9)(\\d{3})(\\d{3})","$1 $2 $3 $4",["679","679[0-2]"] +,"0$1",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] -,[,,"NA","NA"] +,[,,"77\\d{6}","\\d{8}",,,"77273012"] ] ,"MG":[,[,,"[23]\\d{8}","\\d{7,9}"] ,[,,"2(?:0(?:(?:2\\d|4[47]|5[3467]|6[279]|8[268]|9[245])\\d|7(?:2[29]|[35]\\d))|210\\d)\\d{4}","\\d{7,9}",,,"202123456"] @@ -2640,8 +2654,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MN":[,[,,"[12]\\d{7,9}|[57-9]\\d{7}","\\d{8,10}"] -,[,,"[12](?:1\\d|2(?:[1-3]\\d?|7\\d)|3[2-8]\\d{1,2}|4[2-68]\\d{1,2}|5[1-4689]\\d{1,2})\\d{5}|(?:5[0568]|70)\\d{6}","\\d{8,10}",,,"70123456"] +,"MN":[,[,,"[12]\\d{7,9}|[57-9]\\d{7}","\\d{6,10}"] +,[,,"[12](?:1\\d|2(?:[1-3]\\d?|7\\d)|3[2-8]\\d{1,2}|4[2-68]\\d{1,2}|5[1-4689]\\d{1,2})\\d{5}|(?:5[0568]|70)\\d{6}","\\d{6,10}",,,"70123456"] ,[,,"(?:8[89]|9[15689])\\d{6}","\\d{8}",,,"88123456"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -2677,9 +2691,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MP":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7,10}",,,"6702345678"] -,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7,10}",,,"6702345678"] +,"MP":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7}(?:\\d{3})?",,,"6702345678"] +,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7}(?:\\d{3})?",,,"6702345678"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] ,[,,"NA","NA"] @@ -2701,25 +2715,22 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MR":[,[,,"[2-4]\\d{6,7}|[5-7]\\d{6}|8\\d{7}","\\d{7,8}"] -,[,,"5(?:1[035]|2[0-69]|3[0348]|4[468]|5[02-467]|6[39]|7[4-69])\\d{4}|[2-4]5\\d{6}","\\d{7,8}",,,"35123456"] -,[,,"(?:[23][0-4]|4[3-5]|6\\d|7[0-7])\\d{5}|(?:2[27]|3[367]|4[467])\\d{6}","\\d{7,8}",,,"22123456"] +,"MR":[,[,,"[2-48]\\d{7}","\\d{8}"] +,[,,"25[08]\\d{5}|35\\d{6}|45[1-7]\\d{5}","\\d{8}",,,"35123456"] +,[,,"(?:2(?:2\\d|70)|3(?:3\\d|6[1-36]|7[1-3])|4(?:4\\d|6[0457-9]|7[4-9]))\\d{5}","\\d{8}",,,"22123456"] ,[,,"800\\d{5}","\\d{8}",,,"80012345"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"MR",222,"00",,,,,,,,[[,"([2-48]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["[2-48]"] -,"",""] -,[,"([2-7]\\d{2})(\\d{2})(\\d{2})","$1 $2 $3",["[2-7]"] -,"",""] +,"MR",222,"00",,,,,,,,[[,"([2-48]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,"",""] ] ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MS":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"664491\\d{4}","\\d{7,10}",,,"6644912345"] +,"MS":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"664491\\d{4}","\\d{7}(?:\\d{3})?",,,"6644912345"] ,[,,"664492\\d{4}","\\d{10}",,,"6644923456"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002123456"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002123456"] @@ -2758,15 +2769,18 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MV":[,[,,"[3679]\\d{6}","\\d{7}"] -,[,,"(?:3(?:00|3[0-59]|)|6(?:[567][02468]|8[024689]))\\d{4}","\\d{7}",,,"6701234"] -,[,,"(?:7(?:[679]\\d|8[02-9])|9[6-9]\\d)\\d{4}","\\d{7}",,,"7712345"] -,[,,"NA","NA"] +,"MV":[,[,,"[367]\\d{6}|9(?:00\\d{7}|\\d{6})","\\d{7,10}"] +,[,,"(?:3(?:0[01]|3[0-59]|)|6(?:[567][02468]|8[024689]|90))\\d{4}","\\d{7}",,,"6701234"] +,[,,"(?:7[36-9]|9[6-9])\\d{5}","\\d{7}",,,"7712345"] ,[,,"NA","NA"] +,[,,"900\\d{7}","\\d{10}",,,"9001234567"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"MV",960,"0(?:0|19)",,,,,,"00",,[[,"(\\d{3})(\\d{4})","$1-$2",,"",""] +,"MV",960,"0(?:0|19)",,,,,,"00",,[[,"(\\d{3})(\\d{4})","$1-$2",["[367]|9(?:[1-9]|0[1-9])"] +,"",""] +,[,"(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3",["900"] +,"",""] ] ,,[,,"781\\d{4}","\\d{7}",,,"7812345"] ,,,[,,"NA","NA"] @@ -2912,7 +2926,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"NF":[,[] ,[] ,[] @@ -2984,7 +2998,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ] ,"NO":[,[,,"0\\d{4}|[2-9]\\d{7}","\\d{5}(?:\\d{3})?"] -,[,,"0\\d{4}|(?:2[1-4]|3[1-3578]|5[1-35-7]|6[1-4679]|7\\d)\\d{6}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}","\\d{5}(?:\\d{3})?",,,"21234567"] +,[,,"(?:2[1-4]|3[1-3578]|5[1-35-7]|6[1-4679]|7[0-8])\\d{6}","\\d{8}",,,"21234567"] ,[,,"(?:4[015-8]|9\\d)\\d{6}","\\d{8}",,,"41234567"] ,[,,"80[01]\\d{5}","\\d{8}",,,"80012345"] ,[,,"82[09]\\d{5}","\\d{8}",,,"82012345"] @@ -2997,9 +3011,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,"",""] ] ,,[,,"NA","NA"] -,,,[,,"NA","NA"] -,[,,"NA","NA"] -] +,1,,[,,"NA","NA"] +,[,,"0\\d{4}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}","\\d{5}(?:\\d{3})?",,,"01234"] +,1] ,"NP":[,[,,"[1-8]\\d{5,7}|98[45]\\d{7}","\\d{6,10}"] ,[,,"(?:1[014-6]|2[13-79]|3[135-8]|4[146-9]|5[135-7]|6[13-9]|7[15-9]|8[1-4679]|9[1-79])\\d{6}","\\d{6,8}",,,"14567890"] ,[,,"98[45]\\d{7}","\\d{10}",,,"9841234567"] @@ -3230,9 +3244,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"PR":[,[,,"[789]\\d{9}","\\d{7,10}"] -,[,,"(?:787|939)[2-9]\\d{6}","\\d{7,10}",,,"7872345678"] -,[,,"(?:787|939)[2-9]\\d{6}","\\d{7,10}",,,"7872345678"] +,"PR":[,[,,"[5789]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"(?:787|939)[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"7872345678"] +,[,,"(?:787|939)[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"7872345678"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002345678"] ,[,,"NA","NA"] @@ -3378,7 +3392,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ,"RU",7,"8~10","8",,,"8",,,,[[,"([3489]\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2-$3-$4",["[34689]"] ,"8 ($1)",""] -,[,"([67]\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",["[67]"] +,[,"(7\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",["7"] ,"8 ($1)",""] ] ,,[,,"NA","NA"] @@ -3568,6 +3582,18 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] +,"SJ":[,[,,"0\\d{4}|[4789]\\d{7}","\\d{5}(?:\\d{3})?"] +,[,,"79\\d{6}","\\d{8}",,,"79123456"] +,[,,"(?:4[015-8]|9\\d)\\d{6}","\\d{8}",,,"41234567"] +,[,,"80[01]\\d{5}","\\d{8}",,,"80012345"] +,[,,"82[09]\\d{5}","\\d{8}",,,"82012345"] +,[,,"810(?:0[0-6]|[2-8]\\d)\\d{3}","\\d{8}",,,"81021234"] +,[,,"880\\d{5}","\\d{8}",,,"88012345"] +,[,,"NA","NA"] +,"SJ",47,"00",,,,,,,,,,[,,"NA","NA"] +,,,[,,"NA","NA"] +,[,,"0\\d{4}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}","\\d{5}(?:\\d{3})?",,,"01234"] +,1] ,"SK":[,[,,"[2-689]\\d{8}","\\d{9}"] ,[,,"[2-5]\\d{8}","\\d{9}",,,"212345678"] ,[,,"9(?:0[1-8]|1[0-24-9]|4[0489])\\d{6}","\\d{9}",,,"912123456"] @@ -3626,7 +3652,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"SN":[,[,,"[37]\\d{8}","\\d{9}"] ,[,,"3(?:010|3(?:8[1-9]|9[2-9]))\\d{5}","\\d{9}",,,"301012345"] ,[,,"7(?:0[1256]0|6(?:1[23]|2[89]|3[3489]|4[6-9]|5[1-389]|6[6-9]|7[45]|8[3-8])|7(?:1[014-8]|2[0-7]|3[0-35-8]|4[0-6]|[56]\\d|7[0-589]|8[01]|9[0-6]))\\d{5}","\\d{9}",,,"701012345"] @@ -3684,15 +3710,22 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"SV":[,[] -,[] -,[] -,[,,"NA","NA"] -,[,,"NA","NA"] +,"SV":[,[,,"[27]\\d{7}|[89]\\d{6}(?:\\d{4})?","\\d{7,8}|\\d{11}"] +,[,,"2[1-6]\\d{6}","\\d{8}",,,"21234567"] +,[,,"7\\d{7}","\\d{8}",,,"70123456"] +,[,,"800\\d{4}(?:\\d{4})?","\\d{7}(?:\\d{4})?",,,"8001234"] +,[,,"900\\d{4}(?:\\d{4})?","\\d{7}(?:\\d{4})?",,,"9001234"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"SV",503,"00",,,,,,,1,,,[,,"NA","NA"] +,"SV",503,"00",,,,,,,,[[,"(\\d{4})(\\d{4})","$1 $2",["[27]"] +,"",""] +,[,"(\\d{3})(\\d{4})","$1 $2",["[89]"] +,"",""] +,[,"(\\d{3})(\\d{4})(\\d{4})","$1 $2 $3",["[89]"] +,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -3729,9 +3762,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"0800\\d{4}","\\d{8}",,,"08001234"] ,[,,"NA","NA"] -] -,"TC":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"649(?:712|9(?:4\\d|50))\\d{4}","\\d{7,10}",,,"6497121234"] +,1] +,"TC":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"649(?:712|9(?:4\\d|50))\\d{4}","\\d{7}(?:\\d{3})?",,,"6497121234"] ,[,,"649(?:2(?:3[12]|4[1-5])|3(?:3[1-39]|4[1-57])|4[34][12])\\d{4}","\\d{10}",,,"6492311234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002345678"] @@ -3781,7 +3814,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"TH":[,[,,"[2-8]\\d{7,8}|1\\d{9}","\\d{8,10}"] ,[,,"(?:2[1-9]|3[24-9]|4[2-5]|5[3-6]|7[3-7])\\d{6}","\\d{8}",,,"21234567"] ,[,,"8\\d{8}","\\d{9}",,,"812345678"] @@ -3905,12 +3938,12 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,"(444)(\\d{1})(\\d{3})","$1 $2 $3",["444"] ,"",""] ] -,,[,,"NA","NA"] +,,[,,"512\\d{7}","\\d{10}",,,"5123456789"] ,,,[,,"NA","NA"] ,[,,"444\\d{4}|850\\d{7}","\\d{7,10}",,,"4441444"] ] -,"TT":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"868(?:2(?:01|2[1-4])|6(?:1[4-6]|2[1-9]|[3-6]\\d|7[0-79]|9[0-8])|82[12])\\d{4}","\\d{7,10}",,,"8682211234"] +,"TT":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"868(?:2(?:01|2[1-4])|6(?:07|1[4-6]|2[1-9]|[3-6]\\d|7[0-79]|9[0-8])|82[12])\\d{4}","\\d{7}(?:\\d{3})?",,,"8682211234"] ,[,,"868(?:29\\d|3(?:0[1-9]|1[02-9]|[2-9]\\d)|4(?:[679]\\d|8[0-4])|6(?:20|78|8\\d)|7(?:1[02-9]|[2-9]\\d))\\d{4}","\\d{10}",,,"8682911234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002345678"] @@ -4007,9 +4040,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"US":[,[,,"[2-9]\\d{9}","\\d{7,10}"] -,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[04]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7,10}",,,"2012345678"] -,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[04]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7,10}",,,"2012345678"] +,"US":[,[,,"[2-9]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[014]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"2012345678"] +,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[014]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7}(?:\\d{3})?",,,"2012345678"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002345678"] ,[,,"NA","NA"] @@ -4063,9 +4096,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] -,"VC":[,[,,"(?:784|8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] -,[,,"784(?:266|3(?:6[6-9]|7\\d|8[0-24-6])|4(?:38|5[0-36-8]|8\\d|9[01])|555|638|784)\\d{4}","\\d{7,10}",,,"7842661234"] +,1] +,"VC":[,[,,"[5789]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"784(?:266|3(?:6[6-9]|7\\d|8[0-24-6])|4(?:38|5[0-36-8]|8\\d|9[01])|555|638|784)\\d{4}","\\d{7}(?:\\d{3})?",,,"7842661234"] ,[,,"784(?:4(?:3[0-24]|5[45]|9[2-5])|5(?:2[6-9]|3[0-3]|93))\\d{4}","\\d{10}",,,"7844301234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002345678"] @@ -4090,8 +4123,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"VG":[,[,,"(?:284|8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] -,[,,"284(?:(?:229|4(?:46|9[45])|8(?:52|6[459]))\\d{4}|496[0-5]\\d{3})","\\d{7,10}",,,"2842291234"] +,"VG":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"284(?:(?:229|4(?:46|9[45])|8(?:52|6[459]))\\d{4}|496[0-5]\\d{3})","\\d{7}(?:\\d{3})?",,,"2842291234"] ,[,,"284(?:(?:30[0-3]|4(?:4[0-5]|68|99)|54[0-4])\\d{4}|496[6-9]\\d{3})","\\d{10}",,,"2843001234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002345678"] @@ -4102,9 +4135,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"284",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"VI":[,[,,"340(?:6[49]2|7[17]\\d)\\d{4}|(?:8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] -,[,,"340(?:6[49]2|7[17]\\d)\\d{4}|(?:8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}",,,"3406421234"] -,[,,"340(?:6[49]2|7[17]\\d)\\d{4}|(?:8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}",,,"3406421234"] +,"VI":[,[,,"[3589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"340(?:6[49]2|7[17]\\d)\\d{4}","\\d{7}(?:\\d{3})?",,,"3406421234"] +,[,,"340(?:6[49]2|7[17]\\d)\\d{4}","\\d{7}(?:\\d{3})?",,,"3406421234"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}",,,"8002345678"] ,[,,"900[2-9]\\d{6}","\\d{10}",,,"9002345678"] ,[,,"NA","NA"] diff --git a/javascript/i18n/phonenumbers/metadatafortesting.js b/javascript/i18n/phonenumbers/metadatafortesting.js index 11c4bc666..c1cbc829a 100644 --- a/javascript/i18n/phonenumbers/metadatafortesting.js +++ b/javascript/i18n/phonenumbers/metadatafortesting.js @@ -1,4 +1,4 @@ -/* +/** * @license * Copyright (C) 2010 Google Inc. * @@ -17,15 +17,15 @@ /** * @fileoverview Generated metadata for file - * java/resources/com/google/i18n/phonenumbers/test/PhoneNumberMetaDataForTesting.xml + * resources/PhoneNumberMetaDataForTesting.xml * @author Nikolaos Trogkanis */ goog.provide('i18n.phonenumbers.metadata'); /** - * A mapping from a country code to the region codes which denote the - * country/region represented by that country code. In the case of multiple + * A mapping from a country calling code to the region codes which denote the + * region represented by that country calling code. In the case of multiple * countries sharing a calling code, such as the NANPA countries, the one * indicated with "isMainCountryForCode" in the metadata should be first. * @type {Object.>} @@ -152,7 +152,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ,"DE",49,"00","0",,,"0",,,,[[,"(\\d{3})(\\d{3,8})","$1 $2",["2|3[3-9]|906|[4-9][1-9]1"] ,"0$1",""] -,[,"(\\d{2})(\\d{4,9})","$1 $2",["[34]0|[68]9"] +,[,"(\\d{2})(\\d{4,9})","$1/$2",["[34]0|[68]9"] ,"0$1",""] ,[,"([4-9]\\d)(\\d{2})","$1 $2",["[4-9]","[4-6]|[7-9](?:\\d[1-9]|[1-9]\\d)"] ,"0$1",""] @@ -208,7 +208,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"JP":[,[] ,[] ,[] @@ -348,7 +348,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"262|6(?:9[23]|47)|8",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"SG":[,[,,"[13689]\\d{7,10}","\\d{8,11}"] +,"SG":[,[,,"[13689]\\d{7,10}","\\d{8}|\\d{10,11}"] ,[,,"[36]\\d{7}","\\d{8}"] ,[,,"[89]\\d{7}","\\d{8}"] ,[,,"1?800\\d{7}","\\d{10,11}"] @@ -367,9 +367,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"US":[,[,,"[13-9]\\d{9}|2[0-35-9]\\d{8}","\\d{7,10}",,,"1234567890"] -,[,,"[13-9]\\d{9}|2[0-35-9]\\d{8}","\\d{7,10}",,,"1234567890"] -,[,,"[13-9]\\d{9}|2[0-35-9]\\d{8}","\\d{7,10}",,,"1234567890"] +,"US":[,[,,"[13-9]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890"] +,[,,"[13-9]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890"] +,[,,"[13-9]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890"] ,[,,"8(?:00|66|77|88)\\d{7}","\\d{10}",,,"1234567890"] ,[,,"900\\d{7}","\\d{10}",,,"1234567890"] ,[,,"NA","NA"] diff --git a/javascript/i18n/phonenumbers/metadatalite.js b/javascript/i18n/phonenumbers/metadatalite.js index 878bc5e20..bceb7d706 100644 --- a/javascript/i18n/phonenumbers/metadatalite.js +++ b/javascript/i18n/phonenumbers/metadatalite.js @@ -1,4 +1,4 @@ -/* +/** * @license * Copyright (C) 2010 Google Inc. * @@ -17,15 +17,15 @@ /** * @fileoverview Generated metadata for file - * java/resources/com/google/i18n/phonenumbers/src/PhoneNumberMetaData.xml + * resources/PhoneNumberMetaData.xml * @author Nikolaos Trogkanis */ goog.provide('i18n.phonenumbers.metadata'); /** - * A mapping from a country code to the region codes which denote the - * country/region represented by that country code. In the case of multiple + * A mapping from a country calling code to the region codes which denote the + * region represented by that country calling code. In the case of multiple * countries sharing a calling code, such as the NANPA countries, the one * indicated with "isMainCountryForCode" in the metadata should be first. * @type {Object.>} @@ -48,7 +48,7 @@ i18n.phonenumbers.metadata.countryCodeToRegionCodeMap = { ,44:["GB","GG","IM","JE"] ,45:["DK"] ,46:["SE"] -,47:["NO"] +,47:["NO","SJ"] ,48:["PL"] ,49:["DE"] ,51:["PE"] @@ -307,8 +307,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"AG":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"268(?:4(?:6[0-38]|84)|56[0-2])\\d{4}","\\d{7,10}"] +,"AG":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"268(?:4(?:6[0-38]|84)|56[0-2])\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"268(?:464|7(?:2[0-9]|64|7[0-689]|8[02-68]))\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -319,8 +319,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"268",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"AI":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"2644(?:6[12]|9[78])\\d{4}","\\d{7,10}"] +,"AI":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"2644(?:6[12]|9[78])\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"264(?:235|476|5(?:3[6-9]|8[1-4])|7(?:29|72))\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -444,8 +444,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"AS":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"6846(?:22|33|44|55|77|88|9[19])\\d{4}","\\d{7,10}"] +,"AS":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"6846(?:22|33|44|55|77|88|9[19])\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"684(?:733|258)\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -477,7 +477,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,"AU":[,[,,"[1-578]\\d{5,9}","\\d{6,10}"] ,[,,"[2378]\\d{8}","\\d{8,9}"] -,[,,"4[0-68]\\d{7}","\\d{9}"] +,[,,"4(?:[0-2]\\d|3[0-57-9]|4[47-9]|5[0-37-9]|6[6-9]|7[07-9]|8[7-9])\\d{6}","\\d{9}"] ,[,,"1(?:80(?:0\\d{2})?|3(?:00\\d{2})?)\\d{4}","\\d{6,10}"] ,[,,"190[0126]\\d{6}","\\d{10}"] ,[,,"NA","NA"] @@ -515,8 +515,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ] ,"AZ":[,[,,"[1-8]\\d{7,8}","\\d{5,9}"] -,[,,"(?:1(?:(?:[28]\\d|9)\\d|02|1[0-589]|3[358]|4[013-79]|5[0-479]|6[02346-9]|7[0-24-8])|2(?:16|2\\d|3[0-24]|4[1468]|55|6[56]|79)|365?\\d)\\d{5}","\\d{5,9}"] -,[,,"(?:4[04]|5[015]|60|7[07])\\d{7}","\\d{9}"] +,[,,"(?:1(?:(?:[28]\\d|9)\\d|02|1[0-589]|3[358]|4[013-79]|5[0-479]|6[02346-9]|7[0-24-8])|2(?:16|2\\d|3[0-24]|4[1468]|55|6[56]|79)|365?\\d|44\\d{2})\\d{5}","\\d{5,9}"] +,[,,"(?:[46]0|5[015]|7[07])\\d{7}","\\d{9}"] ,[,,"88\\d{7}","\\d{9}"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -551,8 +551,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"81\\d{6}","\\d{8}"] ] -,"BB":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"246[2-9]\\d{6}","\\d{7,10}"] +,"BB":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"246[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] ,[,,"246(?:(?:2[346]|45|82)\\d|25[0-4])\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -698,8 +698,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"BM":[,[,,"[489]\\d{9}","\\d{7,10}"] -,[,,"441(?:2(?:02|23|61|[3479]\\d)|[46]\\d{2}|5(?:4\\d|60|89)|824)\\d{4}","\\d{7,10}"] +,"BM":[,[,,"[4589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"441(?:2(?:02|23|61|[3479]\\d)|[46]\\d{2}|5(?:4\\d|60|89)|824)\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"441(?:[37]\\d|5[0-39])\\d{5}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -760,8 +760,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"BS":[,[,,"[289]\\d{9}","\\d{7,10}"] -,[,,"242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3467]|8[0-4]|9[2-467])|461|502|6(?:12|7[67]|8[78]|9[89])|702)\\d{4}","\\d{7,10}"] +,"BS":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3467]|8[0-4]|9[2-467])|461|502|6(?:12|7[67]|8[78]|9[89])|702)\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"242(?:3(?:5[79]|[79]5)|4(?:[2-4][1-9]|5[1-8]|6[2-8]|7\\d|81)|5(?:2[34]|3[35]|44|5[1-9]|65|77)|6[34]6|727)\\d{4}","\\d{10}"] ,[,,"242300\\d{4}|8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -839,11 +839,11 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] -,"CA":[,[,,"[2-9]\\d{9}|3\\d{6}","\\d{7,10}"] -,[,,"(?:2(?:04|26|50|89)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}|310\\d{4}","\\d{7,10}"] -,[,,"(?:2(?:04|26|50|89)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}","\\d{7,10}"] -,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}|310\\d{4}","\\d{7,10}"] +,1] +,"CA":[,[,,"[2-9]\\d{9}|3\\d{6}","\\d{7}(?:\\d{3})?"] +,[,,"(?:2(?:04|26|[48]9|50)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}|310\\d{4}","\\d{7}(?:\\d{3})?"] +,[,,"(?:2(?:04|26|[48]9|50)|3(?:06|43)|4(?:03|1[68]|38|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|47)|7(?:0[059]|[18]0|78)|8(?:[06]7|19|)|90[25])[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] +,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}|310\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"900[2-9]\\d{6}","\\d{10}"] ,[,,"NA","NA"] ,[,,"5(?:00|33|44)[2-9]\\d{6}","\\d{10}"] @@ -899,7 +899,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"CH":[,[,,"[2-9]\\d{8}","\\d{9}"] ,[,,"(?:2[12467]|3[1-4]|4[134]|5[12568]|6[12]|[7-9]1)\\d{7}","\\d{9}"] ,[,,"7[46-9]\\d{7}","\\d{9}"] @@ -930,16 +930,18 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] -,"CK":[,[] -,[] -,[] +,1] +,"CK":[,[,,"[2-57]\\d{4}","\\d{5}"] +,[,,"(?:2\\d|3[13-7]|4[1-5])\\d{3}","\\d{5}"] +,[,,"(?:5[0-68]|7\\d)\\d{3}","\\d{5}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"CK",682,"00","00",,,"00",,,1,,,[,,"NA","NA"] +,"CK",682,"00",,,,,,,,[[,"(\\d{2})(\\d{3})","$1 $2",,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -1194,8 +1196,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"DM":[,[,,"[7-9]\\d{9}","\\d{7,10}"] -,[,,"767(?:2(?:55|66)|4(?:2[01]|4[0-25-9])|50[0-4])\\d{4}","\\d{7,10}"] +,"DM":[,[,,"[57-9]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"767(?:2(?:55|66)|4(?:2[01]|4[0-25-9])|50[0-4])\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"767(?:2(?:[2346]5|7[5-7])|31[5-7]|61[4-6])\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -1206,9 +1208,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"767",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"DO":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"8[024]9[2-9]\\d{6}","\\d{7,10}"] -,[,,"8[024]9[2-9]\\d{6}","\\d{7,10}"] +,"DO":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"8[024]9[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] +,[,,"8[024]9[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] ,[,,"NA","NA"] @@ -1263,15 +1265,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"EE":[,[,,"[3-9]\\d{6,7}|800\\d{6,7}","\\d{6,10}"] +,"EE":[,[,,"[3-9]\\d{6,7}|800\\d{6,7}","\\d{7,10}"] ,[,,"(?:3[23589]|4(?:0\\d|[3-8])|6\\d|7[1-9]|88)\\d{5}","\\d{7,8}"] ,[,,"(?:5\\d|8[1-5])\\d{6}|5(?:[02]\\d{2}|1(?:[0-8]\\d|95)|5[0-478]\\d|64[0-4]|65[1-589])\\d{3}","\\d{7,8}"] ,[,,"800(?:0\\d{3}|1\\d|[2-9])\\d{3}","\\d{7,10}"] ,[,,"900\\d{4}","\\d{7}"] ,[,,"NA","NA"] -,[,,"70[0-2]?\\d{5}","\\d{7,8}"] +,[,,"70[0-2]\\d{5}","\\d{8}"] ,[,,"NA","NA"] -,"EE",372,"00",,,,,,,,[[,"([34-79]\\d{2})(\\d{4})","$1 $2",["[3679]|4[3-8]|5(?:[0-2]|5[0-478]|6[45])","[3679]|4[3-8]|5(?:[02]|1(?:[0-8]|95)|5[0-478]|6(?:4[0-4]|5[1-589]))"] +,"EE",372,"00",,,,,,,,[[,"([34-79]\\d{2})(\\d{4})","$1 $2",["[369]|4[3-8]|5(?:[0-2]|5[0-478]|6[45])|7[1-9]","[369]|4[3-8]|5(?:[02]|1(?:[0-8]|95)|5[0-478]|6(?:4[0-4]|5[1-589]))|7[1-9]"] ,"",""] ,[,"(70)(\\d{2})(\\d{4})","$1 $2 $3",["70"] ,"",""] @@ -1333,7 +1335,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,"ET":[,[,,"[1-59]\\d{8}","\\d{7,9}"] ,[,,"(?:11(?:1(?:1[124]|2[2-57]|3[1-5]|5[5-8]|8[6-8])|2(?:13|3[6-8]|5[89]|7[05-9]|8[2-6])|3(?:2[01]|3[0-289]|4[1289]|7[1-4]|87)|4(?:1[69]|3[2-49]|4[0-23]|6[5-8])|5(?:1[57]|44|5[0-4])|6(?:18|2[69]|4[5-7]|5[1-5]|6[0-59]|8[015-8]))|2(?:2(?:11[1-9]|22[0-7]|33\\d|44[1467]|66[1-68])|5(?:11[124-6]|33[2-8]|44[1467]|55[14]|66[1-3679]|77[124-79]|880))|3(?:3(?:11[0-46-8]|22[0-6]|33[0134689]|44[04]|55[0-6]|66[01467])|4(?:44[0-8]|55[0-69]|66[0-3]|77[1-5]))|4(?:6(?:22[0-24-7]|33[1-5]|44[13-69]|55[14-689]|660|88[1-4])|7(?:11[1-9]|22[1-9]|33[13-7]|44[13-6]|55[1-689]))|5(?:7(?:227|55[05]|(?:66|77)[14-8])|8(?:11[149]|22[013-79]|33[0-68]|44[013-8]|550|66[1-5]|77\\d)))\\d{4}","\\d{7,9}"] -,[,,"91(?:1(?:[146]\\d|2[0-5]|3[4-6]|50|7[2-6]|8[46-9])|31\\d|4(?:3[0-2489]|7[0-3])|5(?:3[23]|7[3-5])|6(?:58|8[23])|7(?:5[57]|8[01])|8(?:3[45]|7[67]))\\d{4}","\\d{9}"] +,[,,"91[0-8]\\d{6}","\\d{9}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -1345,7 +1347,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"FI":[,[,,"[1-9]\\d{4,11}","\\d{5,12}"] +,"FI":[,[,,"1\\d{4,11}|[2-9]\\d{4,10}","\\d{5,12}"] ,[,,"1(?:[35689][1-8]\\d{3,9}|[47]\\d{5,10})|2[1-8]\\d{3,9}|3(?:[1-8]\\d{3,9}|9\\d{4,8})|[5689][1-8]\\d{3,9}|","\\d{5,12}"] ,[,,"4\\d{5,10}|50\\d{4,8}","\\d{6,11}"] ,[,,"800\\d{4,7}","\\d{7,10}"] @@ -1376,15 +1378,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"FK":[,[] -,[] -,[] +,"FK":[,[,,"[2-7]\\d{4}","\\d{5}"] +,[,,"[2-47]\\d{4}","\\d{5}"] +,[,,"[56]\\d{4}","\\d{5}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"FK",500,"00","0",,,"0",,,1,,,[,,"NA","NA"] +,"FK",500,"00",,,,,,,,,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -1447,7 +1449,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"GB":[,[,,"\\d{7,10}","\\d{4,10}"] ,[,,"2(?:0[01378]|3[0189]|4[017]|8[0-46-9]|9[012])\\d{7}|1(?:(?:1(?:3[0-48]|[46][0-4]|5[012789]|7[0-39]|8[01349])|21[0-7]|31[0-8]|[459]1\\d|61[0-46-9]))\\d{6}|1(?:2(?:0[024-9]|2[3-9]|3[3-79]|4[1-689]|[58][02-9]|6[0-4789]|7[013-9]|9\\d)|3(?:0\\d|[25][02-9]|3[02-579]|[468][0-46-9]|7[1235679]|9[24578])|4(?:0[03-9]|[28][02-5789]|[37]\\d|4[02-69]|5[0-8]|[69][0-79])|5(?:0[1235-9]|2[024-9]|3[015689]|4[02-9]|5[03-9]|6\\d|7[0-35-9]|8[0-468]|9[0-5789])|6(?:0[034689]|2[0-35689]|[38][013-9]|4[1-467]|5[0-69]|6[13-9]|7[0-8]|9[0124578])|7(?:0[0246-9]|2\\d|3[023678]|4[03-9]|5[0-46-9]|6[013-9]|7[0-35-9]|8[024-9]|9[02-9])|8(?:0[35-9]|2[1-5789]|3[02-578]|4[0-578]|5[124-9]|6[2-69]|7\\d|8[02-9]|9[02569])|9(?:0[02-589]|2[02-689]|3[1-5789]|4[2-9]|5[0-579]|6[234789]|7[0124578]|8\\d|9[2-57]))\\d{6}|1(?:2(?:0(?:46[1-4]|87[2-9])|545[1-79]|76(?:2\\d|3[1-8]|6[1-6])|9(?:7(?:2[0-4]|3[2-5])|8(?:2[2-8]|7[0-4789]|8[345])))|3(?:638[2-5]|647[23]|8(?:47[04-9]|64[015789]))|4(?:044[1-7]|20(?:2[23]|8\\d)|6(?:0(?:30|5[2-57]|6[1-8]|7[2-8])|140)|8(?:052|87[123]))|5(?:24(?:3[2-79]|6\\d)|276\\d|6(?:26[06-9]|686))|6(?:06(?:4\\d|7[4-79])|295[567]|35[34]\\d|47(?:24|61)|59(?:5[08]|6[67]|74)|955[0-4])|7(?:26(?:6[13-9]|7[0-7])|442\\d|50(?:2[0-3]|[3-68]2|76))|8(?:27[56]\\d|37(?:5[2-5]|8[239])|84(?:3[2-58]))|9(?:0(?:0(?:6[1-8]|85)|52\\d)|3583|4(?:66[1-8]|9(?:2[01]|81))|63(?:23|3[1-4])|9561))\\d{3}|176888[234678]\\d{2}|16977[23]\\d{3}","\\d{4,10}"] ,[,,"7(?:[1-4]\\d\\d|5(?:0[0-8]|[13-9]\\d|2[0-35-9])|7(?:0[1-9]|[1-7]\\d|8[02-9]|9[0-689])|8(?:[014-9]\\d|[23][0-8])|9(?:[04-9]\\d|1[02-9]|2[0135-9]|3[0-689]))\\d{6}","\\d{10}"] @@ -1481,8 +1483,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,1,,[,,"NA","NA"] ,[,,"(?:3[0347]|55)\\d{8}","\\d{10}"] ] -,"GD":[,[,,"[489]\\d{9}","\\d{7,10}"] -,[,,"473(?:2(?:3[0-2]|69)|3(?:2[89]|86)|4(?:[06]8|3[5-9]|4[0-49]|5[5-79]|73|90)|63[68]|7(?:58|84)|938)\\d{4}","\\d{7,10}"] +,"GD":[,[,,"[4589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"473(?:2(?:3[0-2]|69)|3(?:2[89]|86)|4(?:[06]8|3[5-9]|4[0-49]|5[5-79]|73|90)|63[68]|7(?:58|84)|938)\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"473(?:4(?:0[3-79]|1[04-9]|20|58)|53[3-8])\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -1493,19 +1495,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"473",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"GE":[,[,,"[1-579]\\d{7}|8\\d{8}","\\d{5,9}"] -,[,,"(?:122|2(?:22|36|5[035])|3(?:1[0-35-8]|3[1-35679]|4\\d|7[0-39]|9[1-35-7])|3(?:[256]\\d|4[124-9]|7[0-4])|4(?:1\\d|2[2-7]|3[1-79]|4[2-8]|7[239]|9[1-7]))\\d{5}","\\d{5,8}"] -,[,,"(?:5[1578]|6[28]|7[0147-9]|9[0135-9])\\d{6}","\\d{8}"] +,"GE":[,[,,"[13-79]\\d{7}|8\\d{8}","\\d{5,9}"] +,[,,"(?:3(?:[256]\\d|4[124-9]|7[0-4])|4(?:1\\d|2[2-7]|3[1-79]|4[2-8]|7[239]|9[1-7]))\\d{5}","\\d{5,8}"] +,[,,"(?:14|5[01578]|6[28]|7[0147-9]|9[0-35-9])\\d{6}","\\d{8}"] ,[,,"800\\d{6}","\\d{9}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"GE",995,"8~10","8",,,"8",,,,[[,"(32)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["32"] -,"8 ($1)",""] -,[,"(\\d{3})(\\d)(\\d{2})(\\d{2})","$1 $2 $3 $4",["[24]|3[13-79]"] -,"8 ($1)",""] -,[,"(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["[5679]"] +,"GE",995,"8~10","8",,,"8",,,,[[,"(\\d{2})(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["[13-79]"] ,"8 $1",""] ,[,"(800)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["8"] ,"8 $1",""] @@ -1656,21 +1654,26 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"GT":[,[] -,[] -,[] +,"GT":[,[,,"[2-7]\\d{7}|1[89]\\d{9}","\\d{8}(?:\\d{3})?"] +,[,,"[267][2-9]\\d{6}","\\d{8}"] +,[,,"[345]\\d{7}","\\d{8}"] +,[,,"18[01]\\d{8}","\\d{11}"] +,[,,"19\\d{9}","\\d{11}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,[,,"NA","NA"] -,[,,"NA","NA"] -,"GT",502,"00",,,,,,,1,,,[,,"NA","NA"] +,"GT",502,"00",,,,,,,,[[,"(\\d{4})(\\d{4})","$1 $2",["[2-7]"] +,"",""] +,[,"(\\d{4})(\\d{3})(\\d{4})","$1 $2 $3",["1"] +,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"GU":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"671(?:3\\d{2}|47\\d|56\\d|6[3-5]\\d|7(?:3\\d|89)|828)\\d{4}","\\d{7,10}"] -,[,,"671(?:3\\d{2}|47\\d|56\\d|6[3-5]\\d|7(?:3\\d|89)|828)\\d{4}","\\d{7,10}"] +,"GU":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[23678])|5(?:55|6[2-5]|88)|6(?:3[2-578]|4[24-9]|5[34]|78|8[5-9])|7(?:[079]7|2[0167]|3[45]|8[789])|8(?:[2-5789]8|6[48])|9(?:2[29]|6[79]|7[179]|8[789]|9[78]))\\d{4}","\\d{7}(?:\\d{3})?"] +,[,,"671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[23678])|5(?:55|6[2-5]|88)|6(?:3[2-578]|4[24-9]|5[34]|78|8[5-9])|7(?:[079]7|2[0167]|3[45]|8[789])|8(?:[2-5789]8|6[48])|9(?:2[29]|6[79]|7[179]|8[789]|9[78]))\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] ,[,,"NA","NA"] @@ -1896,15 +1899,15 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"3(?:08162\\d|3\\d{5}|4(?:40[49]06|5624\\d)|7(?:0624\\d|2299\\d))\\d{3}|55\\d{8}","\\d{10}"] ] -,"IN":[,[,,"[1-9]\\d{9,10}","\\d{6,11}"] +,"IN":[,[,,"1\\d{7,11}|[2-9]\\d{9,10}","\\d{6,12}"] ,[,,"(?:11|2[02]|33|4[04]|79|80)[2-6]\\d{7}|(?:1(?:2[0-249]|3[0-25]|4[145]|[59][14]|6[014]|7[1257]|8[01346])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[126-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:[136][25]|22|4[28]|5[12]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)|7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)|8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91))[2-6]\\d{6}|(?:(?:1(?:2[35-8]|3[346-9]|4[236-9]|[59][0235-9]|6[235-9]|7[34689]|8[257-9])|2(?:1[134689]|3[24-8]|4[2-8]|5[25689]|6[2-4679]|7[13-79]|8[2-479]|9[235-9])|3(?:01|1[79]|2[1-5]|4[25-8]|5[125689]|6[235-7]|7[157-9]|8[2-467])|4(?:1[14578]|2[5689]|3[2-467]|5[4-7]|6[35]|73|8[2689]|9[2389])|5(?:[16][146-9]|2[14-8]|3[1346]|4[14-69]|5[46]|7[2-4]|8[2-8]|9[246])|6(?:1[1358]|2[2457]|3[2-4]|4[235-7]|5[2-689]|6[24-58]|7[23-689]|8[1-6])|8(?:1[1357-9]|2[235-8]|3[03-57-9]|4[0-24-9]|5\\d|6[2457-9]|7[1-6]|8[1256]|9[2-4]))\\d|7(?:(?:1[013-9]|2[0235-9]|3[2679]|4[1-35689]|5[2-46-9]|[67][02-9]|9\\d)\\d|8(?:2[0-6]|[013-8]\\d)))[2-6]\\d{5}","\\d{6,10}"] -,[,,"(?:7(?:39[89]|5(?:50|6[6-8]|79|[89][7-9])|6(?:0[027]|20|3[19]|54|65|7[67]|9[6-9])|7(?:0[89]|3[589]|42|60|9[5-9])|8(?:[03][07-9]|14|2[7-9]|4[25]|6[09]))\\d|9\\d{4}|8(?:(?:0[01589]|1[024])\\d|8(?:[079]\\d|44)|9[057-9]\\d)\\d)\\d{5}","\\d{10}"] -,[,,"1(?:800\\d?|600)\\d{6}","\\d{10,11}"] +,[,,"(?:7(?:2(?:0[04-9]|5[09]|7[568]|9[39])|3(?:07|7[3679]|9[689])|4(?:05|1[15-9]|[29][89]|39|8[389])|5(?:0[0-5]|[47]9|50|6[6-9]|[89][7-9])|6(?:0[027]|12|20|3[19]|5[45]|6[5-9]|7[67]|9[6-9])|7(?:0[289]|3[5-9]|42|60|9[5-9])|8(?:[03][07-9]|14|2[7-9]|4[25]|6[09]|7[015689]|9[0357-9]))\\d|9\\d{4}|8(?:(?:0[01589]|1[24]|2[2369]|4[023458]|52|6[0589]|7[2569])\\d|8(?:[079]\\d|44)|9[057-9]\\d)\\d)\\d{5}","\\d{10}"] +,[,,"1(?:600\\d{6}|800\\d{4,8})","\\d{8,12}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"IN",91,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{2})(\\d{6})","$1 $2 $3",["7(?:39|5[5-9]|[67][02-9]|8[0-6])|8(?:0[01589]|1[024]|8[0479]|9[057-9])|9","7(?:39|5(?:50|[6-9])|[67][02-9]|8[0-6])|8(?:0[01589]|1[024]|8(?:[079]|44)|9[057-9])|9"] +,"IN",91,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{2})(\\d{6})","$1 $2 $3",["7(?:2[0579]|39|4[0-389]|5[04-9]|6|7[02-9]|8[0-79])|8(?:0[01589]|1[024]|8[0479]|9[057-9])|9","7(?:2[0579]|39|4[0-389]|5(?:0[0-5]|49|50|[6-9])|6|7[02-9]|8[0-79])|8(?:0[01589]|1[024]|8(?:[079]|44)|9[057-9])|9"] ,"0$1",""] ,[,"(\\d{2})(\\d{4})(\\d{4})","$1 $2 $3",["11|2[02]|33|4[04]|79|80[2-6]"] ,"0$1",""] @@ -1928,22 +1931,26 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,"0$1",""] ,[,"(1600)(\\d{2})(\\d{4})","$1 $2 $3",["160","1600"] ,"$1",""] -,[,"(18[06]0)(\\d{2,3})(\\d{4})","$1 $2 $3",["18[06]","18[06]0"] +,[,"(1800)(\\d{4,5})","$1 $2",["180","1800"] +,"$1",""] +,[,"(18[06]0)(\\d{2,4})(\\d{4})","$1 $2 $3",["18[06]","18[06]0"] ,"$1",""] ] ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"1860345\\d{4}","\\d{11}"] ] -,"IO":[,[] -,[] -,[] +,"IO":[,[,,"3\\d{6}","\\d{7}"] +,[,,"37\\d{5}","\\d{7}"] +,[,,"38\\d{5}","\\d{7}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"IO",246,"00",,,,,,,1,,,[,,"NA","NA"] +,"IO",246,"00",,,,,,,,[[,"(\\d{3})(\\d{4})","$1 $2",,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -2030,7 +2037,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"JE":[,[,,"[135789]\\d{6,9}","\\d{6,10}"] ,[,,"1534\\d{6}","\\d{6,10}"] ,[,,"7(?:509|7(?:00|97)|829|937)\\d{6}","\\d{10}"] @@ -2043,8 +2050,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"3(?:0(?:07(?:35|81)|8901)|3\\d{4}|4(?:4(?:4(?:05|42|69)|703)|5(?:041|800))|7(?:0002|1206))\\d{4}|55\\d{8}","\\d{10}"] ] -,"JM":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"876(?:(?:5[0-26]|6\\d|7[1-6]|9[2-8])\\d{5}|(?:7(?:0[2-689]|8[056]|9[45])|9(?:0[1-8]|1[02378]|9[2-468]))\\d{4})","\\d{7,10}"] +,"JM":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"876(?:(?:5[0-26]|6\\d|7[1-6]|9[2-8])\\d{5}|(?:7(?:0[2-689]|8[056]|9[45])|9(?:0[1-8]|1[02378]|9[2-468]))\\d{4})","\\d{7}(?:\\d{3})?"] ,[,,"876(?:(?:21|[348]\\d|5[78]|77)\\d|7(?:0[07]|8[1-47-9]|9[0-36-9])|9(?:[01]9|9[0579]))\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -2055,12 +2062,12 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"876",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"JO":[,[,,"[235-9]\\d{7,8}","\\d{8,9}"] +,"JO":[,[,,"[235-9]\\d{7,8}","\\d{7,9}"] ,[,,"[2356][2-8]\\d{6}","\\d{7,8}"] ,[,,"7(?:[1-8]\\d|9[02-9])\\d{6}","\\d{9}"] ,[,,"80\\d{6}","\\d{8}"] ,[,,"900\\d{5}","\\d{8}"] -,[,,"8(?:10\\d|5\\d{2}|7(?:[02]0|7[08]|9[09]))\\d{4}","\\d{8}"] +,[,,"85\\d{6}","\\d{8}"] ,[,,"70\\d{7}","\\d{9}"] ,[,,"NA","NA"] ,"JO",962,"00","0",,,"0",,,,[[,"(\\d)(\\d{3})(\\d{4})","$1 $2 $3",["[2356]"] @@ -2072,7 +2079,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,,[,,"NA","NA"] ,,,[,,"NA","NA"] -,[,,"NA","NA"] +,[,,"8(?:10|[78]\\d)\\d{5}","\\d{8}"] ] ,"JP":[,[,,"\\d{9,10}","\\d{9,10}"] ,[,,"(?:1(?:1[236-8]|2[3-6]|3[3-9]|4[2-6]|[58][2-8]|6[2-7]|7[2-9]|9[1-8])|2[2-9]\\d|[36][1-9]\\d|4(?:6[0235-8]|[2-578]\\d|9[2-59])|5(?:6[1-9]|7[2-8]|[2-589]\\d)|7(?:3[4-9]|4[02-9]|[25-9]\\d)|8(?:3[2-9]|4[5-9]|5[1-9]|8[03-9]|[2679]\\d)|9(?:[679][1-9]|[2-58]\\d))\\d{6}","\\d{9}"] @@ -2154,15 +2161,17 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KI":[,[] -,[] -,[] +,"KI":[,[,,"[2-689]\\d{4}","\\d{5}"] +,[,,"(?:[234]\\d|50|8[1-5])\\d{3}","\\d{5}"] +,[,,"[69]\\d{4}","\\d{5}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"KI",686,"00","0",,,"0",,,1,,,[,,"NA","NA"] +,"KI",686,"00","0",,,"0",,,,[[,"(\\d{5})","$1",,"0$1",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -2180,8 +2189,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KN":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"869(?:2(?:29|36)|4(?:6[5-9]|70))\\d{4}","\\d{7,10}"] +,"KN":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"869(?:2(?:29|36)|4(?:6[5-9]|70))\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"869(?:5(?:5[6-8]|6[5-7])|66[2-9]|76[2-5])\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -2241,7 +2250,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ] ,"KW":[,[,,"[12569]\\d{6,7}","\\d{7,8}"] ,[,,"(?:18\\d|2(?:[23]\\d{2}|4[1-35-9]\\d|5(?:0[034]|[2-46]\\d|5[1-3]|7[1-7])))\\d{4}","\\d{7,8}"] -,[,,"(?:5(?:0[02]|5\\d)|6(?:0[034679]|5[015-9]|6\\d|7[067])|9(?:0[09]|4[049]|[79]\\d))\\d{5}","\\d{8}"] +,[,,"(?:5(?:0[0-2]|5\\d)|6(?:0[034679]|5[015-9]|6\\d|7[067]|99)|9(?:0[09]|4[049]|66|[79]\\d))\\d{5}","\\d{8}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -2256,8 +2265,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KY":[,[,,"[389]\\d{9}","\\d{7,10}"] -,[,,"345(?:2(?:22|44)|444|6(?:23|38|40)|7(?:6[6-9]|77)|8(?:00|1[45]|25|4[89]|88)|9(?:14|4[035-9]))\\d{4}","\\d{7,10}"] +,"KY":[,[,,"[3589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"345(?:2(?:22|44)|444|6(?:23|38|40)|7(?:6[6-9]|77)|8(?:00|1[45]|25|4[89]|88)|9(?:14|4[035-9]))\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"345(?:32[3-79]|5(?:1[467]|2[5-7]|4[5-9])|9(?:1[679]|2[4-9]|3[89]))\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}|345976\\d{4}","\\d{10}"] @@ -2268,16 +2277,16 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"345",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"KZ":[,[,,"(?:[67]\\d{2}|80[09])\\d{7}","\\d{10}"] -,[,,"7(?:1(?:0(?:[23]\\d|4[023]|59|63)|1(?:[23]\\d|4[0-79]|59)|2(?:[23]\\d|59)|3(?:2\\d|3[1-7]|4[1235-9]|59)|4(?:2\\d|3[013-79]|4[0-58]|5[1-79])|5(?:2\\d|3[1-8]|4[1-7]|59)|6(?:22|[34]\\d|5[19])|72\\d|8(?:[27]\\d|3[1-46-9]|4[0-4]|))|2(?:1(?:[23]\\d|4[46-9]|5[3469])|2(?:2\\d|3[0679]|46|5[12679]|)|3(?:[234]\\d|5[139]|)|4(?:22|3[1235-8])|5(?:[23]\\d|4[0124-8]|59)|6(?:22|3[1-9]|4[0-4]|59)|7(?:[23]\\d|40|5[279]|7\\d)|8(?:[23]\\d|4[0-3]|59)|9(?:2\\d|3[12478]|59))|3622)\\d{5}","\\d{10}"] -,[,,"7(?:0[01257]\\d{2}|1[2-578]9[01]|2(?:[13-6]9[01]|7(?:58|9[01]))|6[02-4]\\d{2}|7[157]\\d{2})\\d{5}|6\\d{9}","\\d{10}"] +,"KZ":[,[,,"(?:7\\d{2}|80[09])\\d{7}","\\d{10}"] +,[,,"7(?:1(?:0(?:[23]\\d|4[023]|59|63)|1(?:[23]\\d|4[0-79]|59)|2(?:[23]\\d|59)|3(?:2\\d|3[1-79]|4[0-35-9]|59)|4(?:2\\d|3[013-79]|4[0-8]|5[1-79])|5(?:2\\d|3[1-8]|4[1-7]|59)|6(?:2\\d|[34]\\d|5[19]|61)|72\\d|8(?:[27]\\d|3[1-46-9]|4[0-5]|))|2(?:1(?:[23]\\d|4[46-9]|5[3469])|2(?:2\\d|3[0679]|46|5[12679]|)|3(?:[234]\\d|5[139]|)|4(?:2\\d|3[1235-9]|59)|5(?:[23]\\d|4[01246-8]|59|61)|6(?:2\\d|3[1-9]|4[0-4]|59)|7(?:[23]\\d|40|5[279]|7\\d)|8(?:[23]\\d|4[0-3]|59)|9(?:2\\d|3[124578]|59))|3622)\\d{5}","\\d{10}"] +,[,,"7(?:0[01257]\\d{2}|6[02-4]\\d{2}|7[157]\\d{2})\\d{5}","\\d{10}"] ,[,,"800\\d{7}","\\d{10}"] ,[,,"809\\d{7}","\\d{10}"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,[,,"NA","NA"] +,[,,"751\\d{7}","\\d{10}"] ,"KZ",7,"8~10","8",,,"8",,,,,,[,,"NA","NA"] -,,,[,,"NA","NA"] +,,,[,,"751\\d{7}","\\d{10}"] ,[,,"NA","NA"] ] ,"LA":[,[,,"[2-57]\\d{7,9}","\\d{6,10}"] @@ -2314,8 +2323,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"LC":[,[,,"[789]\\d{9}","\\d{7,10}"] -,[,,"758(?:234|4(?:5[0-9]|6[2-9]|8[0-2])|638|758)\\d{4}","\\d{7,10}"] +,"LC":[,[,,"[5789]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"758(?:234|4(?:5[0-9]|6[2-9]|8[0-2])|638|758)\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"758(?:28[4-7]|384|4(?:6[01]|8[4-9])|5(?:1[89]|20|84)|7(?:1[2-9]|2[0-4]))\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -2532,17 +2541,22 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"ME":[,[] -,[] -,[] -,[,,"NA","NA"] -,[,,"NA","NA"] -,[,,"NA","NA"] +,"ME":[,[,,"[2-9]\\d{7,8}","\\d{6,9}"] +,[,,"(?:20[2-8]|3(?:0[2-7]|1[35-7]|2[367]|3[4-7])|4(?:0[237]|1[2467])|5(?:0[47]|1[27]|2[378]))\\d{5}","\\d{6,8}"] +,[,,"6(?:32\\d|[89]\\d{2}|7(?:[0-8]\\d|9(?:[3-9]|[0-2]\\d)))\\d{4}","\\d{8,9}"] +,[,,"800[28]\\d{4}","\\d{8}"] +,[,,"(?:88\\d|9(?:4[13-8]|5[16-8]))\\d{5}","\\d{8}"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"ME",382,"99","0",,,"0",,,1,,,[,,"NA","NA"] +,[,,"78[134579]\\d{5}","\\d{8}"] +,"ME",382,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{3})(\\d{3})","$1 $2 $3",["[2-57-9]|6[3789]","[2-57-9]|6(?:[389]|7(?:[0-8]|9[3-9]))"] +,"0$1",""] +,[,"(67)(9)(\\d{3})(\\d{3})","$1 $2 $3 $4",["679","679[0-2]"] +,"0$1",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] -,[,,"NA","NA"] +,[,,"77\\d{6}","\\d{8}"] ] ,"MG":[,[,,"[23]\\d{8}","\\d{7,9}"] ,[,,"2(?:0(?:(?:2\\d|4[47]|5[3467]|6[279]|8[268]|9[245])\\d|7(?:2[29]|[35]\\d))|210\\d)\\d{4}","\\d{7,9}"] @@ -2640,8 +2654,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MN":[,[,,"[12]\\d{7,9}|[57-9]\\d{7}","\\d{8,10}"] -,[,,"[12](?:1\\d|2(?:[1-3]\\d?|7\\d)|3[2-8]\\d{1,2}|4[2-68]\\d{1,2}|5[1-4689]\\d{1,2})\\d{5}|(?:5[0568]|70)\\d{6}","\\d{8,10}"] +,"MN":[,[,,"[12]\\d{7,9}|[57-9]\\d{7}","\\d{6,10}"] +,[,,"[12](?:1\\d|2(?:[1-3]\\d?|7\\d)|3[2-8]\\d{1,2}|4[2-68]\\d{1,2}|5[1-4689]\\d{1,2})\\d{5}|(?:5[0568]|70)\\d{6}","\\d{6,10}"] ,[,,"(?:8[89]|9[15689])\\d{6}","\\d{8}"] ,[,,"NA","NA"] ,[,,"NA","NA"] @@ -2677,9 +2691,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MP":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7,10}"] -,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7,10}"] +,"MP":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7}(?:\\d{3})?"] +,[,,"670(?:2(?:3[3-5]|88|56)|32[23]|4[38]3|532|6(?:64|70|8\\d))\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] ,[,,"NA","NA"] @@ -2701,25 +2715,22 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MR":[,[,,"[2-4]\\d{6,7}|[5-7]\\d{6}|8\\d{7}","\\d{7,8}"] -,[,,"5(?:1[035]|2[0-69]|3[0348]|4[468]|5[02-467]|6[39]|7[4-69])\\d{4}|[2-4]5\\d{6}","\\d{7,8}"] -,[,,"(?:[23][0-4]|4[3-5]|6\\d|7[0-7])\\d{5}|(?:2[27]|3[367]|4[467])\\d{6}","\\d{7,8}"] +,"MR":[,[,,"[2-48]\\d{7}","\\d{8}"] +,[,,"25[08]\\d{5}|35\\d{6}|45[1-7]\\d{5}","\\d{8}"] +,[,,"(?:2(?:2\\d|70)|3(?:3\\d|6[1-36]|7[1-3])|4(?:4\\d|6[0457-9]|7[4-9]))\\d{5}","\\d{8}"] ,[,,"800\\d{5}","\\d{8}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"MR",222,"00",,,,,,,,[[,"([2-48]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",["[2-48]"] -,"",""] -,[,"([2-7]\\d{2})(\\d{2})(\\d{2})","$1 $2 $3",["[2-7]"] -,"",""] +,"MR",222,"00",,,,,,,,[[,"([2-48]\\d)(\\d{2})(\\d{2})(\\d{2})","$1 $2 $3 $4",,"",""] ] ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MS":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"664491\\d{4}","\\d{7,10}"] +,"MS":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"664491\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"664492\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -2758,15 +2769,18 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"MV":[,[,,"[3679]\\d{6}","\\d{7}"] -,[,,"(?:3(?:00|3[0-59]|)|6(?:[567][02468]|8[024689]))\\d{4}","\\d{7}"] -,[,,"(?:7(?:[679]\\d|8[02-9])|9[6-9]\\d)\\d{4}","\\d{7}"] -,[,,"NA","NA"] +,"MV":[,[,,"[367]\\d{6}|9(?:00\\d{7}|\\d{6})","\\d{7,10}"] +,[,,"(?:3(?:0[01]|3[0-59]|)|6(?:[567][02468]|8[024689]|90))\\d{4}","\\d{7}"] +,[,,"(?:7[36-9]|9[6-9])\\d{5}","\\d{7}"] ,[,,"NA","NA"] +,[,,"900\\d{7}","\\d{10}"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"MV",960,"0(?:0|19)",,,,,,"00",,[[,"(\\d{3})(\\d{4})","$1-$2",,"",""] +,"MV",960,"0(?:0|19)",,,,,,"00",,[[,"(\\d{3})(\\d{4})","$1-$2",["[367]|9(?:[1-9]|0[1-9])"] +,"",""] +,[,"(\\d{3})(\\d{3})(\\d{4})","$1 $2 $3",["900"] +,"",""] ] ,,[,,"781\\d{4}","\\d{7}"] ,,,[,,"NA","NA"] @@ -2912,7 +2926,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"NF":[,[] ,[] ,[] @@ -2984,7 +2998,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ] ,"NO":[,[,,"0\\d{4}|[2-9]\\d{7}","\\d{5}(?:\\d{3})?"] -,[,,"0\\d{4}|(?:2[1-4]|3[1-3578]|5[1-35-7]|6[1-4679]|7\\d)\\d{6}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}","\\d{5}(?:\\d{3})?"] +,[,,"(?:2[1-4]|3[1-3578]|5[1-35-7]|6[1-4679]|7[0-8])\\d{6}","\\d{8}"] ,[,,"(?:4[015-8]|9\\d)\\d{6}","\\d{8}"] ,[,,"80[01]\\d{5}","\\d{8}"] ,[,,"82[09]\\d{5}","\\d{8}"] @@ -2997,9 +3011,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,"",""] ] ,,[,,"NA","NA"] -,,,[,,"NA","NA"] -,[,,"NA","NA"] -] +,1,,[,,"NA","NA"] +,[,,"0\\d{4}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}","\\d{5}(?:\\d{3})?"] +,1] ,"NP":[,[,,"[1-8]\\d{5,7}|98[45]\\d{7}","\\d{6,10}"] ,[,,"(?:1[014-6]|2[13-79]|3[135-8]|4[146-9]|5[135-7]|6[13-9]|7[15-9]|8[1-4679]|9[1-79])\\d{6}","\\d{6,8}"] ,[,,"98[45]\\d{7}","\\d{10}"] @@ -3230,9 +3244,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"PR":[,[,,"[789]\\d{9}","\\d{7,10}"] -,[,,"(?:787|939)[2-9]\\d{6}","\\d{7,10}"] -,[,,"(?:787|939)[2-9]\\d{6}","\\d{7,10}"] +,"PR":[,[,,"[5789]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"(?:787|939)[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] +,[,,"(?:787|939)[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] ,[,,"NA","NA"] @@ -3378,7 +3392,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ,"RU",7,"8~10","8",,,"8",,,,[[,"([3489]\\d{2})(\\d{3})(\\d{2})(\\d{2})","$1 $2-$3-$4",["[34689]"] ,"8 ($1)",""] -,[,"([67]\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",["[67]"] +,[,"(7\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",["7"] ,"8 ($1)",""] ] ,,[,,"NA","NA"] @@ -3568,6 +3582,18 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] +,"SJ":[,[,,"0\\d{4}|[4789]\\d{7}","\\d{5}(?:\\d{3})?"] +,[,,"79\\d{6}","\\d{8}"] +,[,,"(?:4[015-8]|9\\d)\\d{6}","\\d{8}"] +,[,,"80[01]\\d{5}","\\d{8}"] +,[,,"82[09]\\d{5}","\\d{8}"] +,[,,"810(?:0[0-6]|[2-8]\\d)\\d{3}","\\d{8}"] +,[,,"880\\d{5}","\\d{8}"] +,[,,"NA","NA"] +,"SJ",47,"00",,,,,,,,,,[,,"NA","NA"] +,,,[,,"NA","NA"] +,[,,"0\\d{4}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}","\\d{5}(?:\\d{3})?"] +,1] ,"SK":[,[,,"[2-689]\\d{8}","\\d{9}"] ,[,,"[2-5]\\d{8}","\\d{9}"] ,[,,"9(?:0[1-8]|1[0-24-9]|4[0489])\\d{6}","\\d{9}"] @@ -3626,7 +3652,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"SN":[,[,,"[37]\\d{8}","\\d{9}"] ,[,,"3(?:010|3(?:8[1-9]|9[2-9]))\\d{5}","\\d{9}"] ,[,,"7(?:0[1256]0|6(?:1[23]|2[89]|3[3489]|4[6-9]|5[1-389]|6[6-9]|7[45]|8[3-8])|7(?:1[014-8]|2[0-7]|3[0-35-8]|4[0-6]|[56]\\d|7[0-589]|8[01]|9[0-6]))\\d{5}","\\d{9}"] @@ -3684,15 +3710,22 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"SV":[,[] -,[] -,[] -,[,,"NA","NA"] -,[,,"NA","NA"] +,"SV":[,[,,"[27]\\d{7}|[89]\\d{6}(?:\\d{4})?","\\d{7,8}|\\d{11}"] +,[,,"2[1-6]\\d{6}","\\d{8}"] +,[,,"7\\d{7}","\\d{8}"] +,[,,"800\\d{4}(?:\\d{4})?","\\d{7}(?:\\d{4})?"] +,[,,"900\\d{4}(?:\\d{4})?","\\d{7}(?:\\d{4})?"] ,[,,"NA","NA"] ,[,,"NA","NA"] ,[,,"NA","NA"] -,"SV",503,"00",,,,,,,1,,,[,,"NA","NA"] +,"SV",503,"00",,,,,,,,[[,"(\\d{4})(\\d{4})","$1 $2",["[27]"] +,"",""] +,[,"(\\d{3})(\\d{4})","$1 $2",["[89]"] +,"",""] +,[,"(\\d{3})(\\d{4})(\\d{4})","$1 $2 $3",["[89]"] +,"",""] +] +,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] @@ -3729,9 +3762,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"0800\\d{4}","\\d{8}"] ,[,,"NA","NA"] -] -,"TC":[,[,,"[689]\\d{9}","\\d{7,10}"] -,[,,"649(?:712|9(?:4\\d|50))\\d{4}","\\d{7,10}"] +,1] +,"TC":[,[,,"[5689]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"649(?:712|9(?:4\\d|50))\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"649(?:2(?:3[12]|4[1-5])|3(?:3[1-39]|4[1-57])|4[34][12])\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -3781,7 +3814,7 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] +,1] ,"TH":[,[,,"[2-8]\\d{7,8}|1\\d{9}","\\d{8,10}"] ,[,,"(?:2[1-9]|3[24-9]|4[2-5]|5[3-6]|7[3-7])\\d{6}","\\d{8}"] ,[,,"8\\d{8}","\\d{9}"] @@ -3905,12 +3938,12 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,[,"(444)(\\d{1})(\\d{3})","$1 $2 $3",["444"] ,"",""] ] -,,[,,"NA","NA"] +,,[,,"512\\d{7}","\\d{10}"] ,,,[,,"NA","NA"] ,[,,"444\\d{4}|850\\d{7}","\\d{7,10}"] ] -,"TT":[,[,,"[89]\\d{9}","\\d{7,10}"] -,[,,"868(?:2(?:01|2[1-4])|6(?:1[4-6]|2[1-9]|[3-6]\\d|7[0-79]|9[0-8])|82[12])\\d{4}","\\d{7,10}"] +,"TT":[,[,,"[589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"868(?:2(?:01|2[1-4])|6(?:07|1[4-6]|2[1-9]|[3-6]\\d|7[0-79]|9[0-8])|82[12])\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"868(?:29\\d|3(?:0[1-9]|1[02-9]|[2-9]\\d)|4(?:[679]\\d|8[0-4])|6(?:20|78|8\\d)|7(?:1[02-9]|[2-9]\\d))\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -4007,9 +4040,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"US":[,[,,"[2-9]\\d{9}","\\d{7,10}"] -,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[04]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7,10}"] -,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[04]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7,10}"] +,"US":[,[,,"[2-9]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[014]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] +,[,,"(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[014]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-29]|78|8[12])|7(?:0[1-46-8]|1[2-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[058]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[059]))[2-9]\\d{6}","\\d{7}(?:\\d{3})?"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] ,[,,"NA","NA"] @@ -4063,9 +4096,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,[,,"NA","NA"] ,,,[,,"NA","NA"] ,[,,"NA","NA"] -] -,"VC":[,[,,"(?:784|8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] -,[,,"784(?:266|3(?:6[6-9]|7\\d|8[0-24-6])|4(?:38|5[0-36-8]|8\\d|9[01])|555|638|784)\\d{4}","\\d{7,10}"] +,1] +,"VC":[,[,,"[5789]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"784(?:266|3(?:6[6-9]|7\\d|8[0-24-6])|4(?:38|5[0-36-8]|8\\d|9[01])|555|638|784)\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"784(?:4(?:3[0-24]|5[45]|9[2-5])|5(?:2[6-9]|3[0-3]|93))\\d{4}","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -4090,8 +4123,8 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,,[,,"NA","NA"] ,[,,"NA","NA"] ] -,"VG":[,[,,"(?:284|8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] -,[,,"284(?:(?:229|4(?:46|9[45])|8(?:52|6[459]))\\d{4}|496[0-5]\\d{3})","\\d{7,10}"] +,"VG":[,[,,"[2589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"284(?:(?:229|4(?:46|9[45])|8(?:52|6[459]))\\d{4}|496[0-5]\\d{3})","\\d{7}(?:\\d{3})?"] ,[,,"284(?:(?:30[0-3]|4(?:4[0-5]|68|99)|54[0-4])\\d{4}|496[6-9]\\d{3})","\\d{10}"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] @@ -4102,9 +4135,9 @@ i18n.phonenumbers.metadata.countryToMetadata = { ,,"284",[,,"NA","NA"] ,[,,"NA","NA"] ] -,"VI":[,[,,"340(?:6[49]2|7[17]\\d)\\d{4}|(?:8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] -,[,,"340(?:6[49]2|7[17]\\d)\\d{4}|(?:8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] -,[,,"340(?:6[49]2|7[17]\\d)\\d{4}|(?:8(?:00|66|77|88)|900)[2-9]\\d{6}","\\d{7,10}"] +,"VI":[,[,,"[3589]\\d{9}","\\d{7}(?:\\d{3})?"] +,[,,"340(?:6[49]2|7[17]\\d)\\d{4}","\\d{7}(?:\\d{3})?"] +,[,,"340(?:6[49]2|7[17]\\d)\\d{4}","\\d{7}(?:\\d{3})?"] ,[,,"8(?:00|55|66|77|88)[2-9]\\d{6}","\\d{10}"] ,[,,"900[2-9]\\d{6}","\\d{10}"] ,[,,"NA","NA"] diff --git a/javascript/i18n/phonenumbers/phonemetadata.pb.js b/javascript/i18n/phonenumbers/phonemetadata.pb.js index 1d6797145..3cf881cdf 100644 --- a/javascript/i18n/phonenumbers/phonemetadata.pb.js +++ b/javascript/i18n/phonenumbers/phonemetadata.pb.js @@ -1,4 +1,4 @@ -/* +/** * @license * Protocol Buffer 2 Copyright 2008 Google Inc. * All other code copyright its respective owners. @@ -1755,6 +1755,57 @@ i18n.phonenumbers.PhoneMetadata.prototype.clearLeadingDigits = function() { }; +/** + * Gets the value of the leading_zero_possible field. + * @return {?boolean} The value. + */ +i18n.phonenumbers.PhoneMetadata.prototype.getLeadingZeroPossible = function() { + return /** @type {?boolean} */ (this.get$Value(26)); +}; + + +/** + * Gets the value of the leading_zero_possible field or the default value if not set. + * @return {boolean} The value. + */ +i18n.phonenumbers.PhoneMetadata.prototype.getLeadingZeroPossibleOrDefault = function() { + return /** @type {boolean} */ (this.get$ValueOrDefault(26)); +}; + + +/** + * Sets the value of the leading_zero_possible field. + * @param {boolean} value The value. + */ +i18n.phonenumbers.PhoneMetadata.prototype.setLeadingZeroPossible = function(value) { + this.set$Value(26, value); +}; + + +/** + * @return {boolean} Whether the leading_zero_possible field has a value. + */ +i18n.phonenumbers.PhoneMetadata.prototype.hasLeadingZeroPossible = function() { + return this.has$Value(26); +}; + + +/** + * @return {number} The number of values in the leading_zero_possible field. + */ +i18n.phonenumbers.PhoneMetadata.prototype.leadingZeroPossibleCount = function() { + return this.count$Values(26); +}; + + +/** + * Clears the values in the leading_zero_possible field. + */ +i18n.phonenumbers.PhoneMetadata.prototype.clearLeadingZeroPossible = function() { + this.clear$Field(26); +}; + + /** * Message PhoneMetadataCollection. @@ -2038,6 +2089,12 @@ goog.proto2.Message.set$Metadata(i18n.phonenumbers.PhoneMetadata, { name: 'leading_digits', fieldType: goog.proto2.Message.FieldType.STRING, type: String + }, + 26: { + name: 'leading_zero_possible', + fieldType: goog.proto2.Message.FieldType.BOOL, + defaultValue: false, + type: Boolean } }); diff --git a/javascript/i18n/phonenumbers/phonenumber.pb.js b/javascript/i18n/phonenumbers/phonenumber.pb.js index e62168ad3..cf6f2ab75 100644 --- a/javascript/i18n/phonenumbers/phonenumber.pb.js +++ b/javascript/i18n/phonenumbers/phonenumber.pb.js @@ -1,4 +1,4 @@ -/* +/** * @license * Protocol Buffer 2 Copyright 2008 Google Inc. * All other code copyright its respective owners. diff --git a/javascript/i18n/phonenumbers/phonenumberutil.js b/javascript/i18n/phonenumbers/phonenumberutil.js index cae75b57e..316cb8884 100644 --- a/javascript/i18n/phonenumbers/phonenumberutil.js +++ b/javascript/i18n/phonenumbers/phonenumberutil.js @@ -1,4 +1,4 @@ -/* +/** * @license * Copyright (C) 2010 Google Inc. * @@ -48,7 +48,7 @@ i18n.phonenumbers.PhoneNumberUtil = function() { * A mapping from a region code to the PhoneMetadata for that region. * @type {Object.} */ - this.countryToMetadata = {}; + this.regionToMetadataMap = {}; }; goog.addSingletonGetter(i18n.phonenumbers.PhoneNumberUtil); @@ -59,18 +59,17 @@ goog.addSingletonGetter(i18n.phonenumbers.PhoneNumberUtil); * @enum {string} */ i18n.phonenumbers.Error = { - INVALID_COUNTRY_CODE: 'Invalid country code', + INVALID_COUNTRY_CODE: 'Invalid country calling code', // This generally indicates the string passed in had less than 3 digits in it. // More specifically, the number failed to match the regular expression // VALID_PHONE_NUMBER. NOT_A_NUMBER: 'The string supplied did not seem to be a phone number', // This indicates the string started with an international dialing prefix, but // after this was stripped from the number, had less digits than any valid - // phone number (including country code) could have. + // phone number (including country calling code) could have. TOO_SHORT_AFTER_IDD: 'Phone number too short after IDD', - // This indicates the string, after any country code has been stripped, had - // less digits than any - // valid phone number could have. + // This indicates the string, after any country calling code has been + // stripped, had less digits than any valid phone number could have. TOO_SHORT_NSN: 'The string supplied is too short to be a phone number', // This indicates the string had more digits than any valid phone number could // have. @@ -107,7 +106,7 @@ i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_ = 15; /** - * The maximum length of the country code. + * The maximum length of the country calling code. * * @const * @type {number} @@ -135,12 +134,23 @@ i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ = 'ZZ'; i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN = '+'; +/** + * The RFC 3966 format for extensions. + * + * @const + * @type {string} + * @private + */ +i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ = ';ext='; + + /** * These mappings map a character (key) to a specific digit that should replace * it for normalization purposes. Non-European digits that may be used in phone * numbers are mapped to a European equivalent. * * @const + * @type {!Object.} */ i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = { '0': '0', @@ -190,6 +200,7 @@ i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = { * Only upper-case variants of alpha characters are stored. * * @const + * @type {!Object.} * @private */ i18n.phonenumbers.PhoneNumberUtil.ALPHA_MAPPINGS_ = { @@ -226,6 +237,7 @@ i18n.phonenumbers.PhoneNumberUtil.ALPHA_MAPPINGS_ = { * For performance reasons, amalgamate both into one map. * * @const + * @type {!Object.} * @private */ i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_ = { @@ -299,38 +311,107 @@ i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_ = { /** - * A list of all country codes where national significant numbers (excluding any - * national prefix) exist that start with a leading zero. + * Separate map of all symbols that we wish to retain when formatting alpha + * numbers. This includes digits, ASCII letters and number grouping symbols such + * as '-' and ' '. * * @const + * @type {!Object.} * @private */ -i18n.phonenumbers.PhoneNumberUtil.LEADING_ZERO_COUNTRIES_ = { - 39: 1, // Italy - 47: 1, // Norway - 225: 1, // Cote d'Ivoire - 227: 1, // Niger - 228: 1, // Togo - 241: 1, // Gabon - 242: 1, // Congo (Rep. of the) - 268: 1, // Swaziland - 378: 1, // San Marino - 379: 1, // Vatican City - 501: 1 // Belize -}; - - -/** - * Pattern that makes it easy to distinguish whether a country has a unique - * international dialing prefix or not. If a country has a unique international +i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_ = { + '0': '0', + '1': '1', + '2': '2', + '3': '3', + '4': '4', + '5': '5', + '6': '6', + '7': '7', + '8': '8', + '9': '9', + 'A': 'A', + 'B': 'B', + 'C': 'C', + 'D': 'D', + 'E': 'E', + 'F': 'F', + 'G': 'G', + 'H': 'H', + 'I': 'I', + 'J': 'J', + 'K': 'K', + 'L': 'L', + 'M': 'M', + 'N': 'N', + 'O': 'O', + 'P': 'P', + 'Q': 'Q', + 'R': 'R', + 'S': 'S', + 'T': 'T', + 'U': 'U', + 'V': 'V', + 'W': 'W', + 'X': 'X', + 'Y': 'Y', + 'Z': 'Z', + 'a': 'A', + 'b': 'B', + 'c': 'C', + 'd': 'D', + 'e': 'E', + 'f': 'F', + 'g': 'G', + 'h': 'H', + 'i': 'I', + 'j': 'J', + 'k': 'K', + 'l': 'L', + 'm': 'M', + 'n': 'N', + 'o': 'O', + 'p': 'P', + 'q': 'Q', + 'r': 'R', + 's': 'S', + 't': 'T', + 'u': 'U', + 'v': 'V', + 'w': 'W', + 'x': 'X', + 'y': 'Y', + 'z': 'Z', + '-': '-', + '\uFF0D': '-', + '\u2010': '-', + '\u2011': '-', + '\u2012': '-', + '\u2013': '-', + '\u2014': '-', + '\u2015': '-', + '\u2212': '-', + '/': '/', + '\uFF0F': '/', + ' ': ' ', + '\u3000': ' ', + '\u2060': ' ', + '.': '.', + '\uFF0E': '.' +}; + + +/** + * Pattern that makes it easy to distinguish whether a region has a unique + * international dialing prefix or not. If a region has a unique international * prefix (e.g. 011 in USA), it will be represented as a string that contains a * sequence of ASCII digits. If there are multiple available international - * prefixes in a country, they will be represented as a regex string that always + * prefixes in a region, they will be represented as a regex string that always * contains character(s) other than ASCII digits. Note this regex also includes * tilde, which signals waiting for the tone. * * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_ = @@ -386,7 +467,7 @@ i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ = '+\uFF0B'; /** * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_ = @@ -395,7 +476,17 @@ i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_ = /** * @const - * @type {RegExp} + * @type {!RegExp} + * @private + */ +i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_ = + new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION_ + + ']+', 'g'); + + +/** + * @const + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN_ = @@ -412,8 +503,7 @@ i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN_ = * is of no information value when parsing a number. * * @const - * @type {RegExp} - * @public + * @type {!RegExp} */ i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN = new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + @@ -429,7 +519,7 @@ i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN = * the second extension so that the first number is parsed correctly. * * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_ = /[\\\/] *x/; @@ -441,7 +531,7 @@ i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_ = /[\\\/] *x/; * is retained here, as it may signify the previous block was an extension. * * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_ = @@ -455,7 +545,7 @@ i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_ = * are represented by letters. * * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_ = @@ -491,7 +581,7 @@ i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ = * any extension component of the number, after the main national number is * formatted. For example, if you wish the default extension formatting to be * ' extn: 3456', then you should specify ' extn: ' here as the default - * extension prefix. This can be overridden by country-specific preferences. + * extension prefix. This can be overridden by region-specific preferences. * * @const * @type {string} @@ -500,38 +590,50 @@ i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ = i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ = ' ext. '; +/** + * @const + * @type {string} + * @private + */ +i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ = + '([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,7})'; + + /** * Regexp of all possible ways to write extensions, for use when parsing. This * will be run as a case-insensitive regexp match. Wide character versions are - * also provided after each ascii version. There are two regular expressions - * here: the more generic one starts with optional white space and ends with an - * optional full stop (.), followed by zero or more spaces/tabs and then the - * numbers themselves. The other one covers the special case of American numbers - * where the extension is written with a hash at the end, such as "- 503#". Note - * that the only capturing groups should be around the digits that you want to - * capture as part of the extension, or else parsing will fail! We allow two - * options for representing the accented o - the character itself, and one in - * the unicode decomposed form with the combining acute accent. + * also provided after each ASCII version. There are three regular expressions + * here. The first covers RFC 3966 format, where the extension is added using + * ';ext='. The second more generic one starts with optional white space and + * ends with an optional full stop (.), followed by zero or more spaces/tabs and + * then the numbers themselves. The other one covers the special case of + * American numbers where the extension is written with a hash at the end, such + * as '- 503#'. Note that the only capturing groups should be around the digits + * that you want to capture as part of the extension, or else parsing will fail! + * We allow two options for representing the accented o - the character itself, + * and one in the unicode decomposed form with the combining acute accent. * * @const * @type {string} * @private */ i18n.phonenumbers.PhoneNumberUtil.KNOWN_EXTN_PATTERNS_ = + i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ + + i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '|' + '[ \u00A0\\t,]*' + '(?:ext(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45\uFF58\uFF54\uFF4E?|' + '[,x\uFF58#\uFF03~\uFF5E]|int|anexo|\uFF49\uFF4E\uFF54)' + - '[:\\.\uFF0E]?[ \u00A0\\t,-]*([' + - i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,7})#?|[- ]+([' + - i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,5})#'; + '[:\\.\uFF0E]?[ \u00A0\\t,-]*' + + i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '#?|' + + '[- ]+([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,5})#'; /** - * Regexp of all known extension prefixes used by different countries followed - * by 1 or more valid digits, for use when parsing. + * Regexp of all known extension prefixes used by different regions followed by + * 1 or more valid digits, for use when parsing. * * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_ = @@ -544,7 +646,7 @@ i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_ = * number may have an extension prefix appended, followed by 1 or more digits. * * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_ = @@ -555,7 +657,7 @@ i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_ = /** * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_ = /\D+/; @@ -563,7 +665,7 @@ i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_ = /\D+/; /** * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_ = /(\$1)/; @@ -571,7 +673,7 @@ i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_ = /(\$1)/; /** * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_ = /\$NP/; @@ -579,7 +681,7 @@ i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_ = /\$NP/; /** * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/; @@ -587,7 +689,7 @@ i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/; /** * @const - * @type {RegExp} + * @type {!RegExp} * @private */ i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/; @@ -596,16 +698,22 @@ i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/; /** * INTERNATIONAL and NATIONAL formats are consistent with the definition in * ITU-T Recommendation E. 123. For example, the number of the Google Zurich - * office will be written as "+41 44 668 1800" in INTERNATIONAL format, and as - * "044 668 1800" in NATIONAL format. E164 format is as per INTERNATIONAL format - * but with no formatting applied, e.g. +41446681800. - * + * office will be written as '+41 44 668 1800' in INTERNATIONAL format, and as + * '044 668 1800' in NATIONAL format. E164 format is as per INTERNATIONAL format + * but with no formatting applied, e.g. +41446681800. RFC3966 is as per + * INTERNATIONAL format, but with all spaces and other separating symbols + * replaced with a hyphen, and with any phone number extension appended with + * ';ext='. + * + * Note: If you are considering storing the number in a neutral format, you are + * highly advised to use the PhoneNumber class. * @enum {number} */ i18n.phonenumbers.PhoneNumberFormat = { E164: 0, INTERNATIONAL: 1, - NATIONAL: 2 + NATIONAL: 2, + RFC3966: 3 }; @@ -617,7 +725,7 @@ i18n.phonenumbers.PhoneNumberFormat = { i18n.phonenumbers.PhoneNumberType = { FIXED_LINE: 0, MOBILE: 1, - // In some countries (e.g. the USA), it is impossible to distinguish between + // In some regions (e.g. the USA), it is impossible to distinguish between // fixed-line and mobile numbers by looking at the phone number itself. FIXED_LINE_OR_MOBILE: 2, // Freephone lines @@ -634,12 +742,12 @@ i18n.phonenumbers.PhoneNumberType = { // here: http://en.wikipedia.org/wiki/Personal_Numbers PERSONAL_NUMBER: 7, PAGER: 8, - // Used for "Universal Access Numbers" or "Company Numbers". They may be + // Used for 'Universal Access Numbers' or 'Company Numbers'. They may be // further routed to specific offices, but allow one number to be used for a // company. UAN: 9, // A phone number is of type UNKNOWN when it does not fit any of the known - // patterns for a specific country. + // patterns for a specific region. UNKNOWN: 10 }; @@ -812,16 +920,18 @@ i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber = /** - * Gets the length of the geographical area code from the national_number field - * of the PhoneNumber object passed in, so that clients could use it to split a - * national significant number into geographical area code and subscriber - * number. It works in such a way that the resultant subscriber number should be - * diallable, at least on some devices. An example of how this could be used: + * Gets the length of the geographical area code in the {@code national_number} + * field of the PhoneNumber object passed in, so that clients could use it to + * split a national significant number into geographical area code and + * subscriber number. It works in such a way that the resultant subscriber + * number should be diallable, at least on some devices. An example of how this + * could be used: * + *

  * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
  * var number = phoneUtil.parse('16502530000', 'US');
  * var nationalSignificantNumber =
- *     i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number);
+ *     phoneUtil.getNationalSignificantNumber(number);
  * var areaCode;
  * var subscriberNumber;
  *
@@ -833,11 +943,12 @@ i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
  *   areaCode = '';
  *   subscriberNumber = nationalSignificantNumber;
  * }
+ * 
* * N.B.: area code is a very ambiguous concept, so the I18N team generally - * recommends against using it for most purposes, but recommends using the more - * general national_number instead. Read the following carefully before deciding - * to use this method: + * recommends against using it for most purposes. Read the following carefully + * before deciding to use this method: + * * - geographical area codes change over time, and this method honors those * changes; therefore, it doesn't guarantee the stability of the result it * produces. @@ -870,8 +981,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode = /** @type {i18n.phonenumbers.PhoneNumberType} */ var type = this.getNumberTypeHelper_( - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number), - metadata); + this.getNationalSignificantNumber(number), metadata); // Most numbers other than the two types below have to be dialled in full. if (type != i18n.phonenumbers.PhoneNumberType.FIXED_LINE && type != i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE) { @@ -886,14 +996,15 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode = * Gets the length of the national destination code (NDC) from the PhoneNumber * object passed in, so that clients could use it to split a national * significant number into NDC and subscriber number. The NDC of a phone number - * is normally the first group of digit(s) right after the country code when the - * number is formatted in the international format, if there is a subscriber - * number part that follows. An example of how this could be used: + * is normally the first group of digit(s) right after the country calling code + * when the number is formatted in the international format, if there is a + * subscriber number part that follows. An example of how this could be used: * + *
  * var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
  * var number = phoneUtil.parse('18002530000', 'US');
  * var nationalSignificantNumber =
- *     i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number);
+ *     phoneUtil.getNationalSignificantNumber(number);
  * var nationalDestinationCode;
  * var subscriberNumber;
  *
@@ -908,6 +1019,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode =
  *   nationalDestinationCode = '';
  *   subscriberNumber = nationalSignificantNumber;
  * }
+ * 
* * Refer to the unittests to see the difference between this function and * getLengthOfGeographicalAreaCode(). @@ -939,7 +1051,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfNationalDestinationCode = i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_); // The pattern will start with '+COUNTRY_CODE ' so the first group will always // be the empty string (before the + symbol) and the second group will be the - // country code. The third group will be area code if it's not the last group. + // country calling code. The third group will be area code if it is not the + // last group. // NOTE: On IE the first group that is supposed to be the empty string does // not appear in the array of number groups... so make the result on non-IE // browsers to be that of IE. @@ -971,8 +1084,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfNationalDestinationCode = * stripping all other characters if removeNonMatches is true. * * @param {string} number a string of characters representing a phone number. - * @param {!Object} normalizationReplacements a mapping of characters to what - * they should be replaced by in the normalized version of the phone number. + * @param {!Object.} normalizationReplacements a mapping of + * characters to what they should be replaced by in the normalized version + * of the phone number. * @param {boolean} removeNonMatches indicates whether characters that are not * able to be replaced should be stripped from the number. If this is false, * they will be left unchanged in the number. @@ -1007,8 +1121,7 @@ i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_ = /** * Helper function to check region code is not unknown or null. * - * @param {?string} regionCode the ISO 3166-1 two-letter country code that - * denotes the country/region that we want to get the country code for. + * @param {?string} regionCode the ISO 3166-1 two-letter region code. * @return {boolean} true if region code is valid. * @private */ @@ -1026,10 +1139,10 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidRegionCode_ = * where they are - although we do format in either 'national' or * 'international' format depending on what the client asks for, we do not * currently support a more abbreviated format, such as for users in the same - * "area" who could potentially dial the number without area code. Note that if - * the phone number has a country code of 0 or an otherwise invalid country - * code, we cannot work out which formatting rules to apply so we return the - * national significant number with no formatting applied. + * 'area' who could potentially dial the number without area code. Note that if + * the phone number has a country calling code of 0 or an otherwise invalid + * country calling code, we cannot work out which formatting rules to apply so + * we return the national significant number with no formatting applied. * * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be * formatted. @@ -1043,8 +1156,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.format = /** @type {number} */ var countryCode = number.getCountryCodeOrDefault(); /** @type {string} */ - var nationalSignificantNumber = i18n.phonenumbers.PhoneNumberUtil - .getNationalSignificantNumber(number); + var nationalSignificantNumber = this.getNationalSignificantNumber(number); if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.E164) { // Early exit for E164 case since no formatting of the national number needs // to be applied. Extensions are not formatted. @@ -1053,8 +1165,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.format = nationalSignificantNumber, ''); } // Note getRegionCodeForCountryCode() is used because formatting information - // for countries which share a country code is contained by only one country - // for performance reasons. For example, for NANPA countries it will be + // for regions which share a country calling code is contained by only one + // region for performance reasons. For example, for NANPA regions it will be // contained in the metadata for US. /** @type {string} */ var regionCode = this.getRegionCodeForCountryCode(countryCode); @@ -1063,7 +1175,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.format = } /** @type {string} */ - var formattedExtension = this.maybeGetFormattedExtension_(number, regionCode); + var formattedExtension = + this.maybeGetFormattedExtension_(number, regionCode, numberFormat); /** @type {string} */ var formattedNationalNumber = this.formatNationalNumber_(nationalSignificantNumber, @@ -1078,10 +1191,11 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.format = /** * Formats a phone number in the specified format using client-defined - * formatting rules. Note that if the phone number has a country code of zero or - * an otherwise invalid country code, we cannot work out things like whether - * there should be a national prefix applied, or how to format extensions, so we - * return the national significant number with no formatting applied. + * formatting rules. Note that if the phone number has a country calling code of + * zero or an otherwise invalid country calling code, we cannot work out things + * like whether there should be a national prefix applied, or how to format + * extensions, so we return the national significant number with no formatting + * applied. * * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be * formatted. @@ -1095,16 +1209,15 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern = function(number, numberFormat, userDefinedFormats) { /** @type {number} */ - var countryCode = number.getCountryCodeOrDefault(); + var countryCallingCode = number.getCountryCodeOrDefault(); /** @type {string} */ - var nationalSignificantNumber = - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number); + var nationalSignificantNumber = this.getNationalSignificantNumber(number); // Note getRegionCodeForCountryCode() is used because formatting information - // for countries which share a country code is contained by only one country - // for performance reasons. For example, for NANPA countries it will be + // for regions which share a country calling code is contained by only one + // region for performance reasons. For example, for NANPA regions it will be // contained in the metadata for US. /** @type {string} */ - var regionCode = this.getRegionCodeForCountryCode(countryCode); + var regionCode = this.getRegionCodeForCountryCode(countryCallingCode); if (!this.isValidRegionCode_(regionCode)) { return nationalSignificantNumber; } @@ -1150,13 +1263,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern = } /** @type {string} */ - var formattedExtension = this.maybeGetFormattedExtension_(number, regionCode); + var formattedExtension = + this.maybeGetFormattedExtension_(number, regionCode, numberFormat); /** @type {string} */ var formattedNationalNumber = this.formatAccordingToFormats_(nationalSignificantNumber, userDefinedFormatsCopy, numberFormat); - return this.formatNumberByFormat_(countryCode, + return this.formatNumberByFormat_(countryCallingCode, numberFormat, formattedNationalNumber, formattedExtension); @@ -1165,37 +1279,37 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern = /** * Formats a phone number in national format for dialing using the carrier as - * specified in the carrierCode. The carrierCode will always be used regardless - * of whether the phone number already has a preferred domestic carrier code - * stored. If carrierCode contains an empty string, return the number in - * national format without any carrier code. + * specified in the {@code carrierCode}. The {@code carrierCode} will always be + * used regardless of whether the phone number already has a preferred domestic + * carrier code stored. If {@code carrierCode} contains an empty string, returns + * the number in national format without any carrier code. * * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be * formatted. * @param {string} carrierCode the carrier selection code to be used. * @return {string} the formatted phone number in national format for dialing - * using the carrier as specified in the carrierCode. + * using the carrier as specified in the {@code carrierCode}. */ i18n.phonenumbers.PhoneNumberUtil.prototype. formatNationalNumberWithCarrierCode = function(number, carrierCode) { /** @type {number} */ - var countryCode = number.getCountryCodeOrDefault(); + var countryCallingCode = number.getCountryCodeOrDefault(); /** @type {string} */ - var nationalSignificantNumber = - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number); + var nationalSignificantNumber = this.getNationalSignificantNumber(number); // Note getRegionCodeForCountryCode() is used because formatting information - // for countries which share a country code is contained by only one country - // for performance reasons. For example, for NANPA countries it will be + // for regions which share a country calling code is contained by only one + // region for performance reasons. For example, for NANPA regions it will be // contained in the metadata for US. /** @type {string} */ - var regionCode = this.getRegionCodeForCountryCode(countryCode); + var regionCode = this.getRegionCodeForCountryCode(countryCallingCode); if (!this.isValidRegionCode_(regionCode)) { return nationalSignificantNumber; } /** @type {string} */ - var formattedExtension = this.maybeGetFormattedExtension_(number, regionCode); + var formattedExtension = this.maybeGetFormattedExtension_( + number, regionCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL); /** @type {string} */ var formattedNationalNumber = this.formatNationalNumber_(nationalSignificantNumber, @@ -1203,7 +1317,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. i18n.phonenumbers.PhoneNumberFormat.NATIONAL, carrierCode); return this.formatNumberByFormat_( - countryCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL, + countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL, formattedNationalNumber, formattedExtension); }; @@ -1211,14 +1325,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. /** * Formats a phone number in national format for dialing using the carrier as * specified in the preferred_domestic_carrier_code field of the PhoneNumber - * object passed in. If that is missing, use the fallbackCarrierCode passed in - * instead. If there is no preferred_domestic_carrier_code, and the - * fallbackCarrierCode contains an empty string, return the number in national - * format without any carrier code. + * object passed in. If that is missing, use the {@code fallbackCarrierCode} + * passed in instead. If there is no {@code preferred_domestic_carrier_code}, + * and the {@code fallbackCarrierCode} contains an empty string, return the + * number in national format without any carrier code. * - * Use formatNationalNumberWithCarrierCode instead if the carrier code passed in - * should take precedence over the number's preferred_domestic_carrier_code when - * formatting. + *

Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier + * code passed in should take precedence over the number's + * {@code preferred_domestic_carrier_code} when formatting. * * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be * formatted. @@ -1226,7 +1340,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. * none is found in the phone number itself. * @return {string} the formatted phone number in national format for dialing * using the number's preferred_domestic_carrier_code, or the - * fallbackCarrierCode passed in if none is found. + * {@code fallbackCarrierCode} passed in if none is found. */ i18n.phonenumbers.PhoneNumberUtil.prototype. formatNationalNumberWithPreferredCarrierCode = function( @@ -1240,58 +1354,60 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. /** - * Formats a phone number for out-of-country dialing purpose. If no - * countryCallingFrom is supplied, we format the number in its INTERNATIONAL - * format. If the countryCallingFrom is the same as the country where the number - * is from, then NATIONAL formatting will be applied. + * Formats a phone number for out-of-country dialing purposes. If no + * regionCallingFrom is supplied, we format the number in its INTERNATIONAL + * format. If the regionCallingFrom is the same as the region where the + * number is from, then NATIONAL formatting will be applied. * - * If the number itself has a country code of zero or an otherwise invalid - * country code, then we return the number with no formatting applied. + *

If the number itself has a country calling code of zero or an otherwise + * invalid country calling code, then we return the number with no formatting + * applied. * - * Note this function takes care of the case for calling inside of NANPA and - * between Russia and Kazakhstan (who share the same country code). In those - * cases, no international prefix is used. For countries which have multiple + *

Note this function takes care of the case for calling inside of NANPA and + * between Russia and Kazakhstan (who share the same country calling code). In + * those cases, no international prefix is used. For regions which have multiple * international prefixes, the number in its INTERNATIONAL format will be * returned instead. * * @param {i18n.phonenumbers.PhoneNumber} number the phone number to be * formatted. - * @param {string} countryCallingFrom the ISO 3166-1 two-letter country code - * that denotes the foreign country where the call is being placed. + * @param {string} regionCallingFrom the ISO 3166-1 two-letter region code + * that denotes the region where the call is being placed. * @return {string} the formatted phone number. */ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber = - function(number, countryCallingFrom) { + function(number, regionCallingFrom) { - if (!this.isValidRegionCode_(countryCallingFrom)) { + if (!this.isValidRegionCode_(regionCallingFrom)) { return this.format(number, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL); } /** @type {number} */ - var countryCode = number.getCountryCodeOrDefault(); + var countryCallingCode = number.getCountryCodeOrDefault(); /** @type {string} */ - var regionCode = this.getRegionCodeForCountryCode(countryCode); + var regionCode = this.getRegionCodeForCountryCode(countryCallingCode); /** @type {string} */ - var nationalSignificantNumber = - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number); + var nationalSignificantNumber = this.getNationalSignificantNumber(number); if (!this.isValidRegionCode_(regionCode)) { return nationalSignificantNumber; } - if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) { - if (this.isNANPACountry(countryCallingFrom)) { - // For NANPA countries, return the national format for these countries but - // prefix it with the country code. - return countryCode + ' ' + + if (countryCallingCode == + i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) { + if (this.isNANPACountry(regionCallingFrom)) { + // For NANPA regions, return the national format for these regions but + // prefix it with the country calling code. + return countryCallingCode + ' ' + this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL); } - } else if (countryCode == this.getCountryCodeForRegion(countryCallingFrom)) { - // For countries that share a country calling code, the country code need - // not be dialled. This also applies when dialling within a country, so this - // if clause covers both these cases. Technically this is the case for - // dialling from la Reunion to other overseas departments of France (French + } else if (countryCallingCode == + this.getCountryCodeForRegion(regionCallingFrom)) { + // For regions that share a country calling code, the country calling code + // need not be dialled. This also applies when dialling within a region, so + // this if clause covers both these cases. Technically this is the case for + // dialling from La Reunion to other overseas departments of France (French // Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover // this edge case for now and for those cases return the version including - // country code. Details here: + // country calling code. Details here: // http://www.petitfute.com/voyage/225-info-pratiques-reunion return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL); @@ -1301,13 +1417,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber = this.formatNationalNumber_(nationalSignificantNumber, regionCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL); /** @type {i18n.phonenumbers.PhoneMetadata} */ - var metadata = this.getMetadataForRegion(countryCallingFrom); + var metadata = this.getMetadataForRegion(regionCallingFrom); /** @type {string} */ var internationalPrefix = metadata.getInternationalPrefixOrDefault(); /** @type {string} */ - var formattedExtension = this.maybeGetFormattedExtension_(number, regionCode); + var formattedExtension = this.maybeGetFormattedExtension_( + number, regionCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL); - // For countries that have multiple international prefixes, the international + // For regions that have multiple international prefixes, the international // format of the number is returned, unless there is a preferred international // prefix. /** @type {string} */ @@ -1321,11 +1438,11 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber = metadata.getPreferredInternationalPrefixOrDefault(); } - return internationalPrefixForFormatting != '' ? - internationalPrefixForFormatting + ' ' + countryCode + ' ' + + return internationalPrefixForFormatting.length > 0 ? + internationalPrefixForFormatting + ' ' + countryCallingCode + ' ' + formattedNationalNumber + formattedExtension : this.formatNumberByFormat_( - countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL, + countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL, formattedNationalNumber, formattedExtension); }; @@ -1336,14 +1453,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber = * field of the PhoneNumber object passed in. If such information is missing, * the number will be formatted into the NATIONAL format by default. * - * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that needs to + * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to * be formatted in its original number format. - * @param {string} countryCallingFrom the country whose IDD needs to be prefixed + * @param {string} regionCallingFrom the region whose IDD needs to be prefixed * if the original number has one. * @return {string} the formatted phone number in its original number format. */ i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat = - function(number, countryCallingFrom) { + function(number, regionCallingFrom) { if (!number.hasCountryCodeSource()) { return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL); @@ -1354,7 +1471,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat = return this.format(number, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL); case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD: - return this.formatOutOfCountryCallingNumber(number, countryCallingFrom); + return this.formatOutOfCountryCallingNumber(number, regionCallingFrom); case i18n.phonenumbers.PhoneNumber.CountryCodeSource .FROM_NUMBER_WITHOUT_PLUS_SIGN: return this.format(number, @@ -1366,6 +1483,124 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat = }; +/** + * Formats a phone number for out-of-country dialing purposes. + * + * Note that in this version, if the number was entered originally using alpha + * characters and this version of the number is stored in raw_input, this + * representation of the number will be used rather than the digit + * representation. Grouping information, as specified by characters such as '-' + * and ' ', will be retained. + * + *

Caveats:

+ *
    + *
  • This will not produce good results if the country calling code is both + * present in the raw input _and_ is the start of the national number. This is + * not a problem in the regions which typically use alpha numbers. + *
  • This will also not produce good results if the raw input has any grouping + * information within the first three digits of the national number, and if the + * function needs to strip preceding digits/words in the raw input before these + * digits. Normally people group the first three digits together so this is not + * a huge problem - and will be fixed if it proves to be so. + *
+ * + * @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to + * be formatted. + * @param {string} regionCallingFrom the region where the call is being placed. + * @return {string} the formatted phone number. + */ +i18n.phonenumbers.PhoneNumberUtil.prototype. + formatOutOfCountryKeepingAlphaChars = function(number, regionCallingFrom) { + /** @type {string} */ + var rawInput = number.getRawInputOrDefault(); + // If there is no raw input, then we can't keep alpha characters because there + // aren't any. In this case, we return formatOutOfCountryCallingNumber. + if (rawInput.length == 0) { + return this.formatOutOfCountryCallingNumber(number, regionCallingFrom); + } + /** @type {number} */ + var countryCode = number.getCountryCodeOrDefault(); + /** @type {string} */ + var regionCode = this.getRegionCodeForCountryCode(countryCode); + if (!this.isValidRegionCode_(regionCode)) { + return rawInput; + } + // Strip any prefix such as country calling code, IDD, that was present. We do + // this by comparing the number in raw_input with the parsed number. To do + // this, first we normalize punctuation. We retain number grouping symbols + // such as ' ' only. + rawInput = i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_( + rawInput, + i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_, + true); + // Now we trim everything before the first three digits in the parsed number. + // We choose three because all valid alpha numbers have 3 digits at the start + // - if it does not, then we don't trim anything at all. Similarly, if the + // national number was less than three digits, we don't trim anything at all. + /** @type {string} */ + var nationalNumber = this.getNationalSignificantNumber(number); + if (nationalNumber.length > 3) { + /** @type {number} */ + var firstNationalNumberDigit = + rawInput.indexOf(nationalNumber.substring(0, 3)); + if (firstNationalNumberDigit != -1) { + rawInput = rawInput.substring(firstNationalNumberDigit); + } + } + /** @type {i18n.phonenumbers.PhoneMetadata} */ + var metadata = this.getMetadataForRegion(regionCallingFrom); + if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) { + if (this.isNANPACountry(regionCallingFrom)) { + return countryCode + ' ' + rawInput; + } + } else if (countryCode == this.getCountryCodeForRegion(regionCallingFrom)) { + // Here we copy the formatting rules so we can modify the pattern we expect + // to match against. + /** @type {Array.} */ + var availableFormats = []; + for (var i = 0; i < metadata.numberFormatArray().length; ++i) { + /** @type {i18n.phonenumbers.NumberFormat} */ + var newFormat = metadata.numberFormatArray()[i].clone(); + // The first group is the first group of digits that the user determined. + newFormat.setPattern('(\\d+)(.*)'); + // Here we just concatenate them back together after the national prefix + // has been fixed. + newFormat.setFormat('$1$2'); + availableFormats.push(newFormat); + } + // Now we format using these patterns instead of the default pattern, but + // with the national prefix prefixed if necessary, by choosing the format + // rule based on the leading digits present in the unformatted national + // number. This will not work in the cases where the pattern (and not the + // leading digits) decide whether a national prefix needs to be used, since + // we have overridden the pattern to match anything, but that is not the + // case in the metadata to date. + return this.formatAccordingToFormats_(rawInput, availableFormats, + i18n.phonenumbers.PhoneNumberFormat.NATIONAL); + } + /** @type {string} */ + var internationalPrefix = metadata.getInternationalPrefixOrDefault(); + // For countries that have multiple international prefixes, the international + // format of the number is returned, unless there is a preferred international + // prefix. + /** @type {string} */ + var internationalPrefixForFormatting = + i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( + i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_, + internationalPrefix) ? + internationalPrefix : metadata.getPreferredInternationalPrefixOrDefault(); + /** @type {string} */ + var formattedExtension = this.maybeGetFormattedExtension_( + number, regionCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL); + return internationalPrefixForFormatting.length > 0 ? + internationalPrefixForFormatting + ' ' + countryCode + ' ' + + rawInput + formattedExtension : + this.formatNumberByFormat_( + countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL, + rawInput, formattedExtension); +}; + + /** * Gets the national significant number of the a phone number. Note a national * significant number doesn't contain a national prefix or any formatting. @@ -1375,21 +1610,19 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat = * @return {string} the national significant number of the PhoneNumber object * passed in. */ -i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber = +i18n.phonenumbers.PhoneNumberUtil.prototype.getNationalSignificantNumber = function(number) { // The leading zero in the national (significant) number of an Italian phone // number has a special meaning. Unlike the rest of the world, it indicates // the number is a landline number. There have been plans to migrate landline // numbers to start with the digit two since December 2000, but it has not yet - // happened. See http://en.wikipedia.org/wiki/%2B39 for more details. - // Other countries such as Cote d'Ivoire and Gabon use this for their mobile - // numbers. + // happened. See http://en.wikipedia.org/wiki/%2B39 for more details. Other + // regions such as Cote d'Ivoire and Gabon use this for their mobile numbers. /** @type {string} */ var nationalNumber = '' + number.getNationalNumber(); if (number.hasItalianLeadingZero() && number.getItalianLeadingZero() && - i18n.phonenumbers.PhoneNumberUtil.isLeadingZeroCountry( - number.getCountryCodeOrDefault())) { + this.isLeadingZeroPossible(number.getCountryCodeOrDefault())) { return '0' + nationalNumber; } return nationalNumber; @@ -1399,7 +1632,7 @@ i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber = /** * A helper function that is used by format and formatByPattern. * - * @param {number} countryCode the country calling code. + * @param {number} countryCallingCode the country calling code. * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the * phone number should be formatted into. * @param {string} formattedNationalNumber @@ -1408,16 +1641,19 @@ i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber = * @private */ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberByFormat_ = - function(countryCode, numberFormat, + function(countryCallingCode, numberFormat, formattedNationalNumber, formattedExtension) { switch (numberFormat) { case i18n.phonenumbers.PhoneNumberFormat.E164: - return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCode + + return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode + formattedNationalNumber + formattedExtension; case i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL: - return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCode + ' ' + - formattedNationalNumber + formattedExtension; + return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode + + ' ' + formattedNationalNumber + formattedExtension; + case i18n.phonenumbers.PhoneNumberFormat.RFC3966: + return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode + + '-' + formattedNationalNumber + formattedExtension; case i18n.phonenumbers.PhoneNumberFormat.NATIONAL: default: return formattedNationalNumber + formattedExtension; @@ -1426,14 +1662,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberByFormat_ = /** - * Note in some countries, the national number can be written in two completely + * Note in some regions, the national number can be written in two completely * different ways depending on whether it forms part of the NATIONAL format or * INTERNATIONAL format. The numberFormat parameter here is used to specify * which format to use for those cases. If a carrierCode is specified, this will * be inserted into the formatted string to replace $CC. * * @param {string} number a string of characters representing a phone number. - * @param {string} regionCode the ISO 3166-1 two-letter country code. + * @param {string} regionCode the ISO 3166-1 two-letter region code. * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the * phone number should be formatted into. * @param {string=} opt_carrierCode @@ -1454,8 +1690,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNationalNumber_ = (intlNumberFormats.length == 0 || numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL) ? metadata.numberFormatArray() : metadata.intlNumberFormatArray(); - return this.formatAccordingToFormats_(number, availableFormats, numberFormat, - opt_carrierCode); + /** @type {string} */ + var formattedNationalNumber = this.formatAccordingToFormats_( + number, availableFormats, numberFormat, opt_carrierCode); + if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) { + formattedNationalNumber = formattedNationalNumber.replace( + i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_, '-'); + } + return formattedNationalNumber; }; @@ -1489,7 +1731,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatAccordingToFormats_ = // detailed. nationalNumber .search(numFormat.getLeadingDigitsPattern(size - 1)) == 0) { - /** @type {RegExp} */ + /** @type {!RegExp} */ var patternToMatch = new RegExp(numFormat.getPattern()); if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(patternToMatch, nationalNumber)) { @@ -1507,8 +1749,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatAccordingToFormats_ = var carrierCodeFormattingRule = domesticCarrierCodeFormattingRule .replace(i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_, opt_carrierCode); - // Now replace the $FG in the formatting rule with the first group - // and the carrier code combined in the appropriate way. + // Now replace the $FG in the formatting rule with the first group and + // the carrier code combined in the appropriate way. numberFormatRule = numberFormatRule.replace( i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_, carrierCodeFormattingRule); @@ -1538,12 +1780,12 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatAccordingToFormats_ = /** - * Gets a valid number for the specified country. + * Gets a valid number for the specified region. * - * @param {string} regionCode the ISO 3166-1 two-letter country code that - * denotes the country for which an example number is needed. + * @param {string} regionCode the ISO 3166-1 two-letter region code that + * denotes the region for which an example number is needed. * @return {i18n.phonenumbers.PhoneNumber} a valid fixed-line number for the - * specified country. Returns null when the metadata does not contain such + * specified region. Returns null when the metadata does not contain such * information. */ i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber = @@ -1555,14 +1797,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber = /** - * Gets a valid number, if any, for the specified country and number type. + * Gets a valid number for the specified region and number type. * - * @param {string} regionCode the ISO 3166-1 two-letter country code that - * denotes the country for which an example number is needed. + * @param {string} regionCode the ISO 3166-1 two-letter region code that + * denotes the region for which an example number is needed. * @param {i18n.phonenumbers.PhoneNumberType} type the type of number that is * needed. * @return {i18n.phonenumbers.PhoneNumber} a valid number for the specified - * country and type. Returns null when the metadata does not contain such + * region and type. Returns null when the metadata does not contain such * information. */ i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType = @@ -1587,16 +1829,22 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType = * * @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that might have * an extension. - * @param {string} regionCode the ISO 3166-1 two-letter country code. + * @param {string} regionCode the ISO 3166-1 two-letter region code. + * @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the + * phone number should be formatted into. * @return {string} the formatted extension if any. * @private */ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ = - function(number, regionCode) { + function(number, regionCode, numberFormat) { - if (!number.hasExtension()) { + if (!number.hasExtension() || number.getExtension().length == 0) { return ''; } else { + if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) { + return i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ + + number.getExtension(); + } return this.formatExtension_(number.getExtensionOrDefault(), regionCode); } }; @@ -1605,10 +1853,10 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ = /** * Formats the extension part of the phone number by prefixing it with the * appropriate extension prefix. This will be the default extension prefix, - * unless overridden by a preferred extension prefix for this country. + * unless overridden by a preferred extension prefix for this region. * * @param {string} extensionDigits the extension digits. - * @param {string} regionCode the ISO 3166-1 two-letter country code. + * @param {string} regionCode the ISO 3166-1 two-letter region code. * @return {string} the formatted extension. * @private */ @@ -1677,8 +1925,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType = return i18n.phonenumbers.PhoneNumberType.UNKNOWN; } /** @type {string} */ - var nationalSignificantNumber = - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number); + var nationalSignificantNumber = this.getNationalSignificantNumber(number); return this.getNumberTypeHelper_(nationalSignificantNumber, this.getMetadataForRegion(regionCode)); }; @@ -1757,7 +2004,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion = } regionCode = regionCode.toUpperCase(); /** @type {i18n.phonenumbers.PhoneMetadata} */ - var metadata = this.countryToMetadata[regionCode]; + var metadata = this.regionToMetadataMap[regionCode]; if (metadata == null) { /** @type {goog.proto2.PbLiteSerializer} */ var serializer = new goog.proto2.PbLiteSerializer(); @@ -1770,7 +2017,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion = metadata = /** @type {i18n.phonenumbers.PhoneMetadata} */ ( serializer.deserialize(i18n.phonenumbers.PhoneMetadata.getDescriptor(), metadataSerialized)); - this.countryToMetadata[regionCode] = metadata; + this.regionToMetadataMap[regionCode] = metadata; } return metadata; }; @@ -1786,9 +2033,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ = function(nationalNumber, numberDesc) { return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( - numberDesc.getPossibleNumberPattern(), nationalNumber) && + numberDesc.getPossibleNumberPatternOrDefault(), nationalNumber) && i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( - numberDesc.getNationalNumberPattern(), nationalNumber); + numberDesc.getNationalNumberPatternOrDefault(), nationalNumber); }; @@ -1813,16 +2060,16 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) { /** * Tests whether a phone number is valid for a certain region. Note this doesn't * verify the number is actually in use, which is impossible to tell by just - * looking at a number itself. If the country code is not the same as the - * country code for the region, this immediately exits with false. After this, - * the specific number pattern rules for the region are examined. This is useful - * for determining for example whether a particular number is valid for Canada, - * rather than just a valid NANPA number. + * looking at a number itself. If the country calling code is not the same as + * the country calling code for the region, this immediately exits with false. + * After this, the specific number pattern rules for the region are examined. + * This is useful for determining for example whether a particular number is + * valid for Canada, rather than just a valid NANPA number. * * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want * to validate. - * @param {string} regionCode the ISO 3166-1 two-letter country code that - * denotes the region/country that we want to validate the phone number for. + * @param {string} regionCode the ISO 3166-1 two-letter region code that + * denotes the region that we want to validate the phone number for. * @return {boolean} a boolean that indicates whether the number is of a valid * pattern. */ @@ -1838,12 +2085,11 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion = /** @type {i18n.phonenumbers.PhoneNumberDesc} */ var generalNumDesc = metadata.getGeneralDesc(); /** @type {string} */ - var nationalSignificantNumber = - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number); + var nationalSignificantNumber = this.getNationalSignificantNumber(number); - // For countries where we don't have metadata for PhoneNumberDesc, we treat - // any number passed in as a valid number if its national significant number - // is between the minimum and maximum lengths defined by ITU for a national + // For regions where we don't have metadata for PhoneNumberDesc, we treat any + // number passed in as a valid number if its national significant number is + // between the minimum and maximum lengths defined by ITU for a national // significant number. if (!generalNumDesc.hasNationalNumberPattern()) { /** @type {number} */ @@ -1858,13 +2104,13 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion = /** - * Returns the country/region where a phone number is from. This could be used - * for geo-coding in the country/region level. + * Returns the region where a phone number is from. This could be used for + * geocoding at the region level. * * @param {i18n.phonenumbers.PhoneNumber} number the phone number whose origin * we want to know. - * @return {?string} the country/region where the phone number is from, or null - * if no country matches this calling code. + * @return {?string} the region where the phone number is from, or null + * if no region matches this calling code. */ i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForNumber = function(number) { @@ -1898,7 +2144,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. getRegionCodeForNumberFromRegionList_ = function(number, regionCodes) { /** @type {string} */ - var nationalNumber = '' + number.getNationalNumber(); + var nationalNumber = this.getNationalSignificantNumber(number); /** @type {string} */ var regionCode; /** @type {number} */ @@ -1922,20 +2168,20 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. /** - * Returns the region code that matches the specific country code. In the case - * of no region code being found, ZZ will be returned. In the case of multiple - * regions, the one designated in the metadata as the "main" country for this - * calling code will be returned. + * Returns the region code that matches the specific country calling code. In + * the case of no region code being found, ZZ will be returned. In the case of + * multiple regions, the one designated in the metadata as the 'main' region for + * this calling code will be returned. * - * @param {number} countryCode the country calling code. + * @param {number} countryCallingCode the country calling code. * @return {string} */ i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode = - function(countryCode) { + function(countryCallingCode) { /** @type {Array.} */ var regionCodes = - i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCode]; + i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode]; return regionCodes == null ? i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ : regionCodes[0]; }; @@ -1945,9 +2191,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode = * Returns the country calling code for a specific region. For example, this * would be 1 for the United States, and 64 for New Zealand. * - * @param {?string} regionCode the ISO 3166-1 two-letter country code that - * denotes the country/region that we want to get the country code for. - * @return {number} the country calling code for the country/region denoted by + * @param {?string} regionCode the ISO 3166-1 two-letter region code that + * denotes the region that we want to get the country calling code for. + * @return {number} the country calling code for the region denoted by * regionCode. */ i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion = @@ -1968,20 +2214,20 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion = /** * Returns the national dialling prefix for a specific region. For example, this * would be 1 for the United States, and 0 for New Zealand. Set stripNonDigits - * to true to strip symbols like "~" (which indicates a wait for a dialling + * to true to strip symbols like '~' (which indicates a wait for a dialling * tone) from the prefix returned. If no national prefix is present, we return * null. * - * Warning: Do not use this method for do-your-own formatting - for some - * countries, the national dialling prefix is used only for certain types of + *

Warning: Do not use this method for do-your-own formatting - for some + * regions, the national dialling prefix is used only for certain types of * numbers. Use the library's formatting functions to prefix the national prefix * when required. * - * @param {?string} regionCode the ISO 3166-1 two-letter country code that - * denotes the country/region that we want to get the dialling prefix for. + * @param {?string} regionCode the ISO 3166-1 two-letter region code that + * denotes the region that we want to get the dialling prefix for. * @param {boolean} stripNonDigits true to strip non-digits from the national * dialling prefix. - * @return {?string} the dialling prefix for the country/region denoted by + * @return {?string} the dialling prefix for the region denoted by * regionCode. */ i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function( @@ -2010,11 +2256,11 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function( /** - * Check if a country is one of the countries under the North American Numbering - * Plan Administration (NANPA). + * Checks if this is a region under the North American Numbering Plan + * Administration (NANPA). * - * @param {string} regionCode the ISO 3166-1 two-letter country code. - * @return {boolean} true if regionCode is one of the countries under NANPA. + * @param {string} regionCode the ISO 3166-1 two-letter region code. + * @return {boolean} true if regionCode is one of the regions under NANPA. */ i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry = function(regionCode) { @@ -2027,22 +2273,52 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry = /** - * Check whether countryCode represents the country calling code from a country + * Checks whether countryCode represents the country calling code from a region * whose national significant number could contain a leading zero. An example of - * such a country is Italy. + * such a region is Italy. Returns false if no metadata for the country is + * found. * - * @param {number} countryCode the country calling code. + * @param {number} countryCallingCode the country calling code. * @return {boolean} */ -i18n.phonenumbers.PhoneNumberUtil.isLeadingZeroCountry = function(countryCode) { - return countryCode in - i18n.phonenumbers.PhoneNumberUtil.LEADING_ZERO_COUNTRIES_; +i18n.phonenumbers.PhoneNumberUtil.prototype.isLeadingZeroPossible = + function(countryCallingCode) { + /** @type {i18n.phonenumbers.PhoneMetadata} */ + var mainMetadataForCallingCode = this.getMetadataForRegion( + this.getRegionCodeForCountryCode(countryCallingCode)); + return mainMetadataForCallingCode != null && + mainMetadataForCallingCode.getLeadingZeroPossibleOrDefault(); }; /** - * Convenience wrapper around isPossibleNumberWithReason. Instead of returning - * the reason for failure, this method returns a boolean value. + * Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT. + * A valid vanity number will start with at least 3 digits and will have three + * or more alpha characters. This does not do region-specific checks - to work + * out if this number is actually valid for a region, it should be parsed and + * methods such as {@link #isPossibleNumberWithReason} and + * {@link #isValidNumber} should be used. + * + * @param {string} number the number that needs to be checked. + * @return {boolean} true if the number is a valid vanity number. + */ +i18n.phonenumbers.PhoneNumberUtil.prototype.isAlphaNumber = function(number) { + if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(number)) { + // Number is too short, or doesn't match the basic phone number pattern. + return false; + } + /** @type {!goog.string.StringBuffer} */ + var strippedNumber = new goog.string.StringBuffer(number); + this.maybeStripExtension(strippedNumber); + return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( + i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_, + strippedNumber.toString()); +}; + + +/** + * Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of + * returning the reason for failure, this method returns a boolean value. * * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be * checked. @@ -2057,25 +2333,50 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber = /** - * Check whether a phone number is a possible number. It provides a more lenient - * check than isValidNumber in the following sense: + * Helper method to check a number against a particular pattern and determine + * whether it matches, or is too short or too long. Currently, if a number + * pattern suggests that numbers of length 7 and 10 are possible, and a number + * in between these possible lengths is entered, such as of length 8, this will + * return TOO_LONG. * - * 1. It only checks the length of phone numbers. In particular, it doesn't + * @param {string} numberPattern + * @param {string} number + * @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult} + * @private + */ +i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLengthAgainstPattern_ = + function(numberPattern, number) { + if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(numberPattern, + number)) { + return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE; + } + if (number.search(numberPattern) == 0) { + return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG; + } else { + return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT; + } +}; + + +/** + * Check whether a phone number is a possible number. It provides a more lenient + * check than {@link #isValidNumber} in the following sense: + *

    + *
  1. It only checks the length of phone numbers. In particular, it doesn't * check starting digits of the number. - * - * 2. It doesn't attempt to figure out the type of the number, but uses general - * rules which applies to all types of phone numbers in a country. Therefore, it + *
  2. It doesn't attempt to figure out the type of the number, but uses general + * rules which applies to all types of phone numbers in a region. Therefore, it * is much faster than isValidNumber. - * - * 3. For fixed line numbers, many countries have the concept of area code, - * which together with subscriber number constitute the national significant - * number. It is sometimes okay to dial the subscriber number only when dialing - * in the same area. This function will return true if the - * subscriber-number-only version is passed in. On the other hand, because - * isValidNumber validates using information on both starting digits (for fixed - * line numbers, that would most likely be area codes) and length (obviously - * includes the length of area codes for fixed line numbers), it will return - * false for the subscriber-number-only version. + *
  3. For fixed line numbers, many regions have the concept of area code, which + * together with subscriber number constitute the national significant number. + * It is sometimes okay to dial the subscriber number only when dialing in the + * same area. This function will return true if the subscriber-number-only + * version is passed in. On the other hand, because isValidNumber validates + * using information on both starting digits (for fixed line numbers, that would + * most likely be area codes) and length (obviously includes the length of area + * codes for fixed line numbers), it will return false for the + * subscriber-number-only version. + *
* * @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be * checked. @@ -2085,22 +2386,21 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber = i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason = function(number) { + /** @type {string} */ + var nationalNumber = this.getNationalSignificantNumber(number); /** @type {number} */ var countryCode = number.getCountryCodeOrDefault(); // Note: For Russian Fed and NANPA numbers, we just use the rules from the // default region (US or Russia) since the getRegionCodeForNumber will not // work if the number is possible but not valid. This would need to be // revisited if the possible number pattern ever differed between various - // countries within those plans. + // regions within those plans. /** @type {string} */ var regionCode = this.getRegionCodeForCountryCode(countryCode); if (!this.isValidRegionCode_(regionCode)) { return i18n.phonenumbers.PhoneNumberUtil.ValidationResult .INVALID_COUNTRY_CODE; } - /** @type {string} */ - var nationalNumber = - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number); /** @type {i18n.phonenumbers.PhoneNumberDesc} */ var generalNumDesc = this.getMetadataForRegion(regionCode).getGeneralDesc(); // Handling case of numbers with no metadata. @@ -2119,37 +2419,28 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason = /** @type {string} */ var possibleNumberPattern = generalNumDesc.getPossibleNumberPatternOrDefault(); - /** @type {Array. } */ - var matchedGroups = nationalNumber.match('^' + possibleNumberPattern); - /** @type {string} */ - var firstGroup = matchedGroups ? matchedGroups[0] : ''; - if (firstGroup.length > 0) { - return (firstGroup.length == nationalNumber.length) ? - i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE : - i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG; - } else { - return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT; - } + return this.testNumberLengthAgainstPattern_(possibleNumberPattern, + nationalNumber); }; /** * Check whether a phone number is a possible number given a number in the form - * of a string, and the country where the number could be dialed from. It - * provides a more lenient check than isValidNumber. See - * isPossibleNumber(number) for details. + * of a string, and the region where the number could be dialed from. It + * provides a more lenient check than {@link #isValidNumber}. See + * {@link #isPossibleNumber} for details. * - * This method first parses the number, then invokes - * isPossibleNumber(PhoneNumber number) with the resultant PhoneNumber object. + *

This method first parses the number, then invokes + * {@link #isPossibleNumber} with the resultant PhoneNumber object. * * @param {string} number the number that needs to be checked, in the form of a * string. - * @param {string} countryDialingFrom the ISO 3166-1 two-letter country code - * that denotes the country that we are expecting the number to be dialed - * from. Note this is different from the country where the number belongs. + * @param {string} regionDialingFrom the ISO 3166-1 two-letter region code that + * denotes the region that we are expecting the number to be dialed from. + * Note this is different from the region where the number belongs. * For example, the number +1 650 253 0000 is a number that belongs to US. - * When written in this form, it could be dialed from any country. When it - * is written as 00 1 650 253 0000, it could be dialed from any country + * When written in this form, it could be dialed from any region. When it + * is written as 00 1 650 253 0000, it could be dialed from any region * which uses an international dialling prefix of 00. When it is written as * 650 253 0000, it could only be dialed from within the US, and when * written as 253 0000, it could only be dialed from within a smaller area @@ -2157,10 +2448,10 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason = * @return {boolean} true if the number is possible. */ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberString = - function(number, countryDialingFrom) { + function(number, regionDialingFrom) { try { - return this.isPossibleNumber(this.parse(number, countryDialingFrom)); + return this.isPossibleNumber(this.parse(number, regionDialingFrom)); } catch (e) { return false; } @@ -2201,10 +2492,10 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.truncateTooLongNumber = /** - * Extracts country code from fullNumber, returns it and places the remaining - * number in nationalNumber. It assumes that the leading plus sign or IDD has - * already been removed. Returns 0 if fullNumber doesn't start with a valid - * country code, and leaves nationalNumber unmodified. + * Extracts country calling code from fullNumber, returns it and places the + * remaining number in nationalNumber. It assumes that the leading plus sign or + * IDD has already been removed. Returns 0 if fullNumber doesn't start with a + * valid country calling code, and leaves nationalNumber unmodified. * * @param {!goog.string.StringBuffer} fullNumber * @param {!goog.string.StringBuffer} nationalNumber @@ -2234,40 +2525,43 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.extractCountryCode = /** - * Tries to extract a country code from a number. This method will return zero - * if no country code is considered to be present. Country codes are extracted - * in the following ways: - * - by stripping the international dialing prefix of the country the person is + * Tries to extract a country calling code from a number. This method will + * return zero if no country calling code is considered to be present. Country + * calling codes are extracted in the following ways: + *

    + *
  • by stripping the international dialing prefix of the region the person is * dialing from, if this is present in the number, and looking at the next * digits - * - by stripping the '+' sign if present and then looking at the next digits - * - by comparing the start of the number and the country code of the default - * region. If the number is not considered possible for the numbering plan of - * the default region initially, but starts with the country code of this - * region, validation will be reattempted after stripping this country code. If - * this number is considered a possible number, then the first digits will be - * considered the country code and removed as such. + *
  • by stripping the '+' sign if present and then looking at the next digits + *
  • by comparing the start of the number and the country calling code of the + * default region. If the number is not considered possible for the numbering + * plan of the default region initially, but starts with the country calling + * code of this region, validation will be reattempted after stripping this + * country calling code. If this number is considered a possible number, then + * the first digits will be considered the country calling code and removed as + * such. + *
* * It will throw a i18n.phonenumbers.Error if the number starts with a '+' but - * the country code supplied after this does not match that of any known - * country. + * the country calling code supplied after this does not match that of any known + * region. * * @param {string} number non-normalized telephone number that we wish to - * extract a country code from - may begin with '+'. + * extract a country calling code from - may begin with '+'. * @param {i18n.phonenumbers.PhoneMetadata} defaultRegionMetadata metadata * about the region this number may be from. * @param {!goog.string.StringBuffer} nationalNumber a string buffer to store - * the national significant number in, in the case that a country code was - * extracted. The number is appended to any existing contents. If no country - * code was extracted, this will be left unchanged. + * the national significant number in, in the case that a country calling + * code was extracted. The number is appended to any existing contents. If + * no country calling code was extracted, this will be left unchanged. * @param {boolean} keepRawInput true if the country_code_source and * preferred_carrier_code fields of phoneNumber should be populated. - * of phoneNumber should be populated. * @param {i18n.phonenumbers.PhoneNumber} phoneNumber the PhoneNumber object - * that needs to be populated with country code and country code source. - * Note the country code is always populated, whereas country code source is + * where the country_code and country_code_source need to be populated. + * Note the country_code is always populated, whereas country_code_source is * only populated when keepCountryCodeSource is true. - * @return {number} the country code extracted or 0 if none could be extracted. + * @return {number} the country calling code extracted or 0 if none could be + * extracted. * @throws {i18n.phonenumbers.Error} */ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode = @@ -2309,60 +2603,57 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode = return potentialCountryCode; } - // If this fails, they must be using a strange country code that we don't - // recognize, or that doesn't exist. + // If this fails, they must be using a strange country calling code that we + // don't recognize, or that doesn't exist. throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE; } else if (defaultRegionMetadata != null) { - // Check to see if the number is valid for the default region already. If - // not, we check to see if the country code for the default region is - // present at the start of the number. - /** @type {i18n.phonenumbers.PhoneNumberDesc} */ - var generalDesc = defaultRegionMetadata.getGeneralDesc(); - /** @type {RegExp} */ - var validNumberPattern = new RegExp(generalDesc.getNationalNumberPattern()); - if (!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( - validNumberPattern, fullNumber.toString())) { - /** @type {number} */ - var defaultCountryCode = defaultRegionMetadata.getCountryCodeOrDefault(); + // Check to see if the number starts with the country calling code for the + // default region. If so, we remove the country calling code, and do some + // checks on the validity of the number before and after. + /** @type {number} */ + var defaultCountryCode = defaultRegionMetadata.getCountryCodeOrDefault(); + /** @type {string} */ + var defaultCountryCodeString = '' + defaultCountryCode; + /** @type {string} */ + var normalizedNumber = fullNumber.toString(); + if (goog.string.startsWith(normalizedNumber, defaultCountryCodeString)) { + /** @type {!goog.string.StringBuffer} */ + var potentialNationalNumber = new goog.string.StringBuffer( + normalizedNumber.substring(defaultCountryCodeString.length)); + /** @type {i18n.phonenumbers.PhoneNumberDesc} */ + var generalDesc = defaultRegionMetadata.getGeneralDesc(); + /** @type {!RegExp} */ + var validNumberPattern = + new RegExp(generalDesc.getNationalNumberPatternOrDefault()); + this.maybeStripNationalPrefixAndCarrierCode( + potentialNationalNumber, defaultRegionMetadata); /** @type {string} */ - var defaultCountryCodeString = '' + defaultCountryCode; + var potentialNationalNumberStr = potentialNationalNumber.toString(); /** @type {string} */ - var normalizedNumber = fullNumber.toString(); - if (goog.string.startsWith(normalizedNumber, defaultCountryCodeString)) { - // If so, strip this, and see if the resultant number is valid. - /** @type {!goog.string.StringBuffer} */ - var potentialNationalNumber = new goog.string.StringBuffer( - normalizedNumber.substring(defaultCountryCodeString.length)); - this.maybeStripNationalPrefixAndCarrierCode( - potentialNationalNumber, defaultRegionMetadata); - /** @type {string} */ - var potentialNationalNumberStr = potentialNationalNumber.toString(); - /** @type {Array. } */ - var matchedGroups = potentialNationalNumberStr.match( - '^' + generalDesc.getPossibleNumberPattern()); - /** @type {number} */ - var possibleNumberMatchedLength = matchedGroups && - matchedGroups[0] != null && matchedGroups[0].length || 0; - // If the resultant number is either valid, or still too long even with - // the country code stripped, we consider this a better result and keep - // the potential national number. - if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( - validNumberPattern, potentialNationalNumberStr) || - possibleNumberMatchedLength > 0 && - possibleNumberMatchedLength != potentialNationalNumberStr.length) { - nationalNumber.append(potentialNationalNumberStr); - if (keepRawInput) { - phoneNumber.setCountryCodeSource( - i18n.phonenumbers.PhoneNumber.CountryCodeSource - .FROM_NUMBER_WITHOUT_PLUS_SIGN); - } - phoneNumber.setCountryCode(defaultCountryCode); - return defaultCountryCode; + var possibleNumberPattern = + generalDesc.getPossibleNumberPatternOrDefault(); + // If the number was not valid before but is valid now, or if it was too + // long before, we consider the number with the country calling code + // stripped to be a better result and keep that instead. + if ((!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( + validNumberPattern, fullNumber.toString()) && + i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_( + validNumberPattern, potentialNationalNumberStr)) || + this.testNumberLengthAgainstPattern_(possibleNumberPattern, + fullNumber.toString()) == + i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG) { + nationalNumber.append(potentialNationalNumberStr); + if (keepRawInput) { + phoneNumber.setCountryCodeSource( + i18n.phonenumbers.PhoneNumber.CountryCodeSource + .FROM_NUMBER_WITHOUT_PLUS_SIGN); } + phoneNumber.setCountryCode(defaultCountryCode); + return defaultCountryCode; } } } - // No country code present. + // No country calling code present. phoneNumber.setCountryCode(0); return 0; }; @@ -2372,7 +2663,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode = * Strips the IDD from the start of the number if present. Helper function used * by maybeStripInternationalPrefixAndNormalize. * - * @param {RegExp} iddPattern the regular expression for the international + * @param {!RegExp} iddPattern the regular expression for the international * prefix. * @param {!goog.string.StringBuffer} number the phone number that we wish to * strip any international dialing prefix from. @@ -2387,7 +2678,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parsePrefixAsIdd_ = if (numberStr.search(iddPattern) == 0) { /** @type {number} */ var matchEnd = numberStr.match(iddPattern)[0].length; - /** @type {Array. } */ + /** @type {Array.} */ var matchedGroups = numberStr.substring(matchEnd).match( i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN_); if (matchedGroups && matchedGroups[1] != null && @@ -2416,7 +2707,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parsePrefixAsIdd_ = * @param {!goog.string.StringBuffer} number the non-normalized telephone number * that we wish to strip any international dialing prefix from. * @param {string} possibleIddPrefix the international direct dialing prefix - * from the country we think this number may be dialed in. + * from the region we think this number may be dialed in. * @return {i18n.phonenumbers.PhoneNumber.CountryCodeSource} the corresponding * CountryCodeSource if an international dialing prefix could be removed * from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if @@ -2434,7 +2725,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. if (i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_.test(numberStr)) { numberStr = numberStr.replace( i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_, ''); - // Can now normalize the rest of the number since we've consumed the "+" + // Can now normalize the rest of the number since we've consumed the '+' // sign at the start. number.clear(); number.append(i18n.phonenumbers.PhoneNumberUtil.normalize(numberStr)); @@ -2442,7 +2733,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. .FROM_NUMBER_WITH_PLUS_SIGN; } // Attempt to parse the first digits as an international prefix. - /** @type {RegExp} */ + /** @type {!RegExp} */ var iddPattern = new RegExp(possibleIddPrefix); if (this.parsePrefixAsIdd_(iddPattern, number)) { i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(number); @@ -2464,7 +2755,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. * @param {!goog.string.StringBuffer} number the normalized telephone number * that we wish to strip any national dialing prefix from. * @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the - * country that we think this number is from. + * region that we think this number is from. * @return {string} the carrier code extracted if it is present, otherwise * return an empty string. */ @@ -2485,14 +2776,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype. return carrierCode; } // Attempt to parse the first digits as a national prefix. - /** @type {RegExp} */ - var prefixPattern = new RegExp('^' + possibleNationalPrefix); + /** @type {!RegExp} */ + var prefixPattern = new RegExp('^(?:' + possibleNationalPrefix + ')'); /** @type {Array.} */ var prefixMatcher = prefixPattern.exec(numberStr); if (prefixMatcher) { - /** @type {RegExp} */ + /** @type {!RegExp} */ var nationalNumberRule = new RegExp( - metadata.getGeneralDesc().getNationalNumberPattern()); + metadata.getGeneralDesc().getNationalNumberPatternOrDefault()); // prefixMatcher[numOfGroups] == null implies nothing was captured by the // capturing groups in possibleNationalPrefix; therefore, no transformation // is necessary, and we just remove the national prefix. @@ -2553,6 +2844,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeStripExtension = var matchedGroupsLength = matchedGroups.length; for (var i = 1; i < matchedGroupsLength; ++i) { if (matchedGroups[i] != null && matchedGroups[i].length > 0) { + // We go through the capturing groups until we find one that captured + // some digits. If none did, then we will return the empty string. number.clear(); number.append(numberStr.substring(0, mStart)); return matchedGroups[i]; @@ -2566,18 +2859,18 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeStripExtension = /** * Checks to see that the region code used is valid, or if it is not valid, that * the number to parse starts with a + symbol so that we can attempt to infer - * the country from the number. + * the region from the number. * @param {string} numberToParse number that we are attempting to parse. - * @param {?string} defaultCountry the ISO 3166-1 two-letter country code that - * denotes the country that we are expecting the number to be from. + * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that + * denotes the region that we are expecting the number to be from. * @return {boolean} false if it cannot use the region provided and the region * cannot be inferred. * @private */ i18n.phonenumbers.PhoneNumberUtil.prototype.checkRegionForParsing_ = function( - numberToParse, defaultCountry) { - // If the number is null or empty, we can't guess the country code. - return this.isValidRegionCode_(defaultCountry) || + numberToParse, defaultRegion) { + // If the number is null or empty, we can't infer the region. + return this.isValidRegionCode_(defaultRegion) || (numberToParse != null && numberToParse.length > 0 && i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN_.test( numberToParse)); @@ -2586,89 +2879,88 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.checkRegionForParsing_ = function( /** * Parses a string and returns it in proto buffer format. This method will throw - * a i18n.phonenumbers.Error if the number is not considered to be a possible - * number. Note that validation of whether the number is actually a valid number - * for a particular country/region is not performed. This can be done separately - * with isValidNumber. + * a {@link i18n.phonenumbers.Error} if the number is not considered to be a + * possible number. Note that validation of whether the number is actually a + * valid number for a particular region is not performed. This can be done + * separately with {@link #isValidNumber}. * * @param {?string} numberToParse number that we are attempting to parse. This * can contain formatting such as +, ( and -, as well as a phone number * extension. - * @param {?string} defaultCountry the ISO 3166-1 two-letter country code that - * denotes the country that we are expecting the number to be from. This is + * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that + * denotes the region that we are expecting the number to be from. This is * only used if the number being parsed is not written in international - * format. The country code for the number in this case would be stored as - * that of the default country supplied. If the number is guaranteed to - * start with a '+' followed by the country code, then 'ZZ' or null can be + * format. The country_code for the number in this case would be stored as + * that of the default region supplied. If the number is guaranteed to start + * with a '+' followed by the country calling code, then 'ZZ' or null can be * supplied. * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled * with the parsed number. * @throws {i18n.phonenumbers.Error} if the string is not considered to be a - * viable phone number or if no default country was supplied and the number + * viable phone number or if no default region was supplied and the number * is not in international format (does not start with +). */ i18n.phonenumbers.PhoneNumberUtil.prototype.parse = function(numberToParse, - defaultCountry) { - return this.parseHelper_(numberToParse, defaultCountry, false, true); + defaultRegion) { + return this.parseHelper_(numberToParse, defaultRegion, false, true); }; /** * Parses a string and returns it in proto buffer format. This method differs - * from parse() in that it always populates the raw_input field of the protocol - * buffer with numberToParse as well as the country_code_source field. + * from {@link #parse} in that it always populates the raw_input field of the + * protocol buffer with numberToParse as well as the country_code_source field. * * @param {string} numberToParse number that we are attempting to parse. This * can contain formatting such as +, ( and -, as well as a phone number * extension. - * @param {?string} defaultCountry the ISO 3166-1 two-letter country code that - * denotes the country that we are expecting the number to be from. This is + * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that + * denotes the region that we are expecting the number to be from. This is * only used if the number being parsed is not written in international - * format. The country code for the number in this case would be stored as - * that of the default country supplied. + * format. The country calling code for the number in this case would be + * stored as that of the default region supplied. * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled * with the parsed number. * @throws {i18n.phonenumbers.Error} if the string is not considered to be a - * viable phone number or if no default country was supplied and the number - * is not in international format (does not start with +). + * viable phone number or if no default region was supplied. */ i18n.phonenumbers.PhoneNumberUtil.prototype.parseAndKeepRawInput = - function(numberToParse, defaultCountry) { + function(numberToParse, defaultRegion) { - if (!this.isValidRegionCode_(defaultCountry)) { + if (!this.isValidRegionCode_(defaultRegion)) { if (numberToParse.length > 0 && numberToParse.charAt(0) != i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) { throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE; } } - return this.parseHelper_(numberToParse, defaultCountry, true, true); + return this.parseHelper_(numberToParse, defaultRegion, true, true); }; /** * Parses a string and returns it in proto buffer format. This method is the - * same as the public parse() method, with the exception that it allows the - * default country to be null, for use by isNumberMatch(). + * same as the public {@link #parse} method, with the exception that it allows + * the default region to be null, for use by {@link #isNumberMatch}. * * @param {?string} numberToParse number that we are attempting to parse. This * can contain formatting such as +, ( and -, as well as a phone number * extension. - * @param {?string} defaultCountry the ISO 3166-1 two-letter country code that - * denotes the country that we are expecting the number to be from. This is + * @param {?string} defaultRegion the ISO 3166-1 two-letter region code that + * denotes the region that we are expecting the number to be from. This is * only used if the number being parsed is not written in international - * format. The country code for the number in this case would be stored as - * that of the default country supplied. + * format. The country calling code for the number in this case would be + * stored as that of the default region supplied. * @param {boolean} keepRawInput whether to populate the raw_input field of the * phoneNumber with numberToParse. * @param {boolean} checkRegion should be set to false if it is permitted for - * the default country to be null or unknown ('ZZ'). + * the default coregion to be null or unknown ('ZZ'). * @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled * with the parsed number. * @throws {i18n.phonenumbers.Error} * @private */ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = - function(numberToParse, defaultCountry, keepRawInput, checkRegion) { + function(numberToParse, defaultRegion, keepRawInput, checkRegion) { if (numberToParse == null) { throw i18n.phonenumbers.Error.NOT_A_NUMBER; @@ -2682,9 +2974,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = throw i18n.phonenumbers.Error.NOT_A_NUMBER; } - // Check the country supplied is valid, or that the extracted number starts + // Check the region supplied is valid, or that the extracted number starts // with some sort of + sign so the number's region can be determined. - if (checkRegion && !this.checkRegionForParsing_(number, defaultCountry)) { + if (checkRegion && !this.checkRegionForParsing_(number, defaultRegion)) { throw i18n.phonenumbers.Error.INVALID_COUNTRY_CODE; } @@ -2695,8 +2987,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = } /** @type {!goog.string.StringBuffer} */ var nationalNumber = new goog.string.StringBuffer(number); - // Attempt to parse extension first, since it doesn't require - // country-specific data and we want to have the non-normalised number here. + // Attempt to parse extension first, since it doesn't require region-specific + // data and we want to have the non-normalised number here. /** @type {string} */ var extension = this.maybeStripExtension(nationalNumber); if (extension.length > 0) { @@ -2704,28 +2996,28 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = } /** @type {i18n.phonenumbers.PhoneMetadata} */ - var countryMetadata = this.getMetadataForRegion(defaultCountry); + var regionMetadata = this.getMetadataForRegion(defaultRegion); // Check to see if the number is given in international format so we know - // whether this number is from the default country or not. + // whether this number is from the default region or not. /** @type {!goog.string.StringBuffer} */ var normalizedNationalNumber = new goog.string.StringBuffer(); /** @type {number} */ var countryCode = this.maybeExtractCountryCode(nationalNumber.toString(), - countryMetadata, normalizedNationalNumber, keepRawInput, phoneNumber); + regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber); if (countryCode != 0) { /** @type {string} */ var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode); - if (phoneNumberRegion != defaultCountry) { - countryMetadata = this.getMetadataForRegion(phoneNumberRegion); + if (phoneNumberRegion != defaultRegion) { + regionMetadata = this.getMetadataForRegion(phoneNumberRegion); } } else { - // If no extracted country code, use the region supplied instead. The - // national number is just the normalized version of the number we were + // If no extracted country calling code, use the region supplied instead. + // The national number is just the normalized version of the number we were // given to parse. i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(nationalNumber); normalizedNationalNumber.append(nationalNumber.toString()); - if (defaultCountry != null) { - countryCode = countryMetadata.getCountryCodeOrDefault(); + if (defaultRegion != null) { + countryCode = regionMetadata.getCountryCodeOrDefault(); phoneNumber.setCountryCode(countryCode); } else if (keepRawInput) { phoneNumber.clearCountryCodeSource(); @@ -2736,10 +3028,10 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = throw i18n.phonenumbers.Error.TOO_SHORT_NSN; } - if (countryMetadata != null) { + if (regionMetadata != null) { /** @type {string} */ var carrierCode = this.maybeStripNationalPrefixAndCarrierCode( - normalizedNationalNumber, countryMetadata); + normalizedNationalNumber, regionMetadata); if (keepRawInput) { phoneNumber.setPreferredDomesticCarrierCode(carrierCode); } @@ -2757,7 +3049,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = throw i18n.phonenumbers.Error.TOO_LONG; } if (normalizedNationalNumberStr.charAt(0) == '0' && - i18n.phonenumbers.PhoneNumberUtil.isLeadingZeroCountry(countryCode)) { + regionMetadata != null && + regionMetadata.getLeadingZeroPossibleOrDefault()) { phoneNumber.setItalianLeadingZero(true); } phoneNumber.setNationalNumber(parseInt(normalizedNationalNumberStr, 10)); @@ -2768,22 +3061,22 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ = /** * Takes two phone numbers and compares them for equality. * - * Returns EXACT_MATCH if the country code, NSN, presence of a leading zero for - * Italian numbers and any extension present are the same. Returns NSN_MATCH if - * either or both has no country specified, and the NSNs and extensions are the - * same. Returns SHORT_NSN_MATCH if either or both has no country specified, or - * the country specified is the same, and one NSN could be a shorter version of - * the other number. This includes the case where one has an extension + *

Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero + * for Italian numbers and any extension present are the same. Returns NSN_MATCH + * if either or both has no region specified, and the NSNs and extensions are + * the same. Returns SHORT_NSN_MATCH if either or both has no region specified, + * or the region specified is the same, and one NSN could be a shorter version + * of the other number. This includes the case where one has an extension * specified, and the other does not. Returns NO_MATCH otherwise. For example, * the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. The numbers * +1 345 657 1234 and 345 657 are a NO_MATCH. * * @param {i18n.phonenumbers.PhoneNumber|string} firstNumberIn first number to * compare. If it is a string it can contain formatting, and can have - * country code specified with + at the start. + * country calling code specified with + at the start. * @param {i18n.phonenumbers.PhoneNumber|string} secondNumberIn second number to * compare. If it is a string it can contain formatting, and can have - * country code specified with + at the start. + * country calling code specified with + at the start. * @return {i18n.phonenumbers.PhoneNumberUtil.MatchType} NOT_A_NUMBER, NO_MATCH, * SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of * equality of the two numbers, described in the method definition. @@ -2799,8 +3092,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch = /** @type {i18n.phonenumbers.PhoneNumber} */ var secondNumber; if (typeof firstNumberIn == 'string') { - // First see if the first number has an implicit country code, by attempting - // to parse it. + // First see if the first number has an implicit country calling code, by + // attempting to parse it. try { firstNumber = this.parse( firstNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_); @@ -2808,7 +3101,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch = if (e != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) { return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER; } - // The first number has no country code. EXACT_MATCH is no longer + // The first number has no country calling code. EXACT_MATCH is no longer // possible. We parse it as if the region was the same as that for the // second number, and if EXACT_MATCH is returned, we replace this with // NSN_MATCH. @@ -2832,8 +3125,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch = return match; } } - // If the second number is a string or doesn't have a valid country code, - // we parse the first number without country code. + // If the second number is a string or doesn't have a valid country + // calling code, we parse the first number without country calling code. try { firstNumber = this.parseHelper_(firstNumberIn, null, false, false); } catch (e2) { @@ -2882,7 +3175,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch = var firstNumberCountryCode = firstNumber.getCountryCodeOrDefault(); /** @type {number} */ var secondNumberCountryCode = secondNumber.getCountryCodeOrDefault(); - // Both had country code specified. + // Both had country_code specified. if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) { if (firstNumber.equals(secondNumber)) { return i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH; @@ -2897,8 +3190,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch = // This is not a match. return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH; } - // Checks cases where one or both country codes were not specified. To make - // equality checks easier, we first set the country codes to be equal. + // Checks cases where one or both country_code fields were not specified. To + // make equality checks easier, we first set the country_code fields to be + // equal. firstNumber.setCountryCode(0); secondNumber.setCountryCode(0); // If all else was the same, then this is an NSN_MATCH. @@ -2939,14 +3233,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ = /** - * Returns true if the number can only be dialled from within the country. If - * unknown, or the number can be dialled from outside the country as well, + * Returns true if the number can only be dialled from within the region. If + * unknown, or the number can be dialled from outside the region as well, * returns false. Does not check the number is a valid number. * TODO: Make this method public when we have enough metadata to make it * worthwhile. Currently visible for testing purposes only. * * @param {i18n.phonenumbers.PhoneNumber} number the phone-number for which we - * want to know whether it is only diallable from within the country. + * want to know whether it is only diallable from within the region. * @return {boolean} true if the number can only be dialled from within the * country. */ @@ -2955,8 +3249,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled = /** @type {?string} */ var regionCode = this.getRegionCodeForNumber(number); /** @type {string} */ - var nationalSignificantNumber = - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber(number); + var nationalSignificantNumber = this.getNationalSignificantNumber(number); if (!this.isValidRegionCode_(regionCode)) { return true; } @@ -2971,14 +3264,15 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled = * Check whether the entire input sequence can be matched against the regular * expression. * - * @param {RegExp|string} regex the regular expression to match against. + * @param {!RegExp|string} regex the regular expression to match against. * @param {string} str the string to test. * @return {boolean} true if str can be matched entirely against regex. * @private */ i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_ = function(regex, str) { /** @type {Array.} */ - var matchedGroups = str.match(regex); + var matchedGroups = (typeof regex == 'string') ? + str.match('^(?:' + regex + ')$') : str.match(regex); if (matchedGroups && matchedGroups[0].length == str.length) { return true; } diff --git a/javascript/i18n/phonenumbers/phonenumberutil_test.js b/javascript/i18n/phonenumbers/phonenumberutil_test.js index e08431339..caa11b111 100644 --- a/javascript/i18n/phonenumbers/phonenumberutil_test.js +++ b/javascript/i18n/phonenumbers/phonenumberutil_test.js @@ -1,4 +1,4 @@ -/* +/** * @license * Copyright (C) 2010 Google Inc. * @@ -153,9 +153,37 @@ var US_TOLLFREE = new i18n.phonenumbers.PhoneNumber(); US_TOLLFREE.setCountryCode(1); US_TOLLFREE.setNationalNumber(8002530000); + +/** + * Enum containing string constants of region codes for easier testing. + * + * @enum {string} + */ +var RegionCode = { + AD: 'AD', + AO: 'AO', + AR: 'AR', + AU: 'AU', + BS: 'BS', + CS: 'CS', + DE: 'DE', + GB: 'GB', + IT: 'IT', + KR: 'KR', + MX: 'MX', + NZ: 'NZ', + PL: 'PL', + RE: 'RE', + SG: 'SG', + US: 'US', + YT: 'YT', + // Official code for the unknown region. + ZZ: 'ZZ' +}; + function testGetInstanceLoadUSMetadata() { /** @type {i18n.phonenumbers.PhoneMetadata} */ - var metadata = phoneUtil.getMetadataForRegion('US'); + var metadata = phoneUtil.getMetadataForRegion(RegionCode.US); assertEquals('US', metadata.getId()); assertEquals(1, metadata.getCountryCode()); assertEquals('011', metadata.getInternationalPrefix()); @@ -166,7 +194,7 @@ function testGetInstanceLoadUSMetadata() { assertEquals('$1 $2 $3', metadata.getNumberFormat(0).getFormat()); assertEquals('[13-9]\\d{9}|2[0-35-9]\\d{8}', metadata.getGeneralDesc().getNationalNumberPattern()); - assertEquals('\\d{7,10}', + assertEquals('\\d{7}(?:\\d{3})?', metadata.getGeneralDesc().getPossibleNumberPattern()); assertTrue(metadata.getGeneralDesc().equals(metadata.getFixedLine())); assertEquals('\\d{10}', @@ -180,7 +208,7 @@ function testGetInstanceLoadUSMetadata() { function testGetInstanceLoadDEMetadata() { /** @type {i18n.phonenumbers.PhoneMetadata} */ - var metadata = phoneUtil.getMetadataForRegion('DE'); + var metadata = phoneUtil.getMetadataForRegion(RegionCode.DE); assertEquals('DE', metadata.getId()); assertEquals(49, metadata.getCountryCode()); assertEquals('00', metadata.getInternationalPrefix()); @@ -202,7 +230,7 @@ function testGetInstanceLoadDEMetadata() { function testGetInstanceLoadARMetadata() { /** @type {i18n.phonenumbers.PhoneMetadata} */ - var metadata = phoneUtil.getMetadataForRegion('AR'); + var metadata = phoneUtil.getMetadataForRegion(RegionCode.AR); assertEquals('AR', metadata.getId()); assertEquals(54, metadata.getCountryCode()); assertEquals('00', metadata.getInternationalPrefix()); @@ -217,6 +245,15 @@ function testGetInstanceLoadARMetadata() { assertEquals('$1 $2 $3 $4', metadata.getIntlNumberFormat(3).getFormat()); } +function testIsLeadingZeroPossible() { + // Italy + assertTrue(phoneUtil.isLeadingZeroPossible(39)); + // USA + assertFalse(phoneUtil.isLeadingZeroPossible(1)); + // Not in metadata file, just default to false. + assertFalse(phoneUtil.isLeadingZeroPossible(800)); +} + function testGetLengthOfGeographicalAreaCode() { // Google MTV, which has area code '650'. assertEquals(3, phoneUtil.getLengthOfGeographicalAreaCode(US_NUMBER)); @@ -273,7 +310,8 @@ function testGetLengthOfNationalDestinationCode() { assertEquals(0, phoneUtil.getLengthOfNationalDestinationCode(US_SHORT_BY_ONE_NUMBER)); - // A number containing an invalid country code, which shouldn't have any NDC. + // A number containing an invalid country calling code, which shouldn't have + // any NDC. /** @type {i18n.phonenumbers.PhoneNumber} */ var number = new i18n.phonenumbers.PhoneNumber(); number.setCountryCode(123); @@ -283,32 +321,30 @@ function testGetLengthOfNationalDestinationCode() { function testGetNationalSignificantNumber() { assertEquals('6502530000', - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber( - US_NUMBER)); + phoneUtil.getNationalSignificantNumber(US_NUMBER)); // An Italian mobile number. assertEquals('345678901', - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber( - IT_MOBILE)); + phoneUtil.getNationalSignificantNumber(IT_MOBILE)); // An Italian fixed line number. assertEquals('0236618300', - i18n.phonenumbers.PhoneNumberUtil.getNationalSignificantNumber( - IT_NUMBER)); + phoneUtil.getNationalSignificantNumber(IT_NUMBER)); } function testGetExampleNumber() { var PNT = i18n.phonenumbers.PhoneNumberType; - assertTrue(DE_NUMBER.equals(phoneUtil.getExampleNumber('DE'))); + assertTrue(DE_NUMBER.equals(phoneUtil.getExampleNumber(RegionCode.DE))); assertTrue(DE_NUMBER.equals( - phoneUtil.getExampleNumberForType('DE', PNT.FIXED_LINE))); - assertNull(phoneUtil.getExampleNumberForType('DE', PNT.MOBILE)); + phoneUtil.getExampleNumberForType(RegionCode.DE, PNT.FIXED_LINE))); + assertNull(phoneUtil.getExampleNumberForType(RegionCode.DE, PNT.MOBILE)); // For the US, the example number is placed under general description, and // hence should be used for both fixed line and mobile, so neither of these // should return null. - assertNotNull(phoneUtil.getExampleNumberForType('US', PNT.FIXED_LINE)); - assertNotNull(phoneUtil.getExampleNumberForType('US', PNT.MOBILE)); + assertNotNull( + phoneUtil.getExampleNumberForType(RegionCode.US, PNT.FIXED_LINE)); + assertNotNull(phoneUtil.getExampleNumberForType(RegionCode.US, PNT.MOBILE)); } function testNormaliseRemovePunctuation() { @@ -373,6 +409,8 @@ function testFormatUSNumber() { phoneUtil.format(US_PREMIUM, PNF.NATIONAL)); assertEquals('+1 900 253 0000', phoneUtil.format(US_PREMIUM, PNF.INTERNATIONAL)); + assertEquals('+1-900-253-0000', + phoneUtil.format(US_PREMIUM, PNF.RFC3966)); } function testFormatBSNumber() { @@ -402,10 +440,12 @@ function testFormatDENumber() { var deNumber = new i18n.phonenumbers.PhoneNumber(); deNumber.setCountryCode(49); deNumber.setNationalNumber(301234); - assertEquals('030 1234', + assertEquals('030/1234', phoneUtil.format(deNumber, PNF.NATIONAL)); - assertEquals('+49 30 1234', + assertEquals('+49 30/1234', phoneUtil.format(deNumber, PNF.INTERNATIONAL)); + assertEquals('+49-30-1234', + phoneUtil.format(deNumber, PNF.RFC3966)); deNumber = new i18n.phonenumbers.PhoneNumber(); deNumber.setCountryCode(49); @@ -511,47 +551,52 @@ function testFormatARNumber() { function testFormatOutOfCountryCallingNumber() { assertEquals('00 1 900 253 0000', - phoneUtil.formatOutOfCountryCallingNumber(US_PREMIUM, 'DE')); + phoneUtil.formatOutOfCountryCallingNumber(US_PREMIUM, RegionCode.DE)); assertEquals('1 650 253 0000', - phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, 'BS')); + phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.BS)); assertEquals('0~0 1 650 253 0000', - phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, 'PL')); + phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.PL)); assertEquals('011 44 7912 345 678', - phoneUtil.formatOutOfCountryCallingNumber(GB_MOBILE, 'US')); + phoneUtil.formatOutOfCountryCallingNumber(GB_MOBILE, RegionCode.US)); assertEquals('00 49 1234', - phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, 'GB')); + phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, + RegionCode.GB)); // Note this number is correctly formatted without national prefix. Most of // the numbers that are treated as invalid numbers by the library are short // numbers, and they are usually not dialed with national prefix. assertEquals('1234', - phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, 'DE')); + phoneUtil.formatOutOfCountryCallingNumber(DE_SHORT_NUMBER, + RegionCode.DE)); assertEquals('011 39 02 3661 8300', - phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, 'US')); + phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.US)); assertEquals('02 3661 8300', - phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, 'IT')); + phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.IT)); assertEquals('+39 02 3661 8300', - phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, 'SG')); + phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, RegionCode.SG)); assertEquals('6521 8000', - phoneUtil.formatOutOfCountryCallingNumber(SG_NUMBER, 'SG')); + phoneUtil.formatOutOfCountryCallingNumber(SG_NUMBER, RegionCode.SG)); assertEquals('011 54 9 11 8765 4321', - phoneUtil.formatOutOfCountryCallingNumber(AR_MOBILE, 'US')); + phoneUtil.formatOutOfCountryCallingNumber(AR_MOBILE, RegionCode.US)); /** @type {i18n.phonenumbers.PhoneNumber} */ var arNumberWithExtn = AR_MOBILE.clone(); arNumberWithExtn.setExtension('1234'); assertEquals('011 54 9 11 8765 4321 ext. 1234', - phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, 'US')); + phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, + RegionCode.US)); assertEquals('0011 54 9 11 8765 4321 ext. 1234', - phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, 'AU')); + phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, + RegionCode.AU)); assertEquals('011 15 8765-4321 ext. 1234', - phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, 'AR')); + phoneUtil.formatOutOfCountryCallingNumber(arNumberWithExtn, + RegionCode.AR)); } function testFormatOutOfCountryWithPreferredIntlPrefix() { @@ -559,7 +604,102 @@ function testFormatOutOfCountryWithPreferredIntlPrefix() { // (both 0011 and 0012 are accepted as possible international prefixes in our // test metadta.) assertEquals('0011 39 02 3661 8300', - phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, 'AU')); + phoneUtil.formatOutOfCountryCallingNumber(IT_NUMBER, + RegionCode.AU)); +} + +function testFormatOutOfCountryKeepingAlphaChars() { + /** @type {i18n.phonenumbers.PhoneNumber} */ + var alphaNumericNumber = new i18n.phonenumbers.PhoneNumber(); + alphaNumericNumber.setCountryCode(1); + alphaNumericNumber.setNationalNumber(8007493524); + alphaNumericNumber.setRawInput('1800 six-flag'); + assertEquals('0011 1 800 SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.AU)); + + alphaNumericNumber.setRawInput('1-800-SIX-flag'); + assertEquals('0011 1 800-SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.AU)); + + alphaNumericNumber.setRawInput('Call us from UK: 00 1 800 SIX-flag'); + assertEquals('0011 1 800 SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.AU)); + + alphaNumericNumber.setRawInput('800 SIX-flag'); + assertEquals('0011 1 800 SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.AU)); + + // Formatting from within the NANPA region. + assertEquals('1 800 SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.US)); + + assertEquals('1 800 SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.BS)); + + // Testing that if the raw input doesn't exist, it is formatted using + // formatOutOfCountryCallingNumber. + alphaNumericNumber.clearRawInput(); + assertEquals('00 1 800 749 3524', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.DE)); + + // Testing AU alpha number formatted from Australia. + alphaNumericNumber.setCountryCode(61); + alphaNumericNumber.setNationalNumber(827493524); + alphaNumericNumber.setRawInput('+61 82749-FLAG'); + // This number should have the national prefix fixed. + assertEquals('082749-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.AU)); + + alphaNumericNumber.setRawInput('082749-FLAG'); + assertEquals('082749-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.AU)); + + alphaNumericNumber.setNationalNumber(18007493524); + alphaNumericNumber.setRawInput('1-800-SIX-flag'); + // This number should not have the national prefix prefixed, in accordance + // with the override for this specific formatting rule. + assertEquals('1-800-SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.AU)); + + // The metadata should not be permanently changed, since we copied it before + // modifying patterns. Here we check this. + alphaNumericNumber.setNationalNumber(1800749352); + assertEquals('1800 749 352', + phoneUtil.formatOutOfCountryCallingNumber(alphaNumericNumber, + RegionCode.AU)); + + // Testing a region with multiple international prefixes. + assertEquals('+61 1-800-SIX-FLAG', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.SG)); + + // Testing the case with an invalid country calling code. + alphaNumericNumber.setCountryCode(0); + alphaNumericNumber.setNationalNumber(18007493524); + alphaNumericNumber.setRawInput('1-800-SIX-flag'); + // Uses the raw input only. + assertEquals('1-800-SIX-flag', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.DE)); + + // Testing the case of an invalid alpha number. + alphaNumericNumber.setCountryCode(1); + alphaNumericNumber.setNationalNumber(80749); + alphaNumericNumber.setRawInput('180-SIX'); + // No country-code stripping can be done. + assertEquals('00 1 180-SIX', + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, + RegionCode.DE)); } function testFormatWithCarrierCode() { @@ -700,6 +840,9 @@ function testFormatNumberWithExtension() { // Uses default extension prefix: assertEquals('03-331 6005 ext. 1234', phoneUtil.format(nzNumber, PNF.NATIONAL)); + // Uses RFC 3966 syntax. + assertEquals('+64-3-331-6005;ext=1234', + phoneUtil.format(nzNumber, PNF.RFC3966)); // Extension prefix overridden in the territory information for the US: /** @type {i18n.phonenumbers.PhoneNumber} */ var usNumberWithExtension = US_NUMBER.clone(); @@ -710,29 +853,30 @@ function testFormatNumberWithExtension() { function testFormatUsingOriginalNumberFormat() { /** @type {i18n.phonenumbers.PhoneNumber} */ - var number1 = phoneUtil.parseAndKeepRawInput('+442087654321', 'GB'); + var number1 = phoneUtil.parseAndKeepRawInput('+442087654321', RegionCode.GB); assertEquals('+44 20 8765 4321', - phoneUtil.formatInOriginalFormat(number1, 'GB')); + phoneUtil.formatInOriginalFormat(number1, RegionCode.GB)); /** @type {i18n.phonenumbers.PhoneNumber} */ - var number2 = phoneUtil.parseAndKeepRawInput('02087654321', 'GB'); + var number2 = phoneUtil.parseAndKeepRawInput('02087654321', RegionCode.GB); assertEquals('(020) 8765 4321', - phoneUtil.formatInOriginalFormat(number2, 'GB')); + phoneUtil.formatInOriginalFormat(number2, RegionCode.GB)); /** @type {i18n.phonenumbers.PhoneNumber} */ - var number3 = phoneUtil.parseAndKeepRawInput('011442087654321', 'US'); + var number3 = phoneUtil.parseAndKeepRawInput('011442087654321', + RegionCode.US); assertEquals('011 44 20 8765 4321', - phoneUtil.formatInOriginalFormat(number3, 'US')); + phoneUtil.formatInOriginalFormat(number3, RegionCode.US)); /** @type {i18n.phonenumbers.PhoneNumber} */ - var number4 = phoneUtil.parseAndKeepRawInput('442087654321', 'GB'); + var number4 = phoneUtil.parseAndKeepRawInput('442087654321', RegionCode.GB); assertEquals('44 20 8765 4321', - phoneUtil.formatInOriginalFormat(number4, 'GB')); + phoneUtil.formatInOriginalFormat(number4, RegionCode.GB)); /** @type {i18n.phonenumbers.PhoneNumber} */ - var number5 = phoneUtil.parse('+442087654321', 'GB'); + var number5 = phoneUtil.parse('+442087654321', RegionCode.GB); assertEquals('(020) 8765 4321', - phoneUtil.formatInOriginalFormat(number5, 'GB')); + phoneUtil.formatInOriginalFormat(number5, RegionCode.GB)); } function testIsPremiumRate() { @@ -870,9 +1014,9 @@ function testIsValidNumber() { function testIsValidForRegion() { // This number is valid for the Bahamas, but is not a valid US number. assertTrue(phoneUtil.isValidNumber(BS_NUMBER)); - assertTrue(phoneUtil.isValidNumberForRegion(BS_NUMBER, 'BS')); + assertTrue(phoneUtil.isValidNumberForRegion(BS_NUMBER, RegionCode.BS)); assertTrue(phoneUtil.isValidNumberForRegion(BS_NUMBER, 'bs')); - assertFalse(phoneUtil.isValidNumberForRegion(BS_NUMBER, 'US')); + assertFalse(phoneUtil.isValidNumberForRegion(BS_NUMBER, RegionCode.US)); /** @type {i18n.phonenumbers.PhoneNumber} */ var bsInvalidNumber = new i18n.phonenumbers.PhoneNumber(); bsInvalidNumber.setCountryCode(1); @@ -886,24 +1030,24 @@ function testIsValidForRegion() { reNumber.setCountryCode(262); reNumber.setNationalNumber(262123456); assertTrue(phoneUtil.isValidNumber(reNumber)); - assertTrue(phoneUtil.isValidNumberForRegion(reNumber, 'RE')); - assertFalse(phoneUtil.isValidNumberForRegion(reNumber, 'YT')); + assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE)); + assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT)); // Now change the number to be a number for La Mayotte. reNumber.setNationalNumber(269601234); - assertTrue(phoneUtil.isValidNumberForRegion(reNumber, 'YT')); - assertFalse(phoneUtil.isValidNumberForRegion(reNumber, 'RE')); + assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT)); + assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE)); // This number is no longer valid for La Reunion. reNumber.setNationalNumber(269123456); - assertFalse(phoneUtil.isValidNumberForRegion(reNumber, 'YT')); - assertFalse(phoneUtil.isValidNumberForRegion(reNumber, 'RE')); + assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT)); + assertFalse(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE)); assertFalse(phoneUtil.isValidNumber(reNumber)); // However, it should be recognised as from La Mayotte, since it is valid for // this region. - assertEquals('YT', phoneUtil.getRegionCodeForNumber(reNumber)); + assertEquals(RegionCode.YT, phoneUtil.getRegionCodeForNumber(reNumber)); // This number is valid in both places. reNumber.setNationalNumber(800123456); - assertTrue(phoneUtil.isValidNumberForRegion(reNumber, 'YT')); - assertTrue(phoneUtil.isValidNumberForRegion(reNumber, 'RE')); + assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT)); + assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE)); } function testIsNotValidNumber() { @@ -933,46 +1077,46 @@ function testIsNotValidNumber() { } function testGetRegionCodeForCountryCode() { - assertEquals('US', phoneUtil.getRegionCodeForCountryCode(1)); - assertEquals('GB', phoneUtil.getRegionCodeForCountryCode(44)); - assertEquals('DE', phoneUtil.getRegionCodeForCountryCode(49)); + assertEquals(RegionCode.US, phoneUtil.getRegionCodeForCountryCode(1)); + assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForCountryCode(44)); + assertEquals(RegionCode.DE, phoneUtil.getRegionCodeForCountryCode(49)); } function testGetRegionCodeForNumber() { - assertEquals('BS', phoneUtil.getRegionCodeForNumber(BS_NUMBER)); - assertEquals('US', phoneUtil.getRegionCodeForNumber(US_NUMBER)); - assertEquals('GB', phoneUtil.getRegionCodeForNumber(GB_MOBILE)); + assertEquals(RegionCode.BS, phoneUtil.getRegionCodeForNumber(BS_NUMBER)); + assertEquals(RegionCode.US, phoneUtil.getRegionCodeForNumber(US_NUMBER)); + assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForNumber(GB_MOBILE)); } function testGetCountryCodeForRegion() { - assertEquals(1, phoneUtil.getCountryCodeForRegion('US')); - assertEquals(64, phoneUtil.getCountryCodeForRegion('NZ')); + assertEquals(1, phoneUtil.getCountryCodeForRegion(RegionCode.US)); + assertEquals(64, phoneUtil.getCountryCodeForRegion(RegionCode.NZ)); assertEquals(64, phoneUtil.getCountryCodeForRegion('nz')); assertEquals(0, phoneUtil.getCountryCodeForRegion(null)); - assertEquals(0, phoneUtil.getCountryCodeForRegion('ZZ')); + assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.ZZ)); // CS is already deprecated so the library doesn't support it. - assertEquals(0, phoneUtil.getCountryCodeForRegion('CS')); + assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.CS)); } function testGetNationalDiallingPrefixForRegion() { - assertEquals('1', phoneUtil.getNddPrefixForRegion('US', false)); + assertEquals('1', phoneUtil.getNddPrefixForRegion(RegionCode.US, false)); // Test non-main country to see it gets the national dialling prefix for the // main country with that country calling code. - assertEquals('1', phoneUtil.getNddPrefixForRegion('BS', false)); - assertEquals('0', phoneUtil.getNddPrefixForRegion('NZ', false)); + assertEquals('1', phoneUtil.getNddPrefixForRegion(RegionCode.BS, false)); + assertEquals('0', phoneUtil.getNddPrefixForRegion(RegionCode.NZ, false)); // Test case with non digit in the national prefix. - assertEquals('0~0', phoneUtil.getNddPrefixForRegion('AO', false)); - assertEquals('00', phoneUtil.getNddPrefixForRegion('AO', true)); + assertEquals('0~0', phoneUtil.getNddPrefixForRegion(RegionCode.AO, false)); + assertEquals('00', phoneUtil.getNddPrefixForRegion(RegionCode.AO, true)); // Test cases with invalid regions. assertNull(phoneUtil.getNddPrefixForRegion(null, false)); - assertNull(phoneUtil.getNddPrefixForRegion('ZZ', false)); + assertNull(phoneUtil.getNddPrefixForRegion(RegionCode.ZZ, false)); // CS is already deprecated so the library doesn't support it. - assertNull(phoneUtil.getNddPrefixForRegion('CS', false)); + assertNull(phoneUtil.getNddPrefixForRegion(RegionCode.CS, false)); } function testIsNANPACountry() { - assertTrue(phoneUtil.isNANPACountry('US')); - assertTrue(phoneUtil.isNANPACountry('BS')); + assertTrue(phoneUtil.isNANPACountry(RegionCode.US)); + assertTrue(phoneUtil.isNANPACountry(RegionCode.BS)); assertTrue(phoneUtil.isNANPACountry('bs')); } @@ -981,21 +1125,31 @@ function testIsPossibleNumber() { assertTrue(phoneUtil.isPossibleNumber(US_LOCAL_NUMBER)); assertTrue(phoneUtil.isPossibleNumber(GB_NUMBER)); - assertTrue(phoneUtil.isPossibleNumberString('+1 650 253 0000', 'US')); - assertTrue(phoneUtil.isPossibleNumberString('+1 650 GOO OGLE', 'US')); - assertTrue(phoneUtil.isPossibleNumberString('(650) 253-0000', 'US')); - assertTrue(phoneUtil.isPossibleNumberString('253-0000', 'US')); - assertTrue(phoneUtil.isPossibleNumberString('+1 650 253 0000', 'GB')); - assertTrue(phoneUtil.isPossibleNumberString('+44 20 7031 3000', 'GB')); - assertTrue(phoneUtil.isPossibleNumberString('(020) 7031 3000', 'GB')); - assertTrue(phoneUtil.isPossibleNumberString('7031 3000', 'GB')); - assertTrue(phoneUtil.isPossibleNumberString('3331 6005', 'NZ')); - assertTrue(phoneUtil.isPossibleNumberString('3331 6005', 'nz')); + assertTrue( + phoneUtil.isPossibleNumberString('+1 650 253 0000', RegionCode.US)); + assertTrue( + phoneUtil.isPossibleNumberString('+1 650 GOO OGLE', RegionCode.US)); + assertTrue( + phoneUtil.isPossibleNumberString('(650) 253-0000', RegionCode.US)); + assertTrue( + phoneUtil.isPossibleNumberString('253-0000', RegionCode.US)); + assertTrue( + phoneUtil.isPossibleNumberString('+1 650 253 0000', RegionCode.GB)); + assertTrue( + phoneUtil.isPossibleNumberString('+44 20 7031 3000', RegionCode.GB)); + assertTrue( + phoneUtil.isPossibleNumberString('(020) 7031 3000', RegionCode.GB)); + assertTrue( + phoneUtil.isPossibleNumberString('7031 3000', RegionCode.GB)); + assertTrue( + phoneUtil.isPossibleNumberString('3331 6005', RegionCode.NZ)); + assertTrue( + phoneUtil.isPossibleNumberString('3331 6005', 'nz')); } function testIsPossibleNumberWithReason() { var VR = i18n.phonenumbers.PhoneNumberUtil.ValidationResult; - // FYI, national numbers for country code +1 that are within 7 to 10 digits + // National numbers for country calling code +1 that are within 7 to 10 digits // are possible. assertEquals(VR.IS_POSSIBLE, phoneUtil.isPossibleNumberWithReason(US_NUMBER)); @@ -1019,6 +1173,12 @@ function testIsPossibleNumberWithReason() { assertEquals(VR.TOO_SHORT, phoneUtil.isPossibleNumberWithReason(number)); + number = new i18n.phonenumbers.PhoneNumber(); + number.setCountryCode(65); + number.setNationalNumber(1234567890); + assertEquals(VR.IS_POSSIBLE, + phoneUtil.isPossibleNumberWithReason(number)); + // Try with number that we don't have metadata for. /** @type {i18n.phonenumbers.PhoneNumber} */ var adNumber = new i18n.phonenumbers.PhoneNumber(); @@ -1050,12 +1210,18 @@ function testIsNotPossibleNumber() { number.setNationalNumber(300); assertFalse(phoneUtil.isPossibleNumber(number)); - assertFalse(phoneUtil.isPossibleNumberString('+1 650 253 00000', 'US')); - assertFalse(phoneUtil.isPossibleNumberString('(650) 253-00000', 'US')); - assertFalse(phoneUtil.isPossibleNumberString('I want a Pizza', 'US')); - assertFalse(phoneUtil.isPossibleNumberString('253-000', 'US')); - assertFalse(phoneUtil.isPossibleNumberString('1 3000', 'GB')); - assertFalse(phoneUtil.isPossibleNumberString('+44 300', 'GB')); + assertFalse( + phoneUtil.isPossibleNumberString('+1 650 253 00000', RegionCode.US)); + assertFalse( + phoneUtil.isPossibleNumberString('(650) 253-00000', RegionCode.US)); + assertFalse( + phoneUtil.isPossibleNumberString('I want a Pizza', RegionCode.US)); + assertFalse( + phoneUtil.isPossibleNumberString('253-000', RegionCode.US)); + assertFalse( + phoneUtil.isPossibleNumberString('1 3000', RegionCode.GB)); + assertFalse( + phoneUtil.isPossibleNumberString('+44 300', RegionCode.GB)); } function testTruncateTooLongNumber() { @@ -1271,7 +1437,7 @@ function testMaybeStripInternationalPrefix() { strippedNumber.toString(), numberToStrip.toString()); // If the number afterwards is a zero, we should not strip this - no country - // code begins with 0. + // calling code begins with 0. numberToStrip = new goog.string.StringBuffer('0090112-3123'); strippedNumber = new goog.string.StringBuffer('00901123123'); assertEquals(CCS.FROM_DEFAULT_COUNTRY, @@ -1292,7 +1458,7 @@ function testMaybeExtractCountryCode() { /** @type {i18n.phonenumbers.PhoneNumber} */ var number = new i18n.phonenumbers.PhoneNumber(); /** @type {i18n.phonenumbers.PhoneMetadata} */ - var metadata = phoneUtil.getMetadataForRegion('US'); + var metadata = phoneUtil.getMetadataForRegion(RegionCode.US); // Note that for the US, the IDD is 011. try { /** @type {string} */ @@ -1300,18 +1466,19 @@ function testMaybeExtractCountryCode() { /** @type {string} */ var strippedNumber = '123456789'; /** @type {number} */ - var countryCode = 1; + var countryCallingCode = 1; /** @type {!goog.string.StringBuffer} */ var numberToFill = new goog.string.StringBuffer(); - assertEquals('Did not extract country code ' + countryCode + ' correctly.', - countryCode, + assertEquals('Did not extract country calling code ' + countryCallingCode + + ' correctly.', + countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals('Did not figure out CountryCodeSource correctly', CCS.FROM_NUMBER_WITH_IDD, number.getCountryCodeSource()); // Should strip and normalize national significant number. - assertEquals('Did not strip off the country code correctly.', + assertEquals('Did not strip off the country calling code correctly.', strippedNumber, numberToFill.toString()); } catch (e) { @@ -1320,10 +1487,11 @@ function testMaybeExtractCountryCode() { number = new i18n.phonenumbers.PhoneNumber(); try { phoneNumber = '+6423456789'; - countryCode = 64; + countryCallingCode = 64; numberToFill = new goog.string.StringBuffer(); - assertEquals('Did not extract country code ' + countryCode + ' correctly.', - countryCode, + assertEquals('Did not extract country calling code ' + countryCallingCode + + ' correctly.', + countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals('Did not figure out CountryCodeSource correctly', @@ -1336,7 +1504,7 @@ function testMaybeExtractCountryCode() { try { phoneNumber = '2345-6789'; numberToFill = new goog.string.StringBuffer(); - assertEquals('Should not have extracted a country code - ' + + assertEquals('Should not have extracted a country calling code - ' + 'no international prefix present.', 0, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, @@ -1353,7 +1521,8 @@ function testMaybeExtractCountryCode() { numberToFill = new goog.string.StringBuffer(); phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number); - fail('Should have thrown an exception, no valid country code present.'); + fail('Should have thrown an exception, no valid country calling code ' + + 'present.'); } catch (e) { // Expected. assertEquals('Wrong error type stored in exception.', @@ -1363,11 +1532,11 @@ function testMaybeExtractCountryCode() { number = new i18n.phonenumbers.PhoneNumber(); try { phoneNumber = '(1 610) 619 4466'; - countryCode = 1; + countryCallingCode = 1; numberToFill = new goog.string.StringBuffer(); - assertEquals('Should have extracted the country code of the region ' + - 'passed in', - countryCode, + assertEquals('Should have extracted the country calling code of the ' + + 'region passed in', + countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); assertEquals('Did not figure out CountryCodeSource correctly', @@ -1379,11 +1548,11 @@ function testMaybeExtractCountryCode() { number = new i18n.phonenumbers.PhoneNumber(); try { phoneNumber = '(1 610) 619 4466'; - countryCode = 1; + countryCallingCode = 1; numberToFill = new goog.string.StringBuffer(); - assertEquals('Should have extracted the country code of the region ' + - 'passed in', - countryCode, + assertEquals('Should have extracted the country calling code of the ' + + 'region passed in', + countryCallingCode, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, false, number)); @@ -1396,8 +1565,8 @@ function testMaybeExtractCountryCode() { try { phoneNumber = '(1 610) 619 446'; numberToFill = new goog.string.StringBuffer(); - assertEquals('Should not have extracted a country code - ' + - 'invalid number after extraction of uncertain country code.', + assertEquals('Should not have extracted a country calling code - invalid ' + + 'number after extraction of uncertain country calling code.', 0, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, false, @@ -1409,10 +1578,11 @@ function testMaybeExtractCountryCode() { } number = new i18n.phonenumbers.PhoneNumber(); try { - phoneNumber = '(1 610) 619 43'; + phoneNumber = '(1 610) 619'; numberToFill = new goog.string.StringBuffer(); - assertEquals('Should not have extracted a country code - invalid number ' + - 'both before and after extraction of uncertain country code.', + assertEquals('Should not have extracted a country calling code - too ' + + 'short number both before and after extraction of uncertain ' + + 'country calling code.', 0, phoneUtil.maybeExtractCountryCode(phoneNumber, metadata, numberToFill, true, number)); @@ -1426,36 +1596,39 @@ function testMaybeExtractCountryCode() { function testParseNationalNumber() { // National prefix attached. - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('033316005', 'NZ'))); + assertTrue(NZ_NUMBER.equals(phoneUtil.parse('033316005', RegionCode.NZ))); assertTrue(NZ_NUMBER.equals(phoneUtil.parse('033316005', 'nz'))); - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('33316005', 'NZ'))); + assertTrue(NZ_NUMBER.equals(phoneUtil.parse('33316005', RegionCode.NZ))); // National prefix attached and some formatting present. - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('03-331 6005', 'NZ'))); - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('03 331 6005', 'NZ'))); + assertTrue(NZ_NUMBER.equals(phoneUtil.parse('03-331 6005', RegionCode.NZ))); + assertTrue(NZ_NUMBER.equals(phoneUtil.parse('03 331 6005', RegionCode.NZ))); // Testing international prefixes. - // Should strip country code. - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('0064 3 331 6005', 'NZ'))); + // Should strip country calling code. + assertTrue( + NZ_NUMBER.equals(phoneUtil.parse('0064 3 331 6005', RegionCode.NZ))); // Try again, but this time we have an international number with Region Code - // US. It should recognise the country code and parse accordingly. - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('01164 3 331 6005', 'US'))); - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('+64 3 331 6005', 'US'))); + // US. It should recognise the country calling code and parse accordingly. + assertTrue( + NZ_NUMBER.equals(phoneUtil.parse('01164 3 331 6005', RegionCode.US))); + assertTrue( + NZ_NUMBER.equals(phoneUtil.parse('+64 3 331 6005', RegionCode.US))); /** @type {i18n.phonenumbers.PhoneNumber} */ var nzNumber = new i18n.phonenumbers.PhoneNumber(); nzNumber.setCountryCode(64); nzNumber.setNationalNumber(64123456); - assertTrue(nzNumber.equals(phoneUtil.parse('64(0)64123456', 'NZ'))); + assertTrue(nzNumber.equals(phoneUtil.parse('64(0)64123456', RegionCode.NZ))); // Check that using a '/' is fine in a phone number. - assertTrue(DE_NUMBER.equals(phoneUtil.parse('301/23456', 'DE'))); + assertTrue(DE_NUMBER.equals(phoneUtil.parse('301/23456', RegionCode.DE))); /** @type {i18n.phonenumbers.PhoneNumber} */ var usNumber = new i18n.phonenumbers.PhoneNumber(); - // Check it doesn't use the '1' as a country code when parsing if the phone - // number was already possible. + // Check it doesn't use the '1' as a country calling code when parsing if the + // phone number was already possible. usNumber.setCountryCode(1); usNumber.setNationalNumber(1234567890); - assertTrue(usNumber.equals(phoneUtil.parse('123-456-7890', 'US'))); + assertTrue(usNumber.equals(phoneUtil.parse('123-456-7890', RegionCode.US))); } function testParseNumberWithAlphaCharacters() { @@ -1465,67 +1638,70 @@ function testParseNumberWithAlphaCharacters() { tollfreeNumber.setCountryCode(64); tollfreeNumber.setNationalNumber(800332005); assertTrue(tollfreeNumber.equals( - phoneUtil.parse('0800 DDA 005', 'NZ'))); + phoneUtil.parse('0800 DDA 005', RegionCode.NZ))); /** @type {i18n.phonenumbers.PhoneNumber} */ var premiumNumber = new i18n.phonenumbers.PhoneNumber(); premiumNumber.setCountryCode(64); premiumNumber.setNationalNumber(9003326005); assertTrue(premiumNumber.equals( - phoneUtil.parse('0900 DDA 6005', 'NZ'))); + phoneUtil.parse('0900 DDA 6005', RegionCode.NZ))); // Not enough alpha characters for them to be considered intentional, so they // are stripped. assertTrue(premiumNumber.equals( - phoneUtil.parse('0900 332 6005a', 'NZ'))); + phoneUtil.parse('0900 332 6005a', RegionCode.NZ))); assertTrue(premiumNumber.equals( - phoneUtil.parse('0900 332 600a5', 'NZ'))); + phoneUtil.parse('0900 332 600a5', RegionCode.NZ))); assertTrue(premiumNumber.equals( - phoneUtil.parse('0900 332 600A5', 'NZ'))); + phoneUtil.parse('0900 332 600A5', RegionCode.NZ))); assertTrue(premiumNumber.equals( - phoneUtil.parse('0900 a332 600A5', 'NZ'))); + phoneUtil.parse('0900 a332 600A5', RegionCode.NZ))); } function testParseWithInternationalPrefixes() { assertTrue(US_NUMBER.equals( - phoneUtil.parse('+1 (650) 253-0000', 'NZ'))); + phoneUtil.parse('+1 (650) 253-0000', RegionCode.NZ))); assertTrue(US_NUMBER.equals( - phoneUtil.parse('1-650-253-0000', 'US'))); + phoneUtil.parse('1-650-253-0000', RegionCode.US))); // Calling the US number from Singapore by using different service providers // 1st test: calling using SingTel IDD service (IDD is 001) assertTrue(US_NUMBER.equals( - phoneUtil.parse('0011-650-253-0000', 'SG'))); + phoneUtil.parse('0011-650-253-0000', RegionCode.SG))); // 2nd test: calling using StarHub IDD service (IDD is 008) assertTrue(US_NUMBER.equals( - phoneUtil.parse('0081-650-253-0000', 'SG'))); + phoneUtil.parse('0081-650-253-0000', RegionCode.SG))); // 3rd test: calling using SingTel V019 service (IDD is 019) assertTrue(US_NUMBER.equals( - phoneUtil.parse('0191-650-253-0000', 'SG'))); + phoneUtil.parse('0191-650-253-0000', RegionCode.SG))); // Calling the US number from Poland assertTrue(US_NUMBER.equals( - phoneUtil.parse('0~01-650-253-0000', 'PL'))); + phoneUtil.parse('0~01-650-253-0000', RegionCode.PL))); // Using '++' at the start. assertTrue(US_NUMBER.equals( - phoneUtil.parse('++1 (650) 253-0000', 'PL'))); + phoneUtil.parse('++1 (650) 253-0000', RegionCode.PL))); // Using a full-width plus sign. assertTrue(US_NUMBER.equals( - phoneUtil.parse('\uFF0B1 (650) 253-0000', 'SG'))); + phoneUtil.parse('\uFF0B1 (650) 253-0000', RegionCode.SG))); // The whole number, including punctuation, is here represented in full-width // form. assertTrue(US_NUMBER.equals( phoneUtil.parse('\uFF0B\uFF11\u3000\uFF08\uFF16\uFF15\uFF10\uFF09' + '\u3000\uFF12\uFF15\uFF13\uFF0D\uFF10\uFF10\uFF10\uFF10', - 'SG'))); + RegionCode.SG))); // Using U+30FC dash instead. assertTrue(US_NUMBER.equals( phoneUtil.parse('\uFF0B\uFF11\u3000\uFF08\uFF16\uFF15\uFF10\uFF09' + '\u3000\uFF12\uFF15\uFF13\u30FC\uFF10\uFF10\uFF10\uFF10', - 'SG'))); + RegionCode.SG))); } function testParseWithLeadingZero() { - assertTrue(IT_NUMBER.equals(phoneUtil.parse('+39 02-36618 300', 'NZ'))); - assertTrue(IT_NUMBER.equals(phoneUtil.parse('02-36618 300', 'IT'))); + assertTrue( + IT_NUMBER.equals(phoneUtil.parse('+39 02-36618 300', RegionCode.NZ))); + assertTrue( + IT_NUMBER.equals(phoneUtil.parse('02-36618 300', RegionCode.IT))); - assertTrue(IT_MOBILE.equals(phoneUtil.parse('345 678 901', 'IT'))); + assertTrue( + IT_MOBILE.equals(phoneUtil.parse('345 678 901', RegionCode.IT))); } function testParseNationalNumberArgentina() { @@ -1534,42 +1710,55 @@ function testParseNationalNumberArgentina() { var arNumber = new i18n.phonenumbers.PhoneNumber(); arNumber.setCountryCode(54); arNumber.setNationalNumber(93435551212); - assertTrue(arNumber.equals( - phoneUtil.parse('+54 9 343 555 1212', 'AR'))); - assertTrue(arNumber.equals(phoneUtil.parse('0343 15 555 1212', 'AR'))); + assertTrue( + arNumber.equals(phoneUtil.parse('+54 9 343 555 1212', RegionCode.AR))); + assertTrue( + arNumber.equals(phoneUtil.parse('0343 15 555 1212', RegionCode.AR))); arNumber = new i18n.phonenumbers.PhoneNumber(); arNumber.setCountryCode(54); arNumber.setNationalNumber(93715654320); - assertTrue(arNumber.equals( - phoneUtil.parse('+54 9 3715 65 4320', 'AR'))); - assertTrue(arNumber.equals(phoneUtil.parse('03715 15 65 4320', 'AR'))); - assertTrue(AR_MOBILE.equals(phoneUtil.parse('911 876 54321', 'AR'))); + assertTrue( + arNumber.equals(phoneUtil.parse('+54 9 3715 65 4320', RegionCode.AR))); + assertTrue( + arNumber.equals(phoneUtil.parse('03715 15 65 4320', RegionCode.AR))); + assertTrue( + AR_MOBILE.equals(phoneUtil.parse('911 876 54321', RegionCode.AR))); // Test parsing fixed-line numbers of Argentina. - assertTrue(AR_NUMBER.equals(phoneUtil.parse('+54 11 8765 4321', 'AR'))); - assertTrue(AR_NUMBER.equals(phoneUtil.parse('011 8765 4321', 'AR'))); + assertTrue( + AR_NUMBER.equals(phoneUtil.parse('+54 11 8765 4321', RegionCode.AR))); + assertTrue( + AR_NUMBER.equals(phoneUtil.parse('011 8765 4321', RegionCode.AR))); arNumber = new i18n.phonenumbers.PhoneNumber(); arNumber.setCountryCode(54); arNumber.setNationalNumber(3715654321); - assertTrue(arNumber.equals(phoneUtil.parse('+54 3715 65 4321', 'AR'))); - assertTrue(arNumber.equals(phoneUtil.parse('03715 65 4321', 'AR'))); + assertTrue( + arNumber.equals(phoneUtil.parse('+54 3715 65 4321', RegionCode.AR))); + assertTrue( + arNumber.equals(phoneUtil.parse('03715 65 4321', RegionCode.AR))); arNumber = new i18n.phonenumbers.PhoneNumber(); arNumber.setCountryCode(54); arNumber.setNationalNumber(2312340000); - assertTrue(arNumber.equals(phoneUtil.parse('+54 23 1234 0000', 'AR'))); - assertTrue(arNumber.equals(phoneUtil.parse('023 1234 0000', 'AR'))); + assertTrue( + arNumber.equals(phoneUtil.parse('+54 23 1234 0000', RegionCode.AR))); + assertTrue( + arNumber.equals(phoneUtil.parse('023 1234 0000', RegionCode.AR))); } function testParseWithXInNumber() { // Test that having an 'x' in the phone number at the start is ok and that it // just gets removed. - assertTrue(AR_NUMBER.equals(phoneUtil.parse('01187654321', 'AR'))); - assertTrue(AR_NUMBER.equals(phoneUtil.parse('(0) 1187654321', 'AR'))); - assertTrue(AR_NUMBER.equals(phoneUtil.parse('0 1187654321', 'AR'))); - assertTrue(AR_NUMBER.equals(phoneUtil.parse('(0xx) 1187654321', 'AR'))); + assertTrue( + AR_NUMBER.equals(phoneUtil.parse('01187654321', RegionCode.AR))); + assertTrue( + AR_NUMBER.equals(phoneUtil.parse('(0) 1187654321', RegionCode.AR))); + assertTrue( + AR_NUMBER.equals(phoneUtil.parse('0 1187654321', RegionCode.AR))); + assertTrue( + AR_NUMBER.equals(phoneUtil.parse('(0xx) 1187654321', RegionCode.AR))); /** @type {i18n.phonenumbers.PhoneNumber} */ var arFromUs = new i18n.phonenumbers.PhoneNumber(); arFromUs.setCountryCode(54); @@ -1579,7 +1768,8 @@ function testParseWithXInNumber() { // extension, as we allow extensions up to 7 digits. This assumption is okay // for now as all the countries where a carrier selection code is written in // the form of xx have a national significant number of length larger than 7. - assertTrue(arFromUs.equals(phoneUtil.parse('011xx5481429712', 'US'))); + assertTrue( + arFromUs.equals(phoneUtil.parse('011xx5481429712', RegionCode.US))); } function testParseNumbersMexico() { @@ -1589,27 +1779,29 @@ function testParseNumbersMexico() { mxNumber.setCountryCode(52); mxNumber.setNationalNumber(4499780001); assertTrue(mxNumber.equals( - phoneUtil.parse('+52 (449)978-0001', 'MX'))); - assertTrue(mxNumber.equals(phoneUtil.parse('01 (449)978-0001', 'MX'))); - assertTrue(mxNumber.equals(phoneUtil.parse('(449)978-0001', 'MX'))); + phoneUtil.parse('+52 (449)978-0001', RegionCode.MX))); + assertTrue( + mxNumber.equals(phoneUtil.parse('01 (449)978-0001', RegionCode.MX))); + assertTrue( + mxNumber.equals(phoneUtil.parse('(449)978-0001', RegionCode.MX))); // Test parsing mobile numbers of Mexico. mxNumber = new i18n.phonenumbers.PhoneNumber(); mxNumber.setCountryCode(52); mxNumber.setNationalNumber(13312345678); assertTrue(mxNumber.equals( - phoneUtil.parse('+52 1 33 1234-5678', 'MX'))); + phoneUtil.parse('+52 1 33 1234-5678', RegionCode.MX))); assertTrue(mxNumber.equals( - phoneUtil.parse('044 (33) 1234-5678', 'MX'))); + phoneUtil.parse('044 (33) 1234-5678', RegionCode.MX))); assertTrue(mxNumber.equals( - phoneUtil.parse('045 33 1234-5678', 'MX'))); + phoneUtil.parse('045 33 1234-5678', RegionCode.MX))); } function testFailedParseOnInvalidNumbers() { try { /** @type {string} */ var sentencePhoneNumber = 'This is not a phone number'; - phoneUtil.parse(sentencePhoneNumber, 'NZ'); + phoneUtil.parse(sentencePhoneNumber, RegionCode.NZ); fail('This should not parse without throwing an exception ' + sentencePhoneNumber); } catch (e) { @@ -1621,7 +1813,7 @@ function testFailedParseOnInvalidNumbers() { try { /** @type {string} */ var tooLongPhoneNumber = '01495 72553301873 810104'; - phoneUtil.parse(tooLongPhoneNumber, 'GB'); + phoneUtil.parse(tooLongPhoneNumber, RegionCode.GB); fail('This should not parse without throwing an exception ' + tooLongPhoneNumber); } catch (e) { @@ -1633,7 +1825,7 @@ function testFailedParseOnInvalidNumbers() { try { /** @type {string} */ var plusMinusPhoneNumber = '+---'; - phoneUtil.parse(plusMinusPhoneNumber, 'DE'); + phoneUtil.parse(plusMinusPhoneNumber, RegionCode.DE); fail('This should not parse without throwing an exception ' + plusMinusPhoneNumber); } catch (e) { @@ -1645,7 +1837,7 @@ function testFailedParseOnInvalidNumbers() { try { /** @type {string} */ var tooShortPhoneNumber = '+49 0'; - phoneUtil.parse(tooShortPhoneNumber, 'DE'); + phoneUtil.parse(tooShortPhoneNumber, RegionCode.DE); fail('This should not parse without throwing an exception ' + tooShortPhoneNumber); } catch (e) { @@ -1657,8 +1849,8 @@ function testFailedParseOnInvalidNumbers() { try { /** @type {string} */ var invalidCountryCode = '+210 3456 56789'; - phoneUtil.parse(invalidCountryCode, 'NZ'); - fail('This is not a recognised country code: should fail: ' + + phoneUtil.parse(invalidCountryCode, RegionCode.NZ); + fail('This is not a recognised region code: should fail: ' + invalidCountryCode); } catch (e) { // Expected this exception. @@ -1669,8 +1861,8 @@ function testFailedParseOnInvalidNumbers() { try { /** @type {string} */ var someNumber = '123 456 7890'; - phoneUtil.parse(someNumber, 'YY'); - fail('Unknown country code not allowed: should fail.'); + phoneUtil.parse(someNumber, RegionCode.ZZ); + fail('Unknown region code not allowed: should fail.'); } catch (e) { // Expected this exception. assertEquals('Wrong error type stored in exception.', @@ -1680,8 +1872,8 @@ function testFailedParseOnInvalidNumbers() { try { /** @type {string} */ someNumber = '123 456 7890'; - phoneUtil.parse(someNumber, 'CS'); - fail('Deprecated country code not allowed: should fail.'); + phoneUtil.parse(someNumber, RegionCode.CS); + fail('Deprecated region code not allowed: should fail.'); } catch (e) { // Expected this exception. assertEquals('Wrong error type stored in exception.', @@ -1691,7 +1883,7 @@ function testFailedParseOnInvalidNumbers() { try { someNumber = '123 456 7890'; phoneUtil.parse(someNumber, null); - fail('Null country code not allowed: should fail.'); + fail('Null region code not allowed: should fail.'); } catch (e) { // Expected this exception. assertEquals('Wrong error type stored in exception.', @@ -1700,8 +1892,8 @@ function testFailedParseOnInvalidNumbers() { } try { someNumber = '0044------'; - phoneUtil.parse(someNumber, 'GB'); - fail('No number provided, only country code: should fail'); + phoneUtil.parse(someNumber, RegionCode.GB); + fail('No number provided, only region code: should fail'); } catch (e) { // Expected this exception. assertEquals('Wrong error type stored in exception.', @@ -1710,8 +1902,8 @@ function testFailedParseOnInvalidNumbers() { } try { someNumber = '0044'; - phoneUtil.parse(someNumber, 'GB'); - fail('No number provided, only country code: should fail'); + phoneUtil.parse(someNumber, RegionCode.GB); + fail('No number provided, only region code: should fail'); } catch (e) { // Expected this exception. assertEquals('Wrong error type stored in exception.', @@ -1720,7 +1912,7 @@ function testFailedParseOnInvalidNumbers() { } try { someNumber = '011'; - phoneUtil.parse(someNumber, 'US'); + phoneUtil.parse(someNumber, RegionCode.US); fail('Only IDD provided - should fail.'); } catch (e) { // Expected this exception. @@ -1730,7 +1922,7 @@ function testFailedParseOnInvalidNumbers() { } try { someNumber = '0119'; - phoneUtil.parse(someNumber, 'US'); + phoneUtil.parse(someNumber, RegionCode.US); fail('Only IDD provided and then 9 - should fail.'); } catch (e) { // Expected this exception. @@ -1742,7 +1934,7 @@ function testFailedParseOnInvalidNumbers() { /** @type {string} */ var emptyNumber = ''; // Invalid region. - phoneUtil.parse(emptyNumber, 'ZZ'); + phoneUtil.parse(emptyNumber, RegionCode.ZZ); fail('Empty string - should fail.'); } catch (e) { // Expected this exception. @@ -1752,7 +1944,7 @@ function testFailedParseOnInvalidNumbers() { } try { // Invalid region. - phoneUtil.parse(null, 'ZZ'); + phoneUtil.parse(null, RegionCode.ZZ); fail('Null string - should fail.'); } catch (e) { // Expected this exception. @@ -1761,7 +1953,7 @@ function testFailedParseOnInvalidNumbers() { e); } try { - phoneUtil.parse(null, 'US'); + phoneUtil.parse(null, RegionCode.US); fail('Null string - should fail.'); } catch (e) { // Expected this exception. @@ -1772,16 +1964,18 @@ function testFailedParseOnInvalidNumbers() { } function testParseNumbersWithPlusWithNoRegion() { - // 'ZZ' is allowed only if the number starts with a '+' - then the country - // code can be calculated. - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('+64 3 331 6005', 'ZZ'))); + // RegionCode.ZZ is allowed only if the number starts with a '+' - then the + // country calling code can be calculated. + assertTrue( + NZ_NUMBER.equals(phoneUtil.parse('+64 3 331 6005', RegionCode.ZZ))); // Test with full-width plus. - assertTrue(NZ_NUMBER.equals( - phoneUtil.parse('\uFF0B64 3 331 6005', 'ZZ'))); + assertTrue( + NZ_NUMBER.equals(phoneUtil.parse('\uFF0B64 3 331 6005', RegionCode.ZZ))); // Test with normal plus but leading characters that need to be stripped. - assertTrue(NZ_NUMBER.equals( - phoneUtil.parse('Tel: +64 3 331 6005', 'ZZ'))); - assertTrue(NZ_NUMBER.equals(phoneUtil.parse('+64 3 331 6005', null))); + assertTrue( + NZ_NUMBER.equals(phoneUtil.parse('Tel: +64 3 331 6005', RegionCode.ZZ))); + assertTrue( + NZ_NUMBER.equals(phoneUtil.parse('+64 3 331 6005', null))); // It is important that we set the carrier code to an empty string, since we // used ParseAndKeepRawInput and no carrier code was found. @@ -1792,7 +1986,7 @@ function testParseNumbersWithPlusWithNoRegion() { .CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN); nzNumberWithRawInput.setPreferredDomesticCarrierCode(''); assertTrue(nzNumberWithRawInput.equals( - phoneUtil.parseAndKeepRawInput('+64 3 331 6005', 'ZZ'))); + phoneUtil.parseAndKeepRawInput('+64 3 331 6005', RegionCode.ZZ))); // Null is also allowed for the region code in these cases. assertTrue(nzNumberWithRawInput.equals( phoneUtil.parseAndKeepRawInput('+64 3 331 6005', null))); @@ -1805,30 +1999,30 @@ function testParseExtensions() { nzNumber.setNationalNumber(33316005); nzNumber.setExtension('3456'); assertTrue(nzNumber.equals( - phoneUtil.parse('03 331 6005 ext 3456', 'NZ'))); + phoneUtil.parse('03 331 6005 ext 3456', RegionCode.NZ))); assertTrue(nzNumber.equals( - phoneUtil.parse('03-3316005x3456', 'NZ'))); + phoneUtil.parse('03-3316005x3456', RegionCode.NZ))); assertTrue(nzNumber.equals( - phoneUtil.parse('03-3316005 int.3456', 'NZ'))); + phoneUtil.parse('03-3316005 int.3456', RegionCode.NZ))); assertTrue(nzNumber.equals( - phoneUtil.parse('03 3316005 #3456', 'NZ'))); + phoneUtil.parse('03 3316005 #3456', RegionCode.NZ))); // Test the following do not extract extensions: assertTrue(ALPHA_NUMERIC_NUMBER.equals( - phoneUtil.parse('1800 six-flags', 'US'))); + phoneUtil.parse('1800 six-flags', RegionCode.US))); assertTrue(ALPHA_NUMERIC_NUMBER.equals( - phoneUtil.parse('1800 SIX FLAGS', 'US'))); + phoneUtil.parse('1800 SIX FLAGS', RegionCode.US))); assertTrue(ALPHA_NUMERIC_NUMBER.equals( - phoneUtil.parse('0~0 1800 7493 5247', 'PL'))); + phoneUtil.parse('0~0 1800 7493 5247', RegionCode.PL))); assertTrue(ALPHA_NUMERIC_NUMBER.equals( - phoneUtil.parse('(1800) 7493.5247', 'US'))); + phoneUtil.parse('(1800) 7493.5247', RegionCode.US))); // Check that the last instance of an extension token is matched. /** @type {i18n.phonenumbers.PhoneNumber} */ var extnNumber = ALPHA_NUMERIC_NUMBER.clone(); extnNumber.setExtension('1234'); assertTrue(extnNumber.equals( - phoneUtil.parse('0~0 1800 7493 5247 ~1234', 'PL'))); + phoneUtil.parse('0~0 1800 7493 5247 ~1234', RegionCode.PL))); // Verifying bug-fix where the last digit of a number was previously omitted // if it was a 0 when extracting the extension. Also verifying a few different @@ -1839,21 +2033,23 @@ function testParseExtensions() { ukNumber.setNationalNumber(2034567890); ukNumber.setExtension('456'); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890x456', 'NZ'))); + phoneUtil.parse('+44 2034567890x456', RegionCode.NZ))); + assertTrue(ukNumber.equals( + phoneUtil.parse('+44 2034567890x456', RegionCode.GB))); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890x456', 'GB'))); + phoneUtil.parse('+44 2034567890 x456', RegionCode.GB))); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890 x456', 'GB'))); + phoneUtil.parse('+44 2034567890 X456', RegionCode.GB))); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890 X456', 'GB'))); + phoneUtil.parse('+44 2034567890 X 456', RegionCode.GB))); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890 X 456', 'GB'))); + phoneUtil.parse('+44 2034567890 X 456', RegionCode.GB))); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890 X 456', 'GB'))); + phoneUtil.parse('+44 2034567890 x 456 ', RegionCode.GB))); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890 x 456 ', 'GB'))); + phoneUtil.parse('+44 2034567890 X 456', RegionCode.GB))); assertTrue(ukNumber.equals( - phoneUtil.parse('+44 2034567890 X 456', 'GB'))); + phoneUtil.parse('+44-2034567890;ext=456', RegionCode.GB))); /** @type {i18n.phonenumbers.PhoneNumber} */ var usWithExtension = new i18n.phonenumbers.PhoneNumber(); @@ -1861,21 +2057,23 @@ function testParseExtensions() { usWithExtension.setNationalNumber(8009013355); usWithExtension.setExtension('7246433'); assertTrue(usWithExtension.equals( - phoneUtil.parse('(800) 901-3355 x 7246433', 'US'))); + phoneUtil.parse('(800) 901-3355 x 7246433', RegionCode.US))); assertTrue(usWithExtension.equals( - phoneUtil.parse('(800) 901-3355 , ext 7246433', 'US'))); + phoneUtil.parse('(800) 901-3355 , ext 7246433', RegionCode.US))); assertTrue(usWithExtension.equals( - phoneUtil.parse('(800) 901-3355 ,extension 7246433', 'US'))); + phoneUtil.parse('(800) 901-3355 ,extension 7246433', RegionCode.US))); assertTrue(usWithExtension.equals( - phoneUtil.parse('(800) 901-3355 ,extensi\u00F3n 7246433', 'US'))); + phoneUtil.parse('(800) 901-3355 ,extensi\u00F3n 7246433', + RegionCode.US))); // Repeat with the small letter o with acute accent created by combining // characters. assertTrue(usWithExtension.equals( - phoneUtil.parse('(800) 901-3355 ,extensio\u0301n 7246433', 'US'))); + phoneUtil.parse('(800) 901-3355 ,extensio\u0301n 7246433', + RegionCode.US))); assertTrue(usWithExtension.equals( - phoneUtil.parse('(800) 901-3355 , 7246433', 'US'))); + phoneUtil.parse('(800) 901-3355 , 7246433', RegionCode.US))); assertTrue(usWithExtension.equals( - phoneUtil.parse('(800) 901-3355 ext: 7246433', 'US'))); + phoneUtil.parse('(800) 901-3355 ext: 7246433', RegionCode.US))); // Test that if a number has two extensions specified, we ignore the second. /** @type {i18n.phonenumbers.PhoneNumber} */ @@ -1884,11 +2082,11 @@ function testParseExtensions() { usWithTwoExtensionsNumber.setNationalNumber(2121231234); usWithTwoExtensionsNumber.setExtension('508'); assertTrue(usWithTwoExtensionsNumber.equals( - phoneUtil.parse('(212)123-1234 x508/x1234', 'US'))); + phoneUtil.parse('(212)123-1234 x508/x1234', RegionCode.US))); assertTrue(usWithTwoExtensionsNumber.equals( - phoneUtil.parse('(212)123-1234 x508/ x1234', 'US'))); + phoneUtil.parse('(212)123-1234 x508/ x1234', RegionCode.US))); assertTrue(usWithTwoExtensionsNumber.equals( - phoneUtil.parse('(212)123-1234 x508\\x1234', 'US'))); + phoneUtil.parse('(212)123-1234 x508\\x1234', RegionCode.US))); // Test parsing numbers in the form (645) 123-1234-910# works, where the last // 3 digits before the # are an extension. @@ -1897,10 +2095,10 @@ function testParseExtensions() { usWithExtension.setNationalNumber(6451231234); usWithExtension.setExtension('910'); assertTrue(usWithExtension.equals( - phoneUtil.parse('+1 (645) 123 1234-910#', 'US'))); + phoneUtil.parse('+1 (645) 123 1234-910#', RegionCode.US))); // Retry with the same number in a slightly different format. assertTrue(usWithExtension.equals( - phoneUtil.parse('+1 (645) 123 1234 ext. 910#', 'US'))); + phoneUtil.parse('+1 (645) 123 1234 ext. 910#', RegionCode.US))); } function testParseAndKeepRaw() { @@ -1911,7 +2109,7 @@ function testParseAndKeepRaw() { alphaNumericNumber.setCountryCodeSource(CCS.FROM_DEFAULT_COUNTRY); alphaNumericNumber.setPreferredDomesticCarrierCode(''); assertTrue(alphaNumericNumber.equals( - phoneUtil.parseAndKeepRawInput('800 six-flags', 'US'))); + phoneUtil.parseAndKeepRawInput('800 six-flags', RegionCode.US))); /** @type {i18n.phonenumbers.PhoneNumber} */ var shorterAlphaNumber = new i18n.phonenumbers.PhoneNumber(); @@ -1921,24 +2119,24 @@ function testParseAndKeepRaw() { shorterAlphaNumber.setCountryCodeSource(CCS.FROM_NUMBER_WITHOUT_PLUS_SIGN); shorterAlphaNumber.setPreferredDomesticCarrierCode(''); assertTrue(shorterAlphaNumber.equals( - phoneUtil.parseAndKeepRawInput('1800 six-flag', 'US'))); + phoneUtil.parseAndKeepRawInput('1800 six-flag', RegionCode.US))); shorterAlphaNumber.setRawInput('+1800 six-flag'); shorterAlphaNumber.setCountryCodeSource(CCS.FROM_NUMBER_WITH_PLUS_SIGN); assertTrue(shorterAlphaNumber.equals( - phoneUtil.parseAndKeepRawInput('+1800 six-flag', 'NZ'))); + phoneUtil.parseAndKeepRawInput('+1800 six-flag', RegionCode.NZ))); alphaNumericNumber.setCountryCode(1); alphaNumericNumber.setNationalNumber(8007493524); alphaNumericNumber.setRawInput('001800 six-flag'); alphaNumericNumber.setCountryCodeSource(CCS.FROM_NUMBER_WITH_IDD); assertTrue(alphaNumericNumber.equals( - phoneUtil.parseAndKeepRawInput('001800 six-flag', 'NZ'))); + phoneUtil.parseAndKeepRawInput('001800 six-flag', RegionCode.NZ))); // Invalid region code supplied. try { - phoneUtil.parseAndKeepRawInput('123 456 7890', 'CS'); - fail('Deprecated country code not allowed: should fail.'); + phoneUtil.parseAndKeepRawInput('123 456 7890', RegionCode.CS); + fail('Deprecated region code not allowed: should fail.'); } catch (e) { // Expected this exception. assertEquals('Wrong error type stored in exception.', @@ -1954,7 +2152,7 @@ function testParseAndKeepRaw() { koreanNumber.setCountryCodeSource(CCS.FROM_DEFAULT_COUNTRY); koreanNumber.setPreferredDomesticCarrierCode('81'); assertTrue(koreanNumber.equals( - phoneUtil.parseAndKeepRawInput('08122123456', 'KR'))); + phoneUtil.parseAndKeepRawInput('08122123456', RegionCode.KR))); } function testCountryWithNoNumberDesc() { @@ -1974,7 +2172,8 @@ function testCountryWithNoNumberDesc() { // Test dialing a US number from within Andorra. assertEquals('00 1 650 253 0000', - phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, 'AD')); + phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, + RegionCode.AD)); } function testUnknownCountryCallingCodeForValidation() { @@ -1987,11 +2186,11 @@ function testUnknownCountryCallingCodeForValidation() { function testIsNumberMatchMatches() { // Test simple matches where formatting is different, or leading zeroes, - // or country code has been specified. + // or country calling code has been specified. /** @type {i18n.phonenumbers.PhoneNumber} */ - var num1 = phoneUtil.parse('+64 3 331 6005', 'NZ'); + var num1 = phoneUtil.parse('+64 3 331 6005', RegionCode.NZ); /** @type {i18n.phonenumbers.PhoneNumber} */ - var num2 = phoneUtil.parse('+64 03 331 6005', 'NZ'); + var num2 = phoneUtil.parse('+64 03 331 6005', RegionCode.NZ); assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH, phoneUtil.isNumberMatch(num1, num2)); assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH, @@ -2054,10 +2253,10 @@ function testIsNumberMatchNonMatches() { // Non-matches. assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH, phoneUtil.isNumberMatch('03 331 6005', '03 331 6006')); - // Different country code, partial number match. + // Different country calling code, partial number match. assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH, phoneUtil.isNumberMatch('+64 3 331-6005', '+16433316005')); - // Different country code, same number. + // Different country calling code, same number. assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH, phoneUtil.isNumberMatch('+64 3 331-6005', '+6133316005')); // Extension different, all else the same. @@ -2088,7 +2287,7 @@ function testIsNumberMatchNsnMatches() { phoneUtil.isNumberMatch('3 331-6005', '03 331 6005')); assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH, phoneUtil.isNumberMatch(NZ_NUMBER, '03 331 6005')); - // Here the second number possibly starts with the country code for + // Here the second number possibly starts with the country calling code for // New Zealand, although we are unsure. /** @type {i18n.phonenumbers.PhoneNumber} */ var unchangedNzNumber = NZ_NUMBER.clone(); @@ -2136,8 +2335,8 @@ function testIsNumberMatchShortNsnMatches() { phoneUtil.isNumberMatch('1 234 345 6789', '345 6789')); assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH, phoneUtil.isNumberMatch('+1 (234) 345 6789', '345 6789')); - // NSN matches, country code omitted for one number, extension missing for - // one. + // NSN matches, country calling code omitted for one number, extension missing + // for one. assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH, phoneUtil.isNumberMatch('+64 3 331-6005', '3 331 6005#1234')); // One has Italian leading zero, one does not. @@ -2174,3 +2373,10 @@ function testCanBeInternationallyDialled() { // We have no data for NZ - should return true. assertTrue(phoneUtil.canBeInternationallyDialled(NZ_NUMBER)); } + +function testIsAlphaNumber() { + assertTrue(phoneUtil.isAlphaNumber('1800 six-flags')); + assertTrue(phoneUtil.isAlphaNumber('1800 six-flags ext. 1234')); + assertFalse(phoneUtil.isAlphaNumber('1800 123-1234')); + assertFalse(phoneUtil.isAlphaNumber('1800 123-1234 extension: 1234')); +}