JS: libphonenumber v3.2. Patch contributed by tronikos.
authorjia.shao.peng <jia.shao.peng@ee073f10-1060-11df-b6a4-87a95322a99c>
Thu, 21 Apr 2011 08:01:27 +0000 (08:01 +0000)
committerjia.shao.peng <jia.shao.peng@ee073f10-1060-11df-b6a4-87a95322a99c>
Thu, 21 Apr 2011 08:01:27 +0000 (08:01 +0000)
git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@172 ee073f10-1060-11df-b6a4-87a95322a99c

java/resources/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java
javascript/README
javascript/i18n/phonenumbers/asyoutypeformatter.js
javascript/i18n/phonenumbers/asyoutypeformatter_test.js
javascript/i18n/phonenumbers/metadata.js
javascript/i18n/phonenumbers/metadatafortesting.js
javascript/i18n/phonenumbers/metadatalite.js
javascript/i18n/phonenumbers/phonemetadata.pb.js
javascript/i18n/phonenumbers/phonenumber.pb.js
javascript/i18n/phonenumbers/phonenumberutil.js
javascript/i18n/phonenumbers/phonenumberutil_test.js

index 5120311..f00ea3a 100644 (file)
@@ -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.<number, Array.<string>>}\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<Integer, List<String>> in JSON format.
-  private static void writeCountryCodeCodeToRegionCodeMap(
+  private static void writeCountryCodeToRegionCodeMap(
       Map<Integer, List<String>> 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();
   }
index e75e583..d8bfdfc 100644 (file)
@@ -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:
index f1e1be2..ae42cef 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/**
  * @license
  * Copyright (C) 2010 Google Inc.
  *
  * @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
+ * <p>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.
+ * <p>See the unittests for more details on how the formatter is to be used.
  *
  * @author Nikolaos Trogkanis
  */
@@ -47,44 +45,14 @@ 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.
    * @const
@@ -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
@@ -195,27 +163,70 @@ 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.<i18n.phonenumbers.NumberFormat>} */
   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 {
@@ -310,8 +320,6 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.createFormattingTemplate_ =
     function(format) {
 
   /** @type {string} */
-  var numberFormat = format.getFormatOrDefault();
-  /** @type {string} */
   var numberPattern = format.getPatternOrDefault();
 
   // The formatter doesn't format numbers when numberPattern contains '|', e.g.
@@ -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.<string>} */
-    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.<string>} */
-  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);
index ee12daf..407abaa 100644 (file)
@@ -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();
index 839e957..4440986 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/**
  * @license
  * Copyright (C) 2010 Google Inc.
  *
 
 /**
  * @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.<number, Array.<string>>}
@@ -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"]
index 11c4bc6..c1cbc82 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/**
  * @license
  * Copyright (C) 2010 Google Inc.
  *
 
 /**
  * @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.<number, Array.<string>>}
@@ -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"]
index 878bc5e..bceb7d7 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/**
  * @license
  * Copyright (C) 2010 Google Inc.
  *
 
 /**
  * @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.<number, Array.<string>>}
@@ -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"]
index 1d67971..3cf881c 100644 (file)
@@ -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
   }
 });
 
index e62168a..cf6f2ab 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/**
  * @license
  * Protocol Buffer 2 Copyright 2008 Google Inc.
  * All other code copyright its respective owners.
index cae75b5..316cb88 100644 (file)
@@ -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.<string, i18n.phonenumbers.PhoneMetadata>}
    */
-  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}
@@ -136,11 +135,22 @@ 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.<string, string>}
  */
 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.<string, string>}
  * @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.<string, string>}
  * @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.<string, string>}
  * @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}
@@ -501,37 +591,49 @@ 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:
  *
+ * <pre>
  * 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;
  * }
+ * </pre>
  *
  * 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:
  *
+ * <pre>
  * 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;
  * }
+ * </pre>
  *
  * 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.<string, string>} 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.
+ * <p>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.
+ * <p>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
+ * <p>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,
@@ -1367,6 +1484,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.
+ *
+ * <p><b>Caveats:</b></p>
+ * <ul>
+ * <li>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.
+ * <li>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.
+ * </ul>
+ *
+ * @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.<i18n.phonenumbers.NumberFormat>} */
+    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.<string>} */
   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
+ * <p>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:
+ * <ol>
+ * <li>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
+ * <li>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.
+ * <li>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.
+ * </ol>
  *
  * @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.<string> } */
-  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.
+ * <p>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:
+ * <ul>
+ * <li>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.
+ * <li>by stripping the '+' sign if present and then looking at the next digits
+ * <li>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.
+ * </ul>
  *
  * 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.<string> } */
-        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.<string> } */
+    /** @type {Array.<string>} */
     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.<string>} */
   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
+ * <p>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.<string>} */
-  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;
   }
index e084313..caa11b1 100644 (file)
@@ -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'));
+}