Browse Source

JS: libphonenumber 4.5

Review URL: http://codereview.appspot.com/5574080
pull/567/head
Nikolaos Trogkanis 14 years ago
committed by Mihaela Rosca
parent
commit
37d0495859
11 changed files with 1893 additions and 413 deletions
  1. +2
    -2
      javascript/README
  2. +9
    -5
      javascript/i18n/phonenumbers/asyoutypeformatter.js
  3. +29
    -0
      javascript/i18n/phonenumbers/asyoutypeformatter_test.js
  4. +499
    -132
      javascript/i18n/phonenumbers/metadata.js
  5. +45
    -8
      javascript/i18n/phonenumbers/metadatafortesting.js
  6. +498
    -131
      javascript/i18n/phonenumbers/metadatalite.js
  7. +57
    -0
      javascript/i18n/phonenumbers/phonemetadata.pb.js
  8. +438
    -100
      javascript/i18n/phonenumbers/phonenumberutil.js
  9. +310
    -35
      javascript/i18n/phonenumbers/phonenumberutil_test.js
  10. +4
    -0
      javascript/i18n/phonenumbers/regioncodefortesting.js
  11. +2
    -0
      tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java

+ 2
- 2
javascript/README View File

@ -25,7 +25,7 @@ pages with your web browser:
How to update:
==============
The JavaScript library is ported from the Java implementation (revision 388).
The JavaScript library is ported from the Java implementation (revision 421).
When the Java project gets updated follow these steps to update the JavaScript
project:
@ -43,7 +43,7 @@ project:
run the following commands to regenerate metadata.js and
metadatafortesting.js:
ant -f java/libphonenumber/build.xml build-js-metadata
ant -f java/build.xml build-js-metadata
3. Manually port any changes of the Java code to the JavaScript code:
PhoneNumberUtil.java => phonenumberutil.js


+ 9
- 5
javascript/i18n/phonenumbers/asyoutypeformatter.js View File

@ -599,7 +599,7 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.
}
return this.ableToFormat_ ?
this.prefixBeforeNationalNumber_.toString() + tempNationalNumber :
tempNationalNumber;
this.accruedInput_.toString();
} else {
return this.attemptToChooseFormattingPattern_();
}
@ -752,8 +752,8 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.
this.getAvailableFormats_(
nationalNumber.substring(0,
i18n.phonenumbers.AsYouTypeFormatter.MIN_LEADING_DIGITS_LENGTH_));
this.maybeCreateNewTemplate_();
return this.inputAccruedNationalNumber_();
return this.maybeCreateNewTemplate_() ?
this.inputAccruedNationalNumber_() : this.accruedInput_.toString();
} else {
return this.prefixBeforeNationalNumber_.toString() + nationalNumber;
}
@ -783,7 +783,7 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.inputAccruedNationalNumber_ =
}
return this.ableToFormat_ ?
this.prefixBeforeNationalNumber_.toString() + tempNationalNumber :
tempNationalNumber;
this.accruedInput_.toString();
} else {
return this.prefixBeforeNationalNumber_.toString();
}
@ -896,7 +896,11 @@ i18n.phonenumbers.AsYouTypeFormatter.prototype.
this.nationalNumber_.append(numberWithoutCountryCallingCode.toString());
/** @type {string} */
var newRegionCode = this.phoneUtil_.getRegionCodeForCountryCode(countryCode);
if (newRegionCode != this.defaultCountry_) {
if (i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ==
newRegionCode) {
this.currentMetaData_ =
this.phoneUtil_.getMetadataForNonGeographicalRegion(countryCode);
} else if (newRegionCode != this.defaultCountry_) {
this.currentMetaData_ = this.getMetadataForRegion_(newRegionCode);
}
/** @type {string} */


+ 29
- 0
javascript/i18n/phonenumbers/asyoutypeformatter_test.js View File

@ -93,6 +93,7 @@ function testTooLongNumberMatchingMultipleLeadingDigits() {
assertEquals('+81 90 1234 5678', f.inputDigit('8'));
assertEquals('+81 90 12 345 6789', f.inputDigit('9'));
assertEquals('+81901234567890', f.inputDigit('0'));
assertEquals('+819012345678901', f.inputDigit('1'));
}
function testAYTFUS() {
@ -699,6 +700,25 @@ function testAYTF_MX() {
assertEquals('+52 1 541 234 5678', f.inputDigit('8'));
}
function testAYTF_International_Toll_Free() {
/** @type {i18n.phonenumbers.AsYouTypeFormatter} */
var f = new i18n.phonenumbers.AsYouTypeFormatter(RegionCode.US);
// +800 1234 5678
assertEquals('+', f.inputDigit('+'));
assertEquals('+8', f.inputDigit('8'));
assertEquals('+80', f.inputDigit('0'));
assertEquals('+800 ', f.inputDigit('0'));
assertEquals('+800 1', f.inputDigit('1'));
assertEquals('+800 12', f.inputDigit('2'));
assertEquals('+800 123', f.inputDigit('3'));
assertEquals('+800 1234', f.inputDigit('4'));
assertEquals('+800 1234 5', f.inputDigit('5'));
assertEquals('+800 1234 56', f.inputDigit('6'));
assertEquals('+800 1234 567', f.inputDigit('7'));
assertEquals('+800 1234 5678', f.inputDigit('8'));
assertEquals('+800123456789', f.inputDigit('9'));
}
function testAYTFMultipleLeadingDigitPatterns() {
// +81 50 2345 6789
/** @type {i18n.phonenumbers.AsYouTypeFormatter} */
@ -732,6 +752,15 @@ function testAYTFMultipleLeadingDigitPatterns() {
assertEquals('+81 222 12 567', f.inputDigit('7'));
assertEquals('+81 222 12 5678', f.inputDigit('8'));
// 011113
f.clear();
assertEquals('0', f.inputDigit('0'));
assertEquals('01', f.inputDigit('1'));
assertEquals('011', f.inputDigit('1'));
assertEquals('011 1', f.inputDigit('1'));
assertEquals('011 11', f.inputDigit('1'));
assertEquals('011113', f.inputDigit('3'));
// +81 3332 2 5678
f.clear();
assertEquals('+', f.inputDigit('+'));


+ 499
- 132
javascript/i18n/phonenumbers/metadata.js
File diff suppressed because it is too large
View File


+ 45
- 8
javascript/i18n/phonenumbers/metadatafortesting.js View File

@ -47,6 +47,7 @@ i18n.phonenumbers.metadata.countryCodeToRegionCodeMap = {
,244:["AO"]
,262:["RE","YT"]
,376:["AD"]
,800:["001"]
};
/**
@ -66,6 +67,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"AO":[,[,,"[29]\\d{8}","\\d{9}"]
,[,,"2\\d(?:[26-9]\\d|\\d[26-9])\\d{5}","\\d{9}",,,"222123456"]
@ -81,6 +83,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"AR":[,[,,"[1-3689]\\d{9,10}","\\d{6,11}"]
,[,,"[1-3]\\d{9}","\\d{6,10}"]
@ -116,6 +119,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"AU":[,[,,"[1-578]\\d{4,14}","\\d{5,15}"]
,[,,"[2378]\\d{8}","\\d{9}"]
@ -134,6 +138,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"BR":[,[]
,[]
@ -147,6 +152,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"19[023]|911","\\d{3}",,,"190"]
,[,,"NA","NA"]
]
,"BS":[,[,,"(242|8(00|66|77|88)|900)\\d{7}","\\d{7,10}"]
,[,,"242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3-57]|9[2-5])|4(?:2[237]|51|64|77)|502|636|702)\\d{4}","\\d{7,10}"]
@ -160,6 +166,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"DE":[,[,,"\\d{4,14}","\\d{2,14}"]
,[,,"(?:[24-6]\\d{2}|3[03-9]\\d|[789](?:[1-9]\\d|0[2-9]))\\d{1,8}","\\d{2,14}",,,"30123456"]
@ -186,6 +193,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"GB":[,[,,"\\d{10}","\\d{6,10}"]
,[,,"[1-6]\\d{9}","\\d{6,10}"]
@ -208,6 +216,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"IT":[,[,,"[0389]\\d{5,10}","\\d{6,11}"]
,[,,"0\\d{9,10}","\\d{10,11}"]
@ -230,11 +239,12 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,1,[,,"NA","NA"]
]
,"JP":[,[]
,[]
,[]
,[,,"NA","NA"]
]
,"JP":[,[,,"07\\d{5}|[1-357-9]\\d{3,10}","\\d{4,11}"]
,[,,"07\\d{5}|[1-357-9]\\d{3,10}","\\d{4,11}"]
,[,,"07\\d{5}|[1-357-9]\\d{3,10}","\\d{4,11}"]
,[,,"0777[01]\\d{2}","\\d{7}",,,"0777012"]
,[,,"NA","NA"]
,[,,"NA","NA"]
,[,,"NA","NA"]
@ -243,19 +253,22 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,"0$1","",0]
,[,"(\\d{2})(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3 $4",["[57-9]0"]
,"0$1","",0]
,[,"(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",["222|333","(?:222|333)1","(?:222|333)11"]
,[,"(\\d{2})(\\d{3})(\\d{4})","$1 $2 $3",["111|222|333","(?:111|222|333)1","(?:111|222|333)11"]
,"0$1","",0]
,[,"(\\d{4})(\\d)(\\d{4})","$1 $2 $3",["222|333","2221|3332","22212|3332","222120|3332"]
,"0$1","",0]
,[,"(\\d{3})(\\d{2})(\\d{4})","$1 $2 $3",["[23]"]
,"0$1","",0]
,[,"(\\d{4})","*$1",["[23]"]
,[,"(\\d{3})(\\d{4})","$1-$2",["077"]
,"0$1","",0]
,[,"(\\d{4})","*$1",["[23]"]
,"$1","",0]
]
,,[,,"NA","NA"]
,,,[,,"NA","NA"]
,,,[,,"[23]\\d{3}","\\d{4}"]
,[,,"NA","NA"]
,1,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
]
,"KR":[,[,,"[1-7]\\d{3,9}|8\\d{8}","\\d{4,10}"]
,[,,"(?:2|[34][1-3]|5[1-5]|6[1-4])(?:1\\d{2,3}|[2-9]\\d{6,7})","\\d{4,10}",,,"22123456"]
@ -294,6 +307,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"MX":[,[,,"[1-9]\\d{9,10}","\\d{7,11}"]
,[,,"[2-9]\\d{9}","\\d{7,10}"]
@ -329,6 +343,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"NZ":[,[,,"[289]\\d{7,9}|[3-7]\\d{7}","\\d{7,10}"]
,[,,"24099\\d{3}|(?:3[2-79]|[479][2-689]|6[235-9])\\d{6}","\\d{7,8}"]
@ -349,6 +364,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"PL":[,[,,"[1-9]\\d{8}","\\d{9}"]
,[,,"[1-9]\\d{8}","\\d{9}"]
@ -364,6 +380,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"RE":[,[,,"[268]\\d{8}","\\d{9}"]
,[,,"262\\d{6}","\\d{9}",,,"262161234"]
@ -379,6 +396,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,"262|6(?:9[23]|47)|8",[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"SG":[,[,,"[13689]\\d{7,10}","\\d{8}|\\d{10,11}"]
,[,,"[36]\\d{7}","\\d{8}"]
@ -399,6 +417,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"US":[,[,,"[13-689]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890"]
,[,,"[13-689]\\d{9}|2[0-35-9]\\d{8}","\\d{7}(?:\\d{3})?",,,"1234567890"]
@ -417,6 +436,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,1,,[,,"800\\d{7}","\\d{10}",,,"1234567890"]
,[,,"NA","NA"]
,,[,,"119|911","\\d{3}",,,"911"]
,[,,"NA","NA"]
]
,"YT":[,[,,"[268]\\d{8}","\\d{9}"]
,[,,"2696[0-4]\\d{4}","\\d{9}",,,"269601234"]
@ -430,5 +450,22 @@ i18n.phonenumbers.metadata.countryToMetadata = {
,,"269|639",[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
,"001":[,[,,"\\d{8}","\\d{8}",,,"12345678"]
,[,,"NA","NA",,,"12345678"]
,[,,"NA","NA",,,"12345678"]
,[,,"\\d{8}","\\d{8}",,,"12345678"]
,[,,"NA","NA"]
,[,,"NA","NA"]
,[,,"NA","NA"]
,[,,"NA","NA"]
,"001",800,"",,,,,,,1,[[,"(\\d{4})(\\d{4})","$1 $2",,"","",0]
]
,,[,,"NA","NA"]
,,,[,,"NA","NA"]
,[,,"NA","NA"]
,,[,,"NA","NA"]
,[,,"NA","NA"]
]
};

+ 498
- 131
javascript/i18n/phonenumbers/metadatalite.js
File diff suppressed because it is too large
View File


+ 57
- 0
javascript/i18n/phonenumbers/phonemetadata.pb.js View File

@ -1121,6 +1121,57 @@ i18n.phonenumbers.PhoneMetadata.prototype.clearEmergency = function() {
};
/**
* Gets the value of the voicemail field.
* @return {i18n.phonenumbers.PhoneNumberDesc} The value.
*/
i18n.phonenumbers.PhoneMetadata.prototype.getVoicemail = function() {
return /** @type {i18n.phonenumbers.PhoneNumberDesc} */ (this.get$Value(28));
};
/**
* Gets the value of the voicemail field or the default value if not set.
* @return {!i18n.phonenumbers.PhoneNumberDesc} The value.
*/
i18n.phonenumbers.PhoneMetadata.prototype.getVoicemailOrDefault = function() {
return /** @type {!i18n.phonenumbers.PhoneNumberDesc} */ (this.get$ValueOrDefault(28));
};
/**
* Sets the value of the voicemail field.
* @param {!i18n.phonenumbers.PhoneNumberDesc} value The value.
*/
i18n.phonenumbers.PhoneMetadata.prototype.setVoicemail = function(value) {
this.set$Value(28, value);
};
/**
* @return {boolean} Whether the voicemail field has a value.
*/
i18n.phonenumbers.PhoneMetadata.prototype.hasVoicemail = function() {
return this.has$Value(28);
};
/**
* @return {number} The number of values in the voicemail field.
*/
i18n.phonenumbers.PhoneMetadata.prototype.voicemailCount = function() {
return this.count$Values(28);
};
/**
* Clears the values in the voicemail field.
*/
i18n.phonenumbers.PhoneMetadata.prototype.clearVoicemail = function() {
this.clear$Field(28);
};
/**
* Gets the value of the no_international_dialling field.
* @return {i18n.phonenumbers.PhoneNumberDesc} The value.
@ -2125,6 +2176,12 @@ goog.proto2.Message.set$Metadata(i18n.phonenumbers.PhoneMetadata, {
fieldType: goog.proto2.Message.FieldType.MESSAGE,
type: i18n.phonenumbers.PhoneNumberDesc
},
28: {
name: 'voicemail',
required: true,
fieldType: goog.proto2.Message.FieldType.MESSAGE,
type: i18n.phonenumbers.PhoneNumberDesc
},
24: {
name: 'no_international_dialling',
required: true,


+ 438
- 100
javascript/i18n/phonenumbers/phonenumberutil.js View File

@ -217,6 +217,31 @@ i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = {
};
/**
* A map that contains characters that are essential when dialling. That means
* any of the characters in this map must not be removed from a number when
* dialing, otherwise the call will not reach the intended destination.
*
* @const
* @type {!Object.<string, string>}
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_ = {
'0': '0',
'1': '1',
'2': '2',
'3': '3',
'4': '4',
'5': '5',
'6': '6',
'7': '7',
'8': '8',
'9': '9',
'+': '+',
'*': '*'
};
/**
* Only upper-case variants of alpha characters are stored.
*
@ -653,7 +678,7 @@ i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ =
i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '|' +
'[ \u00A0\\t,]*' +
'(?:ext(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45\uFF58\uFF54\uFF4E?|' +
'(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|' +
'[,x\uFF58#\uFF03~\uFF5E]|int|anexo|\uFF49\uFF4E\uFF54)' +
'[:\\.\uFF0E]?[ \u00A0\\t,-]*' +
i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '#?|' +
@ -733,6 +758,13 @@ i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/;
i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/;
/**
* @const
* @type {string}
*/
i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY = '001';
/**
* INTERNATIONAL and NATIONAL formats are consistent with the definition in
* ITU-T Recommendation E. 123. For example, the number of the Google
@ -784,9 +816,11 @@ i18n.phonenumbers.PhoneNumberType = {
// further routed to specific offices, but allow one number to be used for a
// company.
UAN: 9,
// Used for 'Voice Mail Access Numbers'.
VOICEMAIL: 10,
// A phone number is of type UNKNOWN when it does not fit any of the known
// patterns for a specific region.
UNKNOWN: 10
UNKNOWN: -1
};
@ -996,7 +1030,8 @@ i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
* <li> subscriber numbers may not be diallable from all devices (notably
* mobile devices, which typically requires the full national_number to be
* dialled in most regions).
* <li> most non-geographical numbers have no area codes.
* <li> most non-geographical numbers have no area codes, including numbers
* from non-geographical entities.
* <li> some geographical numbers have no area codes.
* </ul>
*
@ -1172,10 +1207,27 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidRegionCode_ =
function(regionCode) {
return regionCode != null &&
regionCode !=
i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY &&
regionCode.toUpperCase() in i18n.phonenumbers.metadata.countryToMetadata;
};
/**
* Helper function to check the country calling code is valid.
*
* @param {number} countryCallingCode the country calling code.
* @return {boolean} true if country calling code code is valid.
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.hasValidCountryCallingCode_ =
function(countryCallingCode) {
return countryCallingCode in
i18n.phonenumbers.metadata.countryCodeToRegionCodeMap;
};
/**
* Formats a phone number in the specified format using default rules. Note that
* this does not promise to produce a phone number that the user can dial from
@ -1220,17 +1272,20 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.format =
// contained in the metadata for US.
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
if (!this.isValidRegionCode_(regionCode)) {
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
return nationalSignificantNumber;
}
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata =
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
/** @type {string} */
var formattedExtension =
this.maybeGetFormattedExtension_(number, regionCode, numberFormat);
this.maybeGetFormattedExtension_(number, metadata, numberFormat);
/** @type {string} */
var formattedNationalNumber =
this.formatNationalNumber_(nationalSignificantNumber,
regionCode,
metadata,
numberFormat);
return this.formatNumberByFormat_(countryCallingCode,
numberFormat,
@ -1268,11 +1323,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
// contained in the metadata for US.
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
if (!this.isValidRegionCode_(regionCode)) {
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
return nationalSignificantNumber;
}
/** @type {Array.<i18n.phonenumbers.NumberFormat>} */
var userDefinedFormatsCopy = [];
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata =
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
/** @type {number} */
var size = userDefinedFormats.length;
for (var i = 0; i < size; ++i) {
@ -1289,8 +1347,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
/** type {i18n.phonenumbers.NumberFormat} */
var numFormatCopy = numFormat.clone();
/** @type {string} */
var nationalPrefix =
this.getMetadataForRegion(regionCode).getNationalPrefixOrDefault();
var nationalPrefix = metadata.getNationalPrefixOrDefault();
if (nationalPrefix.length > 0) {
// Replace $NP with national prefix and $FG with the first group ($1).
nationalPrefixFormattingRule = nationalPrefixFormattingRule
@ -1314,7 +1371,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
/** @type {string} */
var formattedExtension =
this.maybeGetFormattedExtension_(number, regionCode, numberFormat);
this.maybeGetFormattedExtension_(number, metadata, numberFormat);
/** @type {string} */
var formattedNationalNumber =
this.formatAccordingToFormats_(nationalSignificantNumber,
@ -1353,17 +1410,20 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
// contained in the metadata for US.
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
if (!this.isValidRegionCode_(regionCode)) {
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
return nationalSignificantNumber;
}
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata =
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
/** @type {string} */
var formattedExtension = this.maybeGetFormattedExtension_(
number, regionCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
number, metadata, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
/** @type {string} */
var formattedNationalNumber =
this.formatNationalNumber_(nationalSignificantNumber,
regionCode,
metadata,
i18n.phonenumbers.PhoneNumberFormat.NATIONAL,
carrierCode);
return this.formatNumberByFormat_(
@ -1372,6 +1432,21 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
};
/**
* @param {number} countryCallingCode
* @param {?string} regionCode
* @return {i18n.phonenumbers.PhoneMetadata}
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegionOrCallingCode_ =
function(countryCallingCode, regionCode) {
return i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ==
regionCode ?
this.getMetadataForNonGeographicalRegion(countryCallingCode) :
this.getMetadataForRegion(regionCode);
};
/**
* Formats a phone number in national format for dialing using the carrier as
* specified in the preferred_domestic_carrier_code field of the PhoneNumber
@ -1419,9 +1494,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing =
function(number, regionCallingFrom, withFormatting) {
/** @type {?string} */
var regionCode = this.getRegionCodeForNumber(number);
if (!this.isValidRegionCode_(regionCode)) {
/** @type {number} */
var countryCallingCode = number.getCountryCodeOrDefault();
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
return number.hasRawInput() ? number.getRawInputOrDefault() : '';
}
@ -1434,13 +1509,25 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing =
numberNoExt.clearExtension();
/** @type {i18n.phonenumbers.PhoneNumberType} */
var numberType = this.getNumberType(numberNoExt);
if ((regionCode == 'CO') && (regionCallingFrom == 'CO') &&
(numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE)) {
formattedNumber = this.formatNationalNumberWithCarrierCode(
numberNoExt,
i18n.phonenumbers.PhoneNumberUtil
.COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_);
} else if ((regionCode == 'BR') && (regionCallingFrom == 'BR') &&
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
if (regionCode == 'CO' && regionCallingFrom == 'CO') {
if (numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) {
formattedNumber = this.formatNationalNumberWithCarrierCode(
numberNoExt,
i18n.phonenumbers.PhoneNumberUtil
.COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_);
} else {
// E164 doesn't work at all when dialing within Colombia.
formattedNumber = this.format(
numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
}
} else if (regionCode == 'PE' && regionCallingFrom == 'PE') {
// In Peru, numbers cannot be dialled using E164 format from a mobile phone
// for Movistar. Instead they must be dialled in national format.
formattedNumber = this.format(
numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
} else if (regionCode == 'BR' && regionCallingFrom == 'BR' &&
((numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) ||
(numberType == i18n.phonenumbers.PhoneNumberType.MOBILE) ||
(numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE))) {
@ -1463,7 +1550,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing =
}
return withFormatting ?
formattedNumber :
i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(formattedNumber);
i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_, true);
};
@ -1498,10 +1586,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
/** @type {number} */
var countryCallingCode = number.getCountryCodeOrDefault();
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
/** @type {string} */
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
if (!this.isValidRegionCode_(regionCode)) {
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
return nationalSignificantNumber;
}
if (countryCallingCode ==
@ -1525,17 +1611,12 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
return this.format(number,
i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
}
/** @type {string} */
var formattedNationalNumber =
this.formatNationalNumber_(nationalSignificantNumber, regionCode,
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegion(regionCallingFrom);
var metadataForRegionCallingFrom =
this.getMetadataForRegion(regionCallingFrom);
/** @type {string} */
var internationalPrefix = metadata.getInternationalPrefixOrDefault();
/** @type {string} */
var formattedExtension = this.maybeGetFormattedExtension_(
number, regionCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
var internationalPrefix =
metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
// For regions that have multiple international prefixes, the international
// format of the number is returned, unless there is a preferred international
@ -1546,11 +1627,23 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
internationalPrefix)) {
internationalPrefixForFormatting = internationalPrefix;
} else if (metadata.hasPreferredInternationalPrefix()) {
} else if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) {
internationalPrefixForFormatting =
metadata.getPreferredInternationalPrefixOrDefault();
metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
}
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadataForRegion =
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
/** @type {string} */
var formattedNationalNumber =
this.formatNationalNumber_(nationalSignificantNumber, metadataForRegion,
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
/** @type {string} */
var formattedExtension = this.maybeGetFormattedExtension_(number,
metadataForRegion, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
return internationalPrefixForFormatting.length > 0 ?
internationalPrefixForFormatting + ' ' + countryCallingCode + ' ' +
formattedNationalNumber + formattedExtension :
@ -1565,9 +1658,12 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
* is parsed from. The original format is embedded in the country_code_source
* field of the PhoneNumber object passed in. If such information is missing,
* the number will be formatted into the NATIONAL format by default. When the
* number is an invalid number, the method returns the raw input when it is
* available.
* number contains a leading zero and this is unexpected for this country, or we
* don't have a formatting pattern for the number, the method returns the raw
* input when it is available.
*
* Note this method guarantees no digit will be inserted, removed or modified as
* a result of formatting.
* @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
* be formatted in its original number format.
* @param {string} regionCallingFrom the region whose IDD needs to be prefixed
@ -1577,27 +1673,187 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
function(number, regionCallingFrom) {
if (number.hasRawInput() && !this.isValidNumber(number)) {
if (number.hasRawInput() &&
(this.hasUnexpectedItalianLeadingZero_(number) ||
!this.hasFormattingPatternForNumber_(number))) {
// We check if we have the formatting pattern because without that, we might
// format the number as a group without national prefix.
return number.getRawInputOrDefault();
}
if (!number.hasCountryCodeSource()) {
return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
}
/** @type {string} */
var formattedNumber;
switch (number.getCountryCodeSource()) {
case i18n.phonenumbers.PhoneNumber.CountryCodeSource
.FROM_NUMBER_WITH_PLUS_SIGN:
return this.format(number,
formattedNumber = this.format(number,
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
break;
case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD:
return this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
formattedNumber =
this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
break;
case i18n.phonenumbers.PhoneNumber.CountryCodeSource
.FROM_NUMBER_WITHOUT_PLUS_SIGN:
return this.format(number,
formattedNumber = this.format(number,
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL).substring(1);
break;
case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY:
// Fall-through to default case.
default:
return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
/** @type {string} */
var regionCode =
this.getRegionCodeForCountryCode(number.getCountryCodeOrDefault());
// We strip non-digits from the NDD here, and from the raw input later,
// so that we can compare them easily.
/** @type {?string} */
var nationalPrefix = this.getNddPrefixForRegion(regionCode, true);
/** @type {string} */
var nationalFormat =
this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
if (nationalPrefix == null || nationalPrefix.length == 0) {
// If the region doesn't have a national prefix at all, we can safely
// return the national format without worrying about a national prefix
// being added.
formattedNumber = nationalFormat;
break;
}
// Otherwise, we check if the original number was entered with a national
// prefix.
if (this.rawInputContainsNationalPrefix_(
number.getRawInputOrDefault(), nationalPrefix, regionCode)) {
// If so, we can safely return the national format.
formattedNumber = nationalFormat;
break;
}
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegion(regionCode);
/** @type {string} */
var nationalNumber = this.getNationalSignificantNumber(number);
/** @type {i18n.phonenumbers.NumberFormat} */
var formatRule = this.chooseFormattingPatternForNumber_(
metadata.numberFormatArray(), nationalNumber);
// When the format we apply to this number doesn't contain national
// prefix, we can just return the national format.
// TODO: Refactor the code below with the code in
// isNationalPrefixPresentIfRequired.
/** @type {string} */
var candidateNationalPrefixRule =
formatRule.getNationalPrefixFormattingRuleOrDefault();
// We assume that the first-group symbol will never be _before_ the
// national prefix.
/** @type {number} */
var indexOfFirstGroup = candidateNationalPrefixRule.indexOf('$1');
if (indexOfFirstGroup <= 0) {
formattedNumber = nationalFormat;
break;
}
candidateNationalPrefixRule =
candidateNationalPrefixRule.substring(0, indexOfFirstGroup);
candidateNationalPrefixRule = i18n.phonenumbers.PhoneNumberUtil
.normalizeDigitsOnly(candidateNationalPrefixRule);
if (candidateNationalPrefixRule.length == 0) {
// National prefix not used when formatting this number.
formattedNumber = nationalFormat;
break;
}
// Otherwise, we need to remove the national prefix from our output.
/** @type {i18n.phonenumbers.NumberFormat} */
var numFormatCopy = formatRule.clone();
numFormatCopy.clearNationalPrefixFormattingRule();
formattedNumber = this.formatByPattern(number,
i18n.phonenumbers.PhoneNumberFormat.NATIONAL, [numFormatCopy]);
break;
}
/** @type {string} */
var rawInput = number.getRawInputOrDefault();
// If no digit is inserted/removed/modified as a result of our formatting, we
// return the formatted phone number; otherwise we return the raw input the
// user entered.
return (formattedNumber != null &&
i18n.phonenumbers.PhoneNumberUtil
.normalizeDigitsOnly(formattedNumber) ==
i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(rawInput)) ?
formattedNumber :
rawInput;
};
/**
* Check if rawInput, which is assumed to be in the national format, has a
* national prefix. The national prefix is assumed to be in digits-only form.
* @param {string} rawInput
* @param {string} nationalPrefix
* @param {string} regionCode
* @return {boolean}
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.rawInputContainsNationalPrefix_ =
function(rawInput, nationalPrefix, regionCode) {
/** @type {string} */
var normalizedNationalNumber =
i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(rawInput);
if (goog.string.startsWith(normalizedNationalNumber, nationalPrefix)) {
try {
// Some Japanese numbers (e.g. 00777123) might be mistaken to contain the
// national prefix when written without it (e.g. 0777123) if we just do
// prefix matching. To tackle that, we check the validity of the number if
// the assumed national prefix is removed (777123 won't be valid in
// Japan).
return this.isValidNumber(
this.parse(normalizedNationalNumber.substring(nationalPrefix.length),
regionCode));
} catch (e) {
return false;
}
}
return false;
};
/**
* Returns true if a number is from a region whose national significant number
* couldn't contain a leading zero, but has the italian_leading_zero field set
* to true.
* @param {i18n.phonenumbers.PhoneNumber} number
* @return {boolean}
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.hasUnexpectedItalianLeadingZero_ =
function(number) {
return number.hasItalianLeadingZero() &&
!this.isLeadingZeroPossible(number.getCountryCodeOrDefault());
};
/**
* @param {i18n.phonenumbers.PhoneNumber} number
* @return {boolean}
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.hasFormattingPatternForNumber_ =
function(number) {
/** @type {number} */
var countryCallingCode = number.getCountryCodeOrDefault();
/** @type {string} */
var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCallingCode);
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegionOrCallingCode_(
countryCallingCode, phoneNumberRegion);
if (metadata == null) {
return false;
}
/** @type {string} */
var nationalNumber = this.getNationalSignificantNumber(number);
/** @type {i18n.phonenumbers.NumberFormat} */
var formatRule = this.chooseFormattingPatternForNumber_(
metadata.numberFormatArray(), nationalNumber);
return formatRule != null;
};
@ -1638,9 +1894,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
}
/** @type {number} */
var countryCode = number.getCountryCodeOrDefault();
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCode);
if (!this.isValidRegionCode_(regionCode)) {
if (!this.hasValidCountryCallingCode_(countryCode)) {
return rawInput;
}
// Strip any prefix such as country calling code, IDD, that was present. We do
@ -1666,7 +1920,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
}
}
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegion(regionCallingFrom);
var metadataForRegionCallingFrom =
this.getMetadataForRegion(regionCallingFrom);
if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
if (this.isNANPACountry(regionCallingFrom)) {
return countryCode + ' ' + rawInput;
@ -1676,9 +1931,11 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
// to match against.
/** @type {Array.<i18n.phonenumbers.NumberFormat>} */
var availableFormats = [];
for (var i = 0; i < metadata.numberFormatArray().length; ++i) {
for (var i = 0; i < metadataForRegionCallingFrom.numberFormatArray().length;
++i) {
/** @type {i18n.phonenumbers.NumberFormat} */
var newFormat = metadata.numberFormatArray()[i].clone();
var newFormat =
metadataForRegionCallingFrom.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
@ -1697,25 +1954,41 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
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.
var internationalPrefixForFormatting = '';
// If an unsupported region-calling-from is entered, or a country with
// multiple international prefixes, the international format of the number is
// returned, unless there is a preferred international prefix.
if (metadataForRegionCallingFrom != null) {
/** @type {string} */
var internationalPrefix =
metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
internationalPrefixForFormatting =
i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
internationalPrefix) ?
internationalPrefix :
metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
}
/** @type {string} */
var internationalPrefixForFormatting =
i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
internationalPrefix) ?
internationalPrefix : metadata.getPreferredInternationalPrefixOrDefault();
var regionCode = this.getRegionCodeForCountryCode(countryCode);
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadataForRegion =
this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
/** @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);
number, metadataForRegion,
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
if (internationalPrefixForFormatting.length > 0) {
return internationalPrefixForFormatting + ' ' + countryCode + ' ' +
rawInput + formattedExtension;
} else {
// Invalid region entered as country-calling-from (so no metadata was found
// for it) or the region chosen has multiple international dialling
// prefixes.
return this.formatNumberByFormat_(
countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
rawInput, formattedExtension);
}
};
@ -1782,7 +2055,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberByFormat_ =
* 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 region code.
* @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
* region that we think this number is from.
* @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
* phone number should be formatted into.
* @param {string=} opt_carrierCode
@ -1790,10 +2064,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberByFormat_ =
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.formatNationalNumber_ =
function(number, regionCode, numberFormat, opt_carrierCode) {
function(number, metadata, numberFormat, opt_carrierCode) {
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegion(regionCode);
/** @type {Array.<i18n.phonenumbers.NumberFormat>} */
var intlNumberFormats = metadata.intlNumberFormatArray();
// When the intlNumberFormats exists, we use that to format national number
@ -1919,7 +2191,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatAccordingToFormats_ =
* @param {string} regionCode the region for which an example number is needed.
* @return {i18n.phonenumbers.PhoneNumber} a valid fixed-line number for the
* specified region. Returns null when the metadata does not contain such
* information.
* information, or the region 001 is passed in. For 001 (representing non-
* geographical numbers), call {@link #getExampleNumberForNonGeoEntity}
* instead.
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber =
function(regionCode) {
@ -1937,7 +2211,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber =
* needed.
* @return {i18n.phonenumbers.PhoneNumber} a valid number for the specified
* region and type. Returns null when the metadata does not contain such
* information or if an invalid region was entered.
* information or if an invalid region or region 001 was entered.
* For 001 (representing non-geographical numbers), call
* {@link #getExampleNumberForNonGeoEntity} instead.
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType =
function(regionCode, type) {
@ -1959,20 +2235,52 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType =
};
/**
* Gets a valid number for the specified country calling code for a
* non-geographical entity.
*
* @param {number} countryCallingCode the country calling code for a
* non-geographical entity.
* @return {i18n.phonenumbers.PhoneNumber} a valid number for the
* non-geographical entity. Returns null when the metadata does not contain
* such information, or the country calling code passed in does not belong
* to a non-geographical entity.
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForNonGeoEntity =
function(countryCallingCode) {
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata =
this.getMetadataForNonGeographicalRegion(countryCallingCode);
if (metadata != null) {
/** @type {i18n.phonenumbers.PhoneNumberDesc} */
var desc = metadata.getGeneralDesc();
try {
if (desc.hasExampleNumber()) {
return this.parse('+' + countryCallingCode + desc.getExampleNumber(),
'ZZ');
}
} catch (e) {
}
}
return null;
};
/**
* Gets the formatted extension of a phone number, if the phone number had an
* extension specified. If not, it returns an empty string.
*
* @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that might have
* an extension.
* @param {string} regionCode the ISO 3166-1 two-letter region code.
* @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
* region that we think this number is from.
* @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, numberFormat) {
function(number, metadata, numberFormat) {
if (!number.hasExtension() || number.getExtension().length == 0) {
return '';
@ -1981,7 +2289,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ =
return i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
number.getExtension();
}
return this.formatExtension_(number.getExtensionOrDefault(), regionCode);
return this.formatExtension_(number.getExtensionOrDefault(), metadata);
}
};
@ -1992,15 +2300,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ =
* 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 region code.
* @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
* region that we think this number is from.
* @return {string} the formatted extension.
* @private
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.formatExtension_ =
function(extensionDigits, regionCode) {
function(extensionDigits, metadata) {
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegion(regionCode);
if (metadata.hasPreferredExtnPrefix()) {
return metadata.getPreferredExtnPrefix() + extensionDigits;
} else {
@ -2039,6 +2346,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberDescByType_ =
return metadata.getPager();
case i18n.phonenumbers.PhoneNumberType.UAN:
return metadata.getUan();
case i18n.phonenumbers.PhoneNumberType.VOICEMAIL:
return metadata.getVoicemail();
default:
return metadata.getGeneralDesc();
}
@ -2057,13 +2366,17 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType =
/** @type {?string} */
var regionCode = this.getRegionCodeForNumber(number);
if (!this.isValidRegionCode_(regionCode)) {
if (!this.isValidRegionCode_(regionCode) &&
i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY !=
regionCode) {
return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
}
/** @type {string} */
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
return this.getNumberTypeHelper_(nationalSignificantNumber,
this.getMetadataForRegion(regionCode));
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegionOrCallingCode_(
number.getCountryCodeOrDefault(), regionCode);
return this.getNumberTypeHelper_(nationalSignificantNumber, metadata);
};
@ -2105,6 +2418,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberTypeHelper_ =
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getUan())) {
return i18n.phonenumbers.PhoneNumberType.UAN;
}
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoicemail())) {
return i18n.phonenumbers.PhoneNumberType.VOICEMAIL;
}
/** @type {boolean} */
var isFixedLine = this.isNumberMatchingDesc_(nationalNumber, metadata
@ -2159,6 +2475,18 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion =
};
/**
* @param {number} countryCallingCode
* @return {i18n.phonenumbers.PhoneMetadata}
*/
i18n.phonenumbers.PhoneNumberUtil.prototype.
getMetadataForNonGeographicalRegion = function(countryCallingCode) {
return this.getMetadataForRegion(
this.getRegionCodeForCountryCode(countryCallingCode));
};
/**
* @param {string} nationalNumber
* @param {i18n.phonenumbers.PhoneNumberDesc} numberDesc
@ -2188,8 +2516,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ =
i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
/** @type {?string} */
var regionCode = this.getRegionCodeForNumber(number);
return this.isValidRegionCode_(regionCode) &&
this.isValidNumberForRegion(number, /** @type {string} */ (regionCode));
return this.isValidNumberForRegion(number, regionCode);
};
@ -2204,7 +2531,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
*
* @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
* to validate.
* @param {string} regionCode the region that we want to validate the phone
* @param {?string} regionCode 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.
@ -2212,12 +2539,17 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion =
function(number, regionCode) {
if (number.getCountryCodeOrDefault() !=
this.getCountryCodeForRegion(regionCode)) {
/** @type {number} */
var countryCode = number.getCountryCodeOrDefault();
if (countryCode == 0 ||
(i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY !=
regionCode &&
countryCode != this.getCountryCodeForRegion(regionCode))) {
return false;
}
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegion(regionCode);
var metadata =
this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
/** @type {i18n.phonenumbers.PhoneNumberDesc} */
var generalNumDesc = metadata.getGeneralDesc();
/** @type {string} */
@ -2525,14 +2857,17 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason =
// work if the number is possible but not valid. This would need to be
// revisited if the possible number pattern ever differed between various
// regions within those plans.
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCode);
if (!this.isValidRegionCode_(regionCode)) {
if (!this.hasValidCountryCallingCode_(countryCode)) {
return i18n.phonenumbers.PhoneNumberUtil.ValidationResult
.INVALID_COUNTRY_CODE;
}
/** @type {string} */
var regionCode = this.getRegionCodeForCountryCode(countryCode);
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata =
this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
/** @type {i18n.phonenumbers.PhoneNumberDesc} */
var generalNumDesc = this.getMetadataForRegion(regionCode).getGeneralDesc();
var generalNumDesc = metadata.getGeneralDesc();
// Handling case of numbers with no metadata.
if (!generalNumDesc.hasNationalNumberPattern()) {
/** @type {number} */
@ -3164,7 +3499,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ =
/** @type {string} */
var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode);
if (phoneNumberRegion != defaultRegion) {
regionMetadata = this.getMetadataForRegion(phoneNumberRegion);
regionMetadata = this.getMetadataForRegionOrCallingCode_(
countryCode, phoneNumberRegion);
}
} else {
// If no extracted country calling code, use the region supplied instead.
@ -3388,14 +3724,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ =
/**
* 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.
* Returns true if the number can be dialled from outside the region, or
* unknown. If the number can only be dialled from within the region, 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 region.
* want to know whether it is diallable from outside the region.
* @return {boolean} true if the number can only be dialled from within the
* country.
*/
@ -3403,13 +3739,15 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled =
function(number) {
/** @type {?string} */
var regionCode = this.getRegionCodeForNumber(number);
/** @type {string} */
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
if (!this.isValidRegionCode_(regionCode)) {
// Note numbers belonging to non-geographical entities (e.g. +800 numbers)
// are always internationally diallable, and will be caught here.
return true;
}
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = this.getMetadataForRegion(regionCode);
/** @type {string} */
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
return !this.isNumberMatchingDesc_(nationalSignificantNumber,
metadata.getNoInternationalDialling());
};


+ 310
- 35
javascript/i18n/phonenumbers/phonenumberutil_test.js View File

@ -109,6 +109,12 @@ IT_NUMBER.setNationalNumber(236618300);
IT_NUMBER.setItalianLeadingZero(true);
/** @type {i18n.phonenumbers.PhoneNumber} */
var JP_STAR_NUMBER = new i18n.phonenumbers.PhoneNumber();
JP_STAR_NUMBER.setCountryCode(81);
JP_STAR_NUMBER.setNationalNumber(2345);
// Numbers to test the formatting rules from Mexico.
/** @type {i18n.phonenumbers.PhoneNumber} */
var MX_MOBILE1 = new i18n.phonenumbers.PhoneNumber();
@ -196,6 +202,18 @@ US_SPOOF_WITH_RAW_INPUT.setCountryCode(1);
US_SPOOF_WITH_RAW_INPUT.setNationalNumber(0);
US_SPOOF_WITH_RAW_INPUT.setRawInput('000-000-0000');
/** @type {i18n.phonenumbers.PhoneNumber} */
var INTERNATIONAL_TOLL_FREE = new i18n.phonenumbers.PhoneNumber();
INTERNATIONAL_TOLL_FREE.setCountryCode(800);
INTERNATIONAL_TOLL_FREE.setNationalNumber(12345678);
/** @type {i18n.phonenumbers.PhoneNumber} */
var INTERNATIONAL_TOLL_FREE_TOO_LONG = new i18n.phonenumbers.PhoneNumber();
INTERNATIONAL_TOLL_FREE_TOO_LONG.setCountryCode(800);
INTERNATIONAL_TOLL_FREE_TOO_LONG.setNationalNumber(1234567890);
var RegionCode = i18n.phonenumbers.RegionCode;
function testGetInstanceLoadUSMetadata() {
@ -262,13 +280,26 @@ function testGetInstanceLoadARMetadata() {
assertEquals('$1 $2 $3 $4', metadata.getIntlNumberFormat(3).getFormat());
}
function testGetInstanceLoadInternationalTollFreeMetadata() {
/** @type {i18n.phonenumbers.PhoneMetadata} */
var metadata = phoneUtil.getMetadataForNonGeographicalRegion(800);
assertEquals('001', metadata.getId());
assertEquals(800, metadata.getCountryCode());
assertEquals('$1 $2', metadata.getNumberFormat(0).getFormat());
assertEquals('(\\d{4})(\\d{4})', metadata.getNumberFormat(0).getPattern());
assertEquals('12345678', metadata.getGeneralDesc().getExampleNumber());
assertEquals('12345678', metadata.getTollFree().getExampleNumber());
}
function testIsLeadingZeroPossible() {
// Italy
assertTrue(phoneUtil.isLeadingZeroPossible(39));
// USA
assertFalse(phoneUtil.isLeadingZeroPossible(1));
// Not in metadata file, just default to false.
// International toll free numbers
assertFalse(phoneUtil.isLeadingZeroPossible(800));
// Not in metadata file, just default to false.
assertFalse(phoneUtil.isLeadingZeroPossible(888));
}
function testGetLengthOfGeographicalAreaCode() {
@ -296,6 +327,10 @@ function testGetLengthOfGeographicalAreaCode() {
// An invalid US number (1 digit shorter), which has no area code.
assertEquals(0,
phoneUtil.getLengthOfGeographicalAreaCode(US_SHORT_BY_ONE_NUMBER));
// An international toll free number, which has no area code.
assertEquals(0,
phoneUtil.getLengthOfGeographicalAreaCode(INTERNATIONAL_TOLL_FREE));
}
function testGetLengthOfNationalDestinationCode() {
@ -334,6 +369,10 @@ function testGetLengthOfNationalDestinationCode() {
number.setCountryCode(123);
number.setNationalNumber(6502530000);
assertEquals(0, phoneUtil.getLengthOfNationalDestinationCode(number));
// An international toll free number, which has NDC '1234'.
assertEquals(4,
phoneUtil.getLengthOfNationalDestinationCode(INTERNATIONAL_TOLL_FREE));
}
function testGetNationalSignificantNumber() {
@ -347,6 +386,9 @@ function testGetNationalSignificantNumber() {
// An Italian fixed line number.
assertEquals('0236618300',
phoneUtil.getNationalSignificantNumber(IT_NUMBER));
assertEquals('12345678',
phoneUtil.getNationalSignificantNumber(INTERNATIONAL_TOLL_FREE));
}
function testGetExampleNumber() {
@ -364,6 +406,14 @@ function testGetExampleNumber() {
assertNotNull(phoneUtil.getExampleNumberForType(RegionCode.US, PNT.MOBILE));
// CS is an invalid region, so we have no data for it.
assertNull(phoneUtil.getExampleNumberForType(RegionCode.CS, PNT.MOBILE));
// RegionCode 001 is reserved for supporting non-geographical country calling
// code. We don't support getting an example number for it with this method.
assertNull(phoneUtil.getExampleNumber(RegionCode.UN001));
}
function testGetExampleNumberForNonGeoEntity() {
assertTrue(INTERNATIONAL_TOLL_FREE.equals(
phoneUtil.getExampleNumberForNonGeoEntity(800)));
}
function testConvertAlphaCharactersInNumber() {
@ -650,6 +700,9 @@ function testFormatOutOfCountryCallingNumber() {
assertEquals('011 54 9 11 8765 4321',
phoneUtil.formatOutOfCountryCallingNumber(AR_MOBILE, RegionCode.US));
assertEquals('011 800 1234 5678',
phoneUtil.formatOutOfCountryCallingNumber(INTERNATIONAL_TOLL_FREE,
RegionCode.US));
/** @type {i18n.phonenumbers.PhoneNumber} */
var arNumberWithExtn = AR_MOBILE.clone();
@ -669,7 +722,11 @@ function testFormatOutOfCountryWithInvalidRegion() {
// AQ/Antarctica isn't a valid region code for phone number formatting,
// so this falls back to intl formatting.
assertEquals('+1 650 253 0000',
phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, 'AQ'));
phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.AQ));
// For region code 001, the out-of-country format always turns into the
// international format.
assertEquals('+1 650 253 0000',
phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.UN001));
}
function testFormatOutOfCountryWithPreferredIntlPrefix() {
@ -755,6 +812,10 @@ function testFormatOutOfCountryKeepingAlphaChars() {
assertEquals('+61 1-800-SIX-FLAG',
phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber,
RegionCode.SG));
// Testing the case of calling from a non-supported region.
assertEquals('+61 1-800-SIX-FLAG',
phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber,
RegionCode.AQ));
// Testing the case with an invalid country calling code.
alphaNumericNumber.setCountryCode(0);
@ -773,6 +834,15 @@ function testFormatOutOfCountryKeepingAlphaChars() {
assertEquals('00 1 180-SIX',
phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber,
RegionCode.DE));
// Testing the case of calling from a non-supported region.
alphaNumericNumber.setCountryCode(1);
alphaNumericNumber.setNationalNumber(80749);
alphaNumericNumber.setRawInput('180-SIX');
// No country-code stripping can be done since the number is invalid.
assertEquals('+1 180-SIX',
phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber,
RegionCode.AQ));
}
function testFormatWithCarrierCode() {
@ -859,6 +929,30 @@ function testFormatNumberForMobileDialing() {
assertEquals('+16502530000',
phoneUtil.formatNumberForMobileDialing(usNumberWithExtn,
RegionCode.US, false));
// An invalid US number, which is one digit too long.
assertEquals('+165025300001',
phoneUtil.formatNumberForMobileDialing(US_LONG_NUMBER,
RegionCode.US, false));
assertEquals('+1 65025300001',
phoneUtil.formatNumberForMobileDialing(US_LONG_NUMBER,
RegionCode.US, true));
// Star numbers. In real life they appear in Israel, but we have them in JP
// in our test metadata.
assertEquals('*2345',
phoneUtil.formatNumberForMobileDialing(JP_STAR_NUMBER,
RegionCode.JP, false));
assertEquals('*2345',
phoneUtil.formatNumberForMobileDialing(JP_STAR_NUMBER,
RegionCode.JP, true));
assertEquals('+80012345678',
phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE,
RegionCode.JP, false));
assertEquals('+800 1234 5678',
phoneUtil.formatNumberForMobileDialing(INTERNATIONAL_TOLL_FREE,
RegionCode.JP, true));
}
function testFormatByPattern() {
@ -932,6 +1026,8 @@ function testFormatE164Number() {
var PNF = i18n.phonenumbers.PhoneNumberFormat;
assertEquals('+16502530000', phoneUtil.format(US_NUMBER, PNF.E164));
assertEquals('+4930123456', phoneUtil.format(DE_NUMBER, PNF.E164));
assertEquals('+80012345678',
phoneUtil.format(INTERNATIONAL_TOLL_FREE, PNF.E164));
}
function testFormatNumberWithExtension() {
@ -953,46 +1049,163 @@ function testFormatNumberWithExtension() {
phoneUtil.format(usNumberWithExtension, PNF.NATIONAL));
}
function testFormatUsingOriginalNumberFormat() {
function testFormatInOriginalFormat() {
/** @type {i18n.phonenumbers.PhoneNumber} */
var number1 = phoneUtil.parseAndKeepRawInput('+442087654321', RegionCode.GB);
assertEquals('+44 20 8765 4321',
phoneUtil.formatInOriginalFormat(number1, RegionCode.GB));
phoneUtil.formatInOriginalFormat(number1, RegionCode.GB));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number2 = phoneUtil.parseAndKeepRawInput('02087654321', RegionCode.GB);
assertEquals('(020) 8765 4321',
phoneUtil.formatInOriginalFormat(number2, RegionCode.GB));
phoneUtil.formatInOriginalFormat(number2, RegionCode.GB));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number3 = phoneUtil.parseAndKeepRawInput('011442087654321',
RegionCode.US);
assertEquals('011 44 20 8765 4321',
phoneUtil.formatInOriginalFormat(number3, RegionCode.US));
phoneUtil.formatInOriginalFormat(number3, RegionCode.US));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number4 = phoneUtil.parseAndKeepRawInput('442087654321', RegionCode.GB);
assertEquals('44 20 8765 4321',
phoneUtil.formatInOriginalFormat(number4, RegionCode.GB));
phoneUtil.formatInOriginalFormat(number4, RegionCode.GB));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number5 = phoneUtil.parse('+442087654321', RegionCode.GB);
assertEquals('(020) 8765 4321',
phoneUtil.formatInOriginalFormat(number5, RegionCode.GB));
phoneUtil.formatInOriginalFormat(number5, RegionCode.GB));
// Invalid numbers should be formatted using its raw input when that is
// available. Note area codes starting with 7 are intentionally excluded in
// Invalid numbers that we have a formatting pattern for should be formatted
// properly. Note area codes starting with 7 are intentionally excluded in
// the test metadata for testing purposes.
/** @type {i18n.phonenumbers.PhoneNumber} */
var number6 = phoneUtil.parseAndKeepRawInput('7345678901', RegionCode.US);
assertEquals('7345678901',
phoneUtil.formatInOriginalFormat(number6, RegionCode.US));
assertEquals('734 567 8901',
phoneUtil.formatInOriginalFormat(number6, RegionCode.US));
// When the raw input is unavailable, format as usual.
// US is not a leading zero country, and the presence of the leading zero
// leads us to format the number using raw_input.
/** @type {i18n.phonenumbers.PhoneNumber} */
var number7 = phoneUtil.parse('7345678901', RegionCode.US);
assertEquals('734 567 8901',
phoneUtil.formatInOriginalFormat(number7, RegionCode.US));
var number7 = phoneUtil.parseAndKeepRawInput('0734567 8901', RegionCode.US);
assertEquals('0734567 8901',
phoneUtil.formatInOriginalFormat(number7, RegionCode.US));
// This number is valid, but we don't have a formatting pattern for it.
// Fall back to the raw input.
/** @type {i18n.phonenumbers.PhoneNumber} */
var number8 = phoneUtil.parseAndKeepRawInput('02-4567-8900', RegionCode.KR);
assertEquals('02-4567-8900',
phoneUtil.formatInOriginalFormat(number8, RegionCode.KR));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number9 = phoneUtil.parseAndKeepRawInput('01180012345678', RegionCode.US);
assertEquals('011 800 1234 5678',
phoneUtil.formatInOriginalFormat(number9, RegionCode.US));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number10 = phoneUtil.parseAndKeepRawInput('+80012345678', RegionCode.KR);
assertEquals('+800 1234 5678',
phoneUtil.formatInOriginalFormat(number10, RegionCode.KR));
// US local numbers are formatted correctly, as we have formatting patterns
// for them.
/** @type {i18n.phonenumbers.PhoneNumber} */
var localNumberUS = phoneUtil.parseAndKeepRawInput('2530000', RegionCode.US);
assertEquals('253 0000',
phoneUtil.formatInOriginalFormat(localNumberUS, RegionCode.US));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithNationalPrefixUS =
phoneUtil.parseAndKeepRawInput('18003456789', RegionCode.US);
assertEquals('1 800 345 6789',
phoneUtil.formatInOriginalFormat(numberWithNationalPrefixUS,
RegionCode.US));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithoutNationalPrefixGB =
phoneUtil.parseAndKeepRawInput('2087654321', RegionCode.GB);
assertEquals('20 8765 4321',
phoneUtil.formatInOriginalFormat(numberWithoutNationalPrefixGB,
RegionCode.GB));
// Make sure no metadata is modified as a result of the previous function
// call.
assertEquals('(020) 8765 4321',
phoneUtil.formatInOriginalFormat(number5, RegionCode.GB));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithNationalPrefixMX =
phoneUtil.parseAndKeepRawInput('013312345678', RegionCode.MX);
assertEquals('01 33 1234 5678',
phoneUtil.formatInOriginalFormat(numberWithNationalPrefixMX,
RegionCode.MX));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithoutNationalPrefixMX =
phoneUtil.parseAndKeepRawInput('3312345678', RegionCode.MX);
assertEquals('33 1234 5678',
phoneUtil.formatInOriginalFormat(numberWithoutNationalPrefixMX,
RegionCode.MX));
/** @type {i18n.phonenumbers.PhoneNumber} */
var italianFixedLineNumber =
phoneUtil.parseAndKeepRawInput('0212345678', RegionCode.IT);
assertEquals('02 1234 5678',
phoneUtil.formatInOriginalFormat(italianFixedLineNumber, RegionCode.IT));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithNationalPrefixJP =
phoneUtil.parseAndKeepRawInput('00777012', RegionCode.JP);
assertEquals('0077-7012',
phoneUtil.formatInOriginalFormat(numberWithNationalPrefixJP,
RegionCode.JP));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithoutNationalPrefixJP =
phoneUtil.parseAndKeepRawInput('0777012', RegionCode.JP);
assertEquals('0777012',
phoneUtil.formatInOriginalFormat(numberWithoutNationalPrefixJP,
RegionCode.JP));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithCarrierCodeBR =
phoneUtil.parseAndKeepRawInput('012 3121286979', RegionCode.BR);
assertEquals('012 3121286979',
phoneUtil.formatInOriginalFormat(numberWithCarrierCodeBR, RegionCode.BR));
// The default national prefix used in this case is 045. When a number with
// national prefix 044 is entered, we return the raw input as we don't want to
// change the number entered.
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithNationalPrefixMX1 =
phoneUtil.parseAndKeepRawInput('044(33)1234-5678', RegionCode.MX);
assertEquals('044(33)1234-5678',
phoneUtil.formatInOriginalFormat(numberWithNationalPrefixMX1,
RegionCode.MX));
/** @type {i18n.phonenumbers.PhoneNumber} */
var numberWithNationalPrefixMX2 =
phoneUtil.parseAndKeepRawInput('045(33)1234-5678', RegionCode.MX);
assertEquals('045 33 1234 5678',
phoneUtil.formatInOriginalFormat(numberWithNationalPrefixMX2,
RegionCode.MX));
// The default international prefix used in this case is 0011. When a number
// with international prefix 0012 is entered, we return the raw input as we
// don't want to change the number entered.
/** @type {i18n.phonenumbers.PhoneNumber} */
var outOfCountryNumberFromAU1 =
phoneUtil.parseAndKeepRawInput('0012 16502530000', RegionCode.AU);
assertEquals('0012 16502530000',
phoneUtil.formatInOriginalFormat(outOfCountryNumberFromAU1,
RegionCode.AU));
/** @type {i18n.phonenumbers.PhoneNumber} */
var outOfCountryNumberFromAU2 =
phoneUtil.parseAndKeepRawInput('0011 16502530000', RegionCode.AU);
assertEquals('0011 1 650 253 0000',
phoneUtil.formatInOriginalFormat(outOfCountryNumberFromAU2,
RegionCode.AU));
}
function testIsPremiumRate() {
@ -1045,6 +1258,8 @@ function testIsTollFree() {
tollFreeNumber.setCountryCode(49);
tollFreeNumber.setNationalNumber(8001234567);
assertEquals(PNT.TOLL_FREE, phoneUtil.getNumberType(tollFreeNumber));
assertEquals(PNT.TOLL_FREE, phoneUtil.getNumberType(INTERNATIONAL_TOLL_FREE));
}
function testIsMobile() {
@ -1119,6 +1334,7 @@ function testIsValidNumber() {
assertTrue(phoneUtil.isValidNumber(US_NUMBER));
assertTrue(phoneUtil.isValidNumber(IT_NUMBER));
assertTrue(phoneUtil.isValidNumber(GB_MOBILE));
assertTrue(phoneUtil.isValidNumber(INTERNATIONAL_TOLL_FREE));
/** @type {i18n.phonenumbers.PhoneNumber} */
var nzNumber = new i18n.phonenumbers.PhoneNumber();
@ -1163,6 +1379,10 @@ function testIsValidForRegion() {
reNumber.setNationalNumber(800123456);
assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.YT));
assertTrue(phoneUtil.isValidNumberForRegion(reNumber, RegionCode.RE));
assertTrue(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE,
RegionCode.UN001));
assertFalse(phoneUtil.isValidNumberForRegion(INTERNATIONAL_TOLL_FREE,
RegionCode.US));
}
function testIsNotValidNumber() {
@ -1189,18 +1409,23 @@ function testIsNotValidNumber() {
invalidNumber.setCountryCode(64);
invalidNumber.setNationalNumber(3316005);
assertFalse(phoneUtil.isValidNumber(invalidNumber));
assertFalse(phoneUtil.isValidNumber(INTERNATIONAL_TOLL_FREE_TOO_LONG));
}
function testGetRegionCodeForCountryCode() {
assertEquals(RegionCode.US, phoneUtil.getRegionCodeForCountryCode(1));
assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForCountryCode(44));
assertEquals(RegionCode.DE, phoneUtil.getRegionCodeForCountryCode(49));
assertEquals(RegionCode.UN001, phoneUtil.getRegionCodeForCountryCode(800));
}
function testGetRegionCodeForNumber() {
assertEquals(RegionCode.BS, phoneUtil.getRegionCodeForNumber(BS_NUMBER));
assertEquals(RegionCode.US, phoneUtil.getRegionCodeForNumber(US_NUMBER));
assertEquals(RegionCode.GB, phoneUtil.getRegionCodeForNumber(GB_MOBILE));
assertEquals(RegionCode.UN001,
phoneUtil.getRegionCodeForNumber(INTERNATIONAL_TOLL_FREE));
}
function testGetCountryCodeForRegion() {
@ -1208,6 +1433,7 @@ function testGetCountryCodeForRegion() {
assertEquals(64, phoneUtil.getCountryCodeForRegion(RegionCode.NZ));
assertEquals(0, phoneUtil.getCountryCodeForRegion(null));
assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.ZZ));
assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.UN001));
// CS is already deprecated so the library doesn't support it.
assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.CS));
}
@ -1224,6 +1450,7 @@ function testGetNationalDiallingPrefixForRegion() {
// Test cases with invalid regions.
assertNull(phoneUtil.getNddPrefixForRegion(null, false));
assertNull(phoneUtil.getNddPrefixForRegion(RegionCode.ZZ, false));
assertNull(phoneUtil.getNddPrefixForRegion(RegionCode.UN001, false));
// CS is already deprecated so the library doesn't support it.
assertNull(phoneUtil.getNddPrefixForRegion(RegionCode.CS, false));
}
@ -1233,6 +1460,7 @@ function testIsNANPACountry() {
assertTrue(phoneUtil.isNANPACountry(RegionCode.BS));
assertFalse(phoneUtil.isNANPACountry(RegionCode.DE));
assertFalse(phoneUtil.isNANPACountry(RegionCode.ZZ));
assertFalse(phoneUtil.isNANPACountry(RegionCode.UN001));
assertFalse(phoneUtil.isNANPACountry(null));
}
@ -1240,6 +1468,7 @@ function testIsPossibleNumber() {
assertTrue(phoneUtil.isPossibleNumber(US_NUMBER));
assertTrue(phoneUtil.isPossibleNumber(US_LOCAL_NUMBER));
assertTrue(phoneUtil.isPossibleNumber(GB_NUMBER));
assertTrue(phoneUtil.isPossibleNumber(INTERNATIONAL_TOLL_FREE));
assertTrue(
phoneUtil.isPossibleNumberString('+1 650 253 0000', RegionCode.US));
@ -1259,6 +1488,8 @@ function testIsPossibleNumber() {
phoneUtil.isPossibleNumberString('7031 3000', RegionCode.GB));
assertTrue(
phoneUtil.isPossibleNumberString('3331 6005', RegionCode.NZ));
assertTrue(
phoneUtil.isPossibleNumberString('+800 1234 5678', RegionCode.UN001));
}
function testIsPossibleNumberWithReason() {
@ -1266,32 +1497,35 @@ function testIsPossibleNumberWithReason() {
// National numbers for country calling code +1 that are within 7 to 10 digits
// are possible.
assertEquals(VR.IS_POSSIBLE,
phoneUtil.isPossibleNumberWithReason(US_NUMBER));
phoneUtil.isPossibleNumberWithReason(US_NUMBER));
assertEquals(VR.IS_POSSIBLE,
phoneUtil.isPossibleNumberWithReason(US_LOCAL_NUMBER));
phoneUtil.isPossibleNumberWithReason(US_LOCAL_NUMBER));
assertEquals(VR.TOO_LONG,
phoneUtil.isPossibleNumberWithReason(US_LONG_NUMBER));
phoneUtil.isPossibleNumberWithReason(US_LONG_NUMBER));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number = new i18n.phonenumbers.PhoneNumber();
number.setCountryCode(0);
number.setNationalNumber(2530000);
assertEquals(VR.INVALID_COUNTRY_CODE,
phoneUtil.isPossibleNumberWithReason(number));
phoneUtil.isPossibleNumberWithReason(number));
number = new i18n.phonenumbers.PhoneNumber();
number.setCountryCode(1);
number.setNationalNumber(253000);
assertEquals(VR.TOO_SHORT,
phoneUtil.isPossibleNumberWithReason(number));
phoneUtil.isPossibleNumberWithReason(number));
number = new i18n.phonenumbers.PhoneNumber();
number.setCountryCode(65);
number.setNationalNumber(1234567890);
assertEquals(VR.IS_POSSIBLE,
phoneUtil.isPossibleNumberWithReason(number));
phoneUtil.isPossibleNumberWithReason(number));
assertEquals(VR.TOO_LONG,
phoneUtil.isPossibleNumberWithReason(INTERNATIONAL_TOLL_FREE_TOO_LONG));
// Try with number that we don't have metadata for.
/** @type {i18n.phonenumbers.PhoneNumber} */
@ -1299,19 +1533,20 @@ function testIsPossibleNumberWithReason() {
adNumber.setCountryCode(376);
adNumber.setNationalNumber(12345);
assertEquals(VR.IS_POSSIBLE,
phoneUtil.isPossibleNumberWithReason(adNumber));
phoneUtil.isPossibleNumberWithReason(adNumber));
adNumber.setCountryCode(376);
adNumber.setNationalNumber(13);
assertEquals(VR.TOO_SHORT,
phoneUtil.isPossibleNumberWithReason(adNumber));
phoneUtil.isPossibleNumberWithReason(adNumber));
adNumber.setCountryCode(376);
adNumber.setNationalNumber(12345678901234567);
assertEquals(VR.TOO_LONG,
phoneUtil.isPossibleNumberWithReason(adNumber));
phoneUtil.isPossibleNumberWithReason(adNumber));
}
function testIsNotPossibleNumber() {
assertFalse(phoneUtil.isPossibleNumber(US_LONG_NUMBER));
assertFalse(phoneUtil.isPossibleNumber(INTERNATIONAL_TOLL_FREE_TOO_LONG));
/** @type {i18n.phonenumbers.PhoneNumber} */
var number = new i18n.phonenumbers.PhoneNumber();
@ -1323,26 +1558,20 @@ function testIsNotPossibleNumber() {
number.setCountryCode(44);
number.setNationalNumber(300);
assertFalse(phoneUtil.isPossibleNumber(number));
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));
assertFalse(
phoneUtil.isPossibleNumberString('253-000', RegionCode.US));
assertFalse(
phoneUtil.isPossibleNumberString('1 3000', RegionCode.GB));
assertFalse(
phoneUtil.isPossibleNumberString('+44 300', RegionCode.GB));
phoneUtil.isPossibleNumberString('+800 1234 5678 9', RegionCode.UN001));
}
function testTruncateTooLongNumber() {
// US number 650-253-0000, but entered with one additional digit at the end.
assertTrue(phoneUtil.truncateTooLongNumber(US_LONG_NUMBER));
assertTrue(US_NUMBER.equals(US_LONG_NUMBER));
// GB number 080 1234 5678, but entered with 4 extra digits at the end.
/** @type {i18n.phonenumbers.PhoneNumber} */
var tooLongNumber = new i18n.phonenumbers.PhoneNumber();
@ -1367,6 +1596,15 @@ function testTruncateTooLongNumber() {
assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber));
assertTrue(validNumber.equals(tooLongNumber));
// US number 650-253-0000, but entered with one additional digit at the end.
tooLongNumber = US_LONG_NUMBER.clone();
assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber));
assertTrue(US_NUMBER.equals(tooLongNumber));
tooLongNumber = INTERNATIONAL_TOLL_FREE_TOO_LONG.clone();
assertTrue(phoneUtil.truncateTooLongNumber(tooLongNumber));
assertTrue(INTERNATIONAL_TOLL_FREE.equals(tooLongNumber));
// Tests what happens when a valid number is passed in.
/** @type {i18n.phonenumbers.PhoneNumber} */
var validNumberCopy = validNumber.clone();
@ -1626,6 +1864,22 @@ function testMaybeExtractCountryCode() {
fail('Should not have thrown an exception: ' + e.toString());
}
number = new i18n.phonenumbers.PhoneNumber();
try {
phoneNumber = '+80012345678';
countryCallingCode = 800;
numberToFill = new goog.string.StringBuffer();
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_PLUS_SIGN,
number.getCountryCodeSource());
} catch (e) {
fail('Should not have thrown an exception: ' + e.toString());
}
number = new i18n.phonenumbers.PhoneNumber();
try {
phoneNumber = '2345-6789';
numberToFill = new goog.string.StringBuffer();
@ -1792,6 +2046,8 @@ function testParseNumberWithAlphaCharacters() {
function testParseWithInternationalPrefixes() {
assertTrue(US_NUMBER.equals(
phoneUtil.parse('+1 (650) 253-0000', RegionCode.NZ)));
assertTrue(INTERNATIONAL_TOLL_FREE.equals(
phoneUtil.parse('011 800 1234 5678', RegionCode.US)));
assertTrue(US_NUMBER.equals(
phoneUtil.parse('1-650-253-0000', RegionCode.US)));
// Calling the US number from Singapore by using different service providers
@ -2130,6 +2386,8 @@ function testParseNumbersWithPlusWithNoRegion() {
NZ_NUMBER.equals(phoneUtil.parse('Tel: +64 3 331 6005', RegionCode.ZZ)));
assertTrue(
NZ_NUMBER.equals(phoneUtil.parse('+64 3 331 6005', null)));
assertTrue(
INTERNATIONAL_TOLL_FREE.equals(phoneUtil.parse('+800 1234 5678', null)));
// It is important that we set the carrier code to an empty string, since we
// used ParseAndKeepRawInput and no carrier code was found.
@ -2204,6 +2462,16 @@ function testParseExtensions() {
phoneUtil.parse('+44 2034567890 X 456', RegionCode.GB)));
assertTrue(ukNumber.equals(
phoneUtil.parse('+44-2034567890;ext=456', RegionCode.GB)));
// Full-width extension, 'extn' only.
assertTrue(ukNumber.equals(
phoneUtil.parse('+442034567890\uFF45\uFF58\uFF54\uFF4E456',
RegionCode.GB)));
// 'xtn' only.
assertTrue(ukNumber.equals(
phoneUtil.parse('+442034567890\uFF58\uFF54\uFF4E456', RegionCode.GB)));
// 'xt' only.
assertTrue(ukNumber.equals(
phoneUtil.parse('+442034567890\uFF58\uFF54456', RegionCode.GB)));
/** @type {i18n.phonenumbers.PhoneNumber} */
var usWithExtension = new i18n.phonenumbers.PhoneNumber();
@ -2349,6 +2617,8 @@ function testIsNumberMatchMatches() {
phoneUtil.isNumberMatch(num1, num2));
assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH,
phoneUtil.isNumberMatch('+64 3 331 6005', '+64 03 331 6005'));
assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH,
phoneUtil.isNumberMatch('+800 1234 5678', '+80012345678'));
assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH,
phoneUtil.isNumberMatch('+64 03 331-6005', '+64 03331 6005'));
assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH,
@ -2407,6 +2677,8 @@ function testIsNumberMatchNonMatches() {
// Non-matches.
assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH,
phoneUtil.isNumberMatch('03 331 6005', '03 331 6006'));
assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH,
phoneUtil.isNumberMatch('+800 1234 5678', '+1 800 1234 5678'));
// Different country calling code, partial number match.
assertEquals(i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH,
phoneUtil.isNumberMatch('+64 3 331-6005', '+16433316005'));
@ -2528,11 +2800,14 @@ function testCanBeInternationallyDialled() {
// We have no data for NZ - should return true.
assertTrue(phoneUtil.canBeInternationallyDialled(NZ_NUMBER));
assertTrue(phoneUtil.canBeInternationallyDialled(INTERNATIONAL_TOLL_FREE));
}
function testIsAlphaNumber() {
assertTrue(phoneUtil.isAlphaNumber('1800 six-flags'));
assertTrue(phoneUtil.isAlphaNumber('1800 six-flags ext. 1234'));
assertTrue(phoneUtil.isAlphaNumber('+800 six-flags'));
assertFalse(phoneUtil.isAlphaNumber('1800 123-1234'));
assertFalse(phoneUtil.isAlphaNumber('1800 123-1234 extension: 1234'));
assertFalse(phoneUtil.isAlphaNumber('+800 1234-1234'));
}

+ 4
- 0
javascript/i18n/phonenumbers/regioncodefortesting.js View File

@ -29,10 +29,14 @@ goog.provide('i18n.phonenumbers.RegionCode');
* @enum {string}
*/
i18n.phonenumbers.RegionCode = {
// Region code for global networks (e.g. +800 numbers).
UN001: '001',
AD: 'AD',
AO: 'AO',
AQ: 'AQ',
AR: 'AR',
AU: 'AU',
BR: 'BR',
BS: 'BS',
CA: 'CA',
CN: 'CN',


+ 2
- 0
tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataJsonFromXml.java View File

@ -361,6 +361,8 @@ public class BuildMetadataJsonFromXml extends Command {
}
// required PhoneNumberDesc emergency = 27;
toJsArray(metadata.getEmergency(), jsArrayBuilder);
// required PhoneNumberDesc voicemail = 28;
toJsArray(metadata.getVoicemail(), jsArrayBuilder);
jsArrayBuilder.endArray();
}


Loading…
Cancel
Save