google-libphonenumber 1.0.26 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +8 -0
- package/CHANGELOG.md +30 -0
- package/dist/browser/libphonenumber.js +183 -171
- package/dist/browser/libphonenumber.min.js +9 -9
- package/dist/libphonenumber.js +183 -171
- package/package.json +8 -12
- package/.eslintignore +0 -2
- package/.eslintrc.yml +0 -11
- package/.gitattributes +0 -1
- package/.jscsrc +0 -4
- package/.travis.yml +0 -10
- package/patch.diff +0 -410
- package/patch1.diff +0 -129
- package/patch2.diff +0 -411
- package/src/asyoutypeformatter.js +0 -1113
- package/src/asyoutypeformatter_test.html +0 -38
- package/src/asyoutypeformatter_test.js +0 -1207
- package/src/demo-compiled.html +0 -53
- package/src/demo-compiled.js +0 -456
- package/src/demo.html +0 -62
- package/src/demo.js +0 -161
- package/src/index.js +0 -14
- package/src/metadata.js +0 -5226
- package/src/metadatafortesting.js +0 -630
- package/src/metadatalite.js +0 -5226
- package/src/phonemetadata.pb.js +0 -2443
- package/src/phonenumber.pb.js +0 -536
- package/src/phonenumberutil.js +0 -4223
- package/src/phonenumberutil_test.html +0 -37
- package/src/phonenumberutil_test.js +0 -3330
- package/src/regioncodefortesting.js +0 -66
- package/test/as-you-type-formatter_test.js +0 -33
- package/test/browser.html +0 -17
- package/test/exports_test.js +0 -35
- package/test/phone-util_test.js +0 -101
- package/v1.4.6.tar.gz +0 -0
package/src/phonenumberutil.js
DELETED
|
@@ -1,4223 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (C) 2010 The Libphonenumber Authors.
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @fileoverview Utility for international phone numbers.
|
|
20
|
-
* Functionality includes formatting, parsing and validation.
|
|
21
|
-
* (based on the java implementation).
|
|
22
|
-
*
|
|
23
|
-
* NOTE: A lot of methods in this class require Region Code strings. These must
|
|
24
|
-
* be provided using ISO 3166-1 two-letter country-code format. These should be
|
|
25
|
-
* in upper-case (but for compatibility lower-case is also allowed). The list of
|
|
26
|
-
* the codes can be found here:
|
|
27
|
-
* http://www.iso.org/iso/english_country_names_and_code_elements
|
|
28
|
-
*
|
|
29
|
-
* @author Nikolaos Trogkanis
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
goog.provide('i18n.phonenumbers.Error');
|
|
33
|
-
goog.provide('i18n.phonenumbers.PhoneNumberFormat');
|
|
34
|
-
goog.provide('i18n.phonenumbers.PhoneNumberType');
|
|
35
|
-
goog.provide('i18n.phonenumbers.PhoneNumberUtil');
|
|
36
|
-
goog.provide('i18n.phonenumbers.PhoneNumberUtil.MatchType');
|
|
37
|
-
goog.provide('i18n.phonenumbers.PhoneNumberUtil.ValidationResult');
|
|
38
|
-
|
|
39
|
-
goog.require('goog.array');
|
|
40
|
-
goog.require('goog.proto2.PbLiteSerializer');
|
|
41
|
-
goog.require('goog.string');
|
|
42
|
-
goog.require('goog.string.StringBuffer');
|
|
43
|
-
goog.require('i18n.phonenumbers.NumberFormat');
|
|
44
|
-
goog.require('i18n.phonenumbers.PhoneMetadata');
|
|
45
|
-
goog.require('i18n.phonenumbers.PhoneMetadataCollection');
|
|
46
|
-
goog.require('i18n.phonenumbers.PhoneNumber');
|
|
47
|
-
goog.require('i18n.phonenumbers.PhoneNumber.CountryCodeSource');
|
|
48
|
-
goog.require('i18n.phonenumbers.PhoneNumberDesc');
|
|
49
|
-
goog.require('i18n.phonenumbers.metadata');
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @constructor
|
|
55
|
-
* @private
|
|
56
|
-
*/
|
|
57
|
-
i18n.phonenumbers.PhoneNumberUtil = function() {
|
|
58
|
-
/**
|
|
59
|
-
* A mapping from a region code to the PhoneMetadata for that region.
|
|
60
|
-
* @type {Object.<string, i18n.phonenumbers.PhoneMetadata>}
|
|
61
|
-
*/
|
|
62
|
-
this.regionToMetadataMap = {};
|
|
63
|
-
};
|
|
64
|
-
goog.addSingletonGetter(i18n.phonenumbers.PhoneNumberUtil);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Errors encountered when parsing phone numbers.
|
|
69
|
-
*
|
|
70
|
-
* @enum {string}
|
|
71
|
-
*/
|
|
72
|
-
i18n.phonenumbers.Error = {
|
|
73
|
-
INVALID_COUNTRY_CODE: 'Invalid country calling code',
|
|
74
|
-
// This generally indicates the string passed in had less than 3 digits in it.
|
|
75
|
-
// More specifically, the number failed to match the regular expression
|
|
76
|
-
// VALID_PHONE_NUMBER.
|
|
77
|
-
NOT_A_NUMBER: 'The string supplied did not seem to be a phone number',
|
|
78
|
-
// This indicates the string started with an international dialing prefix, but
|
|
79
|
-
// after this was stripped from the number, had less digits than any valid
|
|
80
|
-
// phone number (including country calling code) could have.
|
|
81
|
-
TOO_SHORT_AFTER_IDD: 'Phone number too short after IDD',
|
|
82
|
-
// This indicates the string, after any country calling code has been
|
|
83
|
-
// stripped, had less digits than any valid phone number could have.
|
|
84
|
-
TOO_SHORT_NSN: 'The string supplied is too short to be a phone number',
|
|
85
|
-
// This indicates the string had more digits than any valid phone number could
|
|
86
|
-
// have.
|
|
87
|
-
TOO_LONG: 'The string supplied is too long to be a phone number'
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @const
|
|
93
|
-
* @type {number}
|
|
94
|
-
* @private
|
|
95
|
-
*/
|
|
96
|
-
i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_ = 1;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* The minimum length of the national significant number.
|
|
101
|
-
*
|
|
102
|
-
* @const
|
|
103
|
-
* @type {number}
|
|
104
|
-
* @private
|
|
105
|
-
*/
|
|
106
|
-
i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ = 2;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* The ITU says the maximum length should be 15, but we have found longer
|
|
111
|
-
* numbers in Germany.
|
|
112
|
-
*
|
|
113
|
-
* @const
|
|
114
|
-
* @type {number}
|
|
115
|
-
* @private
|
|
116
|
-
*/
|
|
117
|
-
i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_ = 17;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* The maximum length of the country calling code.
|
|
122
|
-
*
|
|
123
|
-
* @const
|
|
124
|
-
* @type {number}
|
|
125
|
-
* @private
|
|
126
|
-
*/
|
|
127
|
-
i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ = 3;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* We don't allow input strings for parsing to be longer than 250 chars. This
|
|
132
|
-
* prevents malicious input from consuming CPU.
|
|
133
|
-
*
|
|
134
|
-
* @const
|
|
135
|
-
* @type {number}
|
|
136
|
-
* @private
|
|
137
|
-
*/
|
|
138
|
-
i18n.phonenumbers.PhoneNumberUtil.MAX_INPUT_STRING_LENGTH_ = 250;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Region-code for the unknown region.
|
|
143
|
-
*
|
|
144
|
-
* @const
|
|
145
|
-
* @type {string}
|
|
146
|
-
* @private
|
|
147
|
-
*/
|
|
148
|
-
i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ = 'ZZ';
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* The prefix that needs to be inserted in front of a Colombian landline number
|
|
153
|
-
* when dialed from a mobile phone in Colombia.
|
|
154
|
-
*
|
|
155
|
-
* @const
|
|
156
|
-
* @type {string}
|
|
157
|
-
* @private
|
|
158
|
-
*/
|
|
159
|
-
i18n.phonenumbers.PhoneNumberUtil.COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_ = '3';
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Map of country calling codes that use a mobile token before the area code.
|
|
164
|
-
* One example of when this is relevant is when determining the length of the
|
|
165
|
-
* national destination code, which should be the length of the area code plus
|
|
166
|
-
* the length of the mobile token.
|
|
167
|
-
*
|
|
168
|
-
* @const
|
|
169
|
-
* @type {!Object.<number, string>}
|
|
170
|
-
* @private
|
|
171
|
-
*/
|
|
172
|
-
i18n.phonenumbers.PhoneNumberUtil.MOBILE_TOKEN_MAPPINGS_ = {
|
|
173
|
-
52: '1',
|
|
174
|
-
54: '9'
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Set of country calling codes that have geographically assigned mobile
|
|
180
|
-
* numbers. This may not be complete; we add calling codes case by case, as we
|
|
181
|
-
* find geographical mobile numbers or hear from user reports.
|
|
182
|
-
*
|
|
183
|
-
* @const
|
|
184
|
-
* @type {!Array.<number>}
|
|
185
|
-
* @private
|
|
186
|
-
*/
|
|
187
|
-
i18n.phonenumbers.PhoneNumberUtil.GEO_MOBILE_COUNTRIES_ = [
|
|
188
|
-
52, // Mexico
|
|
189
|
-
54, // Argentina
|
|
190
|
-
55 // Brazil
|
|
191
|
-
];
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* The PLUS_SIGN signifies the international prefix.
|
|
196
|
-
*
|
|
197
|
-
* @const
|
|
198
|
-
* @type {string}
|
|
199
|
-
*/
|
|
200
|
-
i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN = '+';
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* @const
|
|
205
|
-
* @type {string}
|
|
206
|
-
* @private
|
|
207
|
-
*/
|
|
208
|
-
i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ = '*';
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* The RFC 3966 format for extensions.
|
|
213
|
-
*
|
|
214
|
-
* @const
|
|
215
|
-
* @type {string}
|
|
216
|
-
* @private
|
|
217
|
-
*/
|
|
218
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ = ';ext=';
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* @const
|
|
223
|
-
* @type {string}
|
|
224
|
-
* @private
|
|
225
|
-
*/
|
|
226
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ = 'tel:';
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* @const
|
|
231
|
-
* @type {string}
|
|
232
|
-
* @private
|
|
233
|
-
*/
|
|
234
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_ = ';phone-context=';
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* @const
|
|
239
|
-
* @type {string}
|
|
240
|
-
* @private
|
|
241
|
-
*/
|
|
242
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_ = ';isub=';
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* These mappings map a character (key) to a specific digit that should replace
|
|
247
|
-
* it for normalization purposes. Non-European digits that may be used in phone
|
|
248
|
-
* numbers are mapped to a European equivalent.
|
|
249
|
-
*
|
|
250
|
-
* @const
|
|
251
|
-
* @type {!Object.<string, string>}
|
|
252
|
-
*/
|
|
253
|
-
i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = {
|
|
254
|
-
'0': '0',
|
|
255
|
-
'1': '1',
|
|
256
|
-
'2': '2',
|
|
257
|
-
'3': '3',
|
|
258
|
-
'4': '4',
|
|
259
|
-
'5': '5',
|
|
260
|
-
'6': '6',
|
|
261
|
-
'7': '7',
|
|
262
|
-
'8': '8',
|
|
263
|
-
'9': '9',
|
|
264
|
-
'\uFF10': '0', // Fullwidth digit 0
|
|
265
|
-
'\uFF11': '1', // Fullwidth digit 1
|
|
266
|
-
'\uFF12': '2', // Fullwidth digit 2
|
|
267
|
-
'\uFF13': '3', // Fullwidth digit 3
|
|
268
|
-
'\uFF14': '4', // Fullwidth digit 4
|
|
269
|
-
'\uFF15': '5', // Fullwidth digit 5
|
|
270
|
-
'\uFF16': '6', // Fullwidth digit 6
|
|
271
|
-
'\uFF17': '7', // Fullwidth digit 7
|
|
272
|
-
'\uFF18': '8', // Fullwidth digit 8
|
|
273
|
-
'\uFF19': '9', // Fullwidth digit 9
|
|
274
|
-
'\u0660': '0', // Arabic-indic digit 0
|
|
275
|
-
'\u0661': '1', // Arabic-indic digit 1
|
|
276
|
-
'\u0662': '2', // Arabic-indic digit 2
|
|
277
|
-
'\u0663': '3', // Arabic-indic digit 3
|
|
278
|
-
'\u0664': '4', // Arabic-indic digit 4
|
|
279
|
-
'\u0665': '5', // Arabic-indic digit 5
|
|
280
|
-
'\u0666': '6', // Arabic-indic digit 6
|
|
281
|
-
'\u0667': '7', // Arabic-indic digit 7
|
|
282
|
-
'\u0668': '8', // Arabic-indic digit 8
|
|
283
|
-
'\u0669': '9', // Arabic-indic digit 9
|
|
284
|
-
'\u06F0': '0', // Eastern-Arabic digit 0
|
|
285
|
-
'\u06F1': '1', // Eastern-Arabic digit 1
|
|
286
|
-
'\u06F2': '2', // Eastern-Arabic digit 2
|
|
287
|
-
'\u06F3': '3', // Eastern-Arabic digit 3
|
|
288
|
-
'\u06F4': '4', // Eastern-Arabic digit 4
|
|
289
|
-
'\u06F5': '5', // Eastern-Arabic digit 5
|
|
290
|
-
'\u06F6': '6', // Eastern-Arabic digit 6
|
|
291
|
-
'\u06F7': '7', // Eastern-Arabic digit 7
|
|
292
|
-
'\u06F8': '8', // Eastern-Arabic digit 8
|
|
293
|
-
'\u06F9': '9' // Eastern-Arabic digit 9
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* A map that contains characters that are essential when dialling. That means
|
|
299
|
-
* any of the characters in this map must not be removed from a number when
|
|
300
|
-
* dialling, otherwise the call will not reach the intended destination.
|
|
301
|
-
*
|
|
302
|
-
* @const
|
|
303
|
-
* @type {!Object.<string, string>}
|
|
304
|
-
* @private
|
|
305
|
-
*/
|
|
306
|
-
i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_ = {
|
|
307
|
-
'0': '0',
|
|
308
|
-
'1': '1',
|
|
309
|
-
'2': '2',
|
|
310
|
-
'3': '3',
|
|
311
|
-
'4': '4',
|
|
312
|
-
'5': '5',
|
|
313
|
-
'6': '6',
|
|
314
|
-
'7': '7',
|
|
315
|
-
'8': '8',
|
|
316
|
-
'9': '9',
|
|
317
|
-
'+': i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN,
|
|
318
|
-
'*': '*'
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Only upper-case variants of alpha characters are stored.
|
|
324
|
-
*
|
|
325
|
-
* @const
|
|
326
|
-
* @type {!Object.<string, string>}
|
|
327
|
-
* @private
|
|
328
|
-
*/
|
|
329
|
-
i18n.phonenumbers.PhoneNumberUtil.ALPHA_MAPPINGS_ = {
|
|
330
|
-
'A': '2',
|
|
331
|
-
'B': '2',
|
|
332
|
-
'C': '2',
|
|
333
|
-
'D': '3',
|
|
334
|
-
'E': '3',
|
|
335
|
-
'F': '3',
|
|
336
|
-
'G': '4',
|
|
337
|
-
'H': '4',
|
|
338
|
-
'I': '4',
|
|
339
|
-
'J': '5',
|
|
340
|
-
'K': '5',
|
|
341
|
-
'L': '5',
|
|
342
|
-
'M': '6',
|
|
343
|
-
'N': '6',
|
|
344
|
-
'O': '6',
|
|
345
|
-
'P': '7',
|
|
346
|
-
'Q': '7',
|
|
347
|
-
'R': '7',
|
|
348
|
-
'S': '7',
|
|
349
|
-
'T': '8',
|
|
350
|
-
'U': '8',
|
|
351
|
-
'V': '8',
|
|
352
|
-
'W': '9',
|
|
353
|
-
'X': '9',
|
|
354
|
-
'Y': '9',
|
|
355
|
-
'Z': '9'
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* For performance reasons, amalgamate both into one map.
|
|
361
|
-
*
|
|
362
|
-
* @const
|
|
363
|
-
* @type {!Object.<string, string>}
|
|
364
|
-
* @private
|
|
365
|
-
*/
|
|
366
|
-
i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_ = {
|
|
367
|
-
'0': '0',
|
|
368
|
-
'1': '1',
|
|
369
|
-
'2': '2',
|
|
370
|
-
'3': '3',
|
|
371
|
-
'4': '4',
|
|
372
|
-
'5': '5',
|
|
373
|
-
'6': '6',
|
|
374
|
-
'7': '7',
|
|
375
|
-
'8': '8',
|
|
376
|
-
'9': '9',
|
|
377
|
-
'\uFF10': '0', // Fullwidth digit 0
|
|
378
|
-
'\uFF11': '1', // Fullwidth digit 1
|
|
379
|
-
'\uFF12': '2', // Fullwidth digit 2
|
|
380
|
-
'\uFF13': '3', // Fullwidth digit 3
|
|
381
|
-
'\uFF14': '4', // Fullwidth digit 4
|
|
382
|
-
'\uFF15': '5', // Fullwidth digit 5
|
|
383
|
-
'\uFF16': '6', // Fullwidth digit 6
|
|
384
|
-
'\uFF17': '7', // Fullwidth digit 7
|
|
385
|
-
'\uFF18': '8', // Fullwidth digit 8
|
|
386
|
-
'\uFF19': '9', // Fullwidth digit 9
|
|
387
|
-
'\u0660': '0', // Arabic-indic digit 0
|
|
388
|
-
'\u0661': '1', // Arabic-indic digit 1
|
|
389
|
-
'\u0662': '2', // Arabic-indic digit 2
|
|
390
|
-
'\u0663': '3', // Arabic-indic digit 3
|
|
391
|
-
'\u0664': '4', // Arabic-indic digit 4
|
|
392
|
-
'\u0665': '5', // Arabic-indic digit 5
|
|
393
|
-
'\u0666': '6', // Arabic-indic digit 6
|
|
394
|
-
'\u0667': '7', // Arabic-indic digit 7
|
|
395
|
-
'\u0668': '8', // Arabic-indic digit 8
|
|
396
|
-
'\u0669': '9', // Arabic-indic digit 9
|
|
397
|
-
'\u06F0': '0', // Eastern-Arabic digit 0
|
|
398
|
-
'\u06F1': '1', // Eastern-Arabic digit 1
|
|
399
|
-
'\u06F2': '2', // Eastern-Arabic digit 2
|
|
400
|
-
'\u06F3': '3', // Eastern-Arabic digit 3
|
|
401
|
-
'\u06F4': '4', // Eastern-Arabic digit 4
|
|
402
|
-
'\u06F5': '5', // Eastern-Arabic digit 5
|
|
403
|
-
'\u06F6': '6', // Eastern-Arabic digit 6
|
|
404
|
-
'\u06F7': '7', // Eastern-Arabic digit 7
|
|
405
|
-
'\u06F8': '8', // Eastern-Arabic digit 8
|
|
406
|
-
'\u06F9': '9', // Eastern-Arabic digit 9
|
|
407
|
-
'A': '2',
|
|
408
|
-
'B': '2',
|
|
409
|
-
'C': '2',
|
|
410
|
-
'D': '3',
|
|
411
|
-
'E': '3',
|
|
412
|
-
'F': '3',
|
|
413
|
-
'G': '4',
|
|
414
|
-
'H': '4',
|
|
415
|
-
'I': '4',
|
|
416
|
-
'J': '5',
|
|
417
|
-
'K': '5',
|
|
418
|
-
'L': '5',
|
|
419
|
-
'M': '6',
|
|
420
|
-
'N': '6',
|
|
421
|
-
'O': '6',
|
|
422
|
-
'P': '7',
|
|
423
|
-
'Q': '7',
|
|
424
|
-
'R': '7',
|
|
425
|
-
'S': '7',
|
|
426
|
-
'T': '8',
|
|
427
|
-
'U': '8',
|
|
428
|
-
'V': '8',
|
|
429
|
-
'W': '9',
|
|
430
|
-
'X': '9',
|
|
431
|
-
'Y': '9',
|
|
432
|
-
'Z': '9'
|
|
433
|
-
};
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Separate map of all symbols that we wish to retain when formatting alpha
|
|
438
|
-
* numbers. This includes digits, ASCII letters and number grouping symbols such
|
|
439
|
-
* as '-' and ' '.
|
|
440
|
-
*
|
|
441
|
-
* @const
|
|
442
|
-
* @type {!Object.<string, string>}
|
|
443
|
-
* @private
|
|
444
|
-
*/
|
|
445
|
-
i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_ = {
|
|
446
|
-
'0': '0',
|
|
447
|
-
'1': '1',
|
|
448
|
-
'2': '2',
|
|
449
|
-
'3': '3',
|
|
450
|
-
'4': '4',
|
|
451
|
-
'5': '5',
|
|
452
|
-
'6': '6',
|
|
453
|
-
'7': '7',
|
|
454
|
-
'8': '8',
|
|
455
|
-
'9': '9',
|
|
456
|
-
'A': 'A',
|
|
457
|
-
'B': 'B',
|
|
458
|
-
'C': 'C',
|
|
459
|
-
'D': 'D',
|
|
460
|
-
'E': 'E',
|
|
461
|
-
'F': 'F',
|
|
462
|
-
'G': 'G',
|
|
463
|
-
'H': 'H',
|
|
464
|
-
'I': 'I',
|
|
465
|
-
'J': 'J',
|
|
466
|
-
'K': 'K',
|
|
467
|
-
'L': 'L',
|
|
468
|
-
'M': 'M',
|
|
469
|
-
'N': 'N',
|
|
470
|
-
'O': 'O',
|
|
471
|
-
'P': 'P',
|
|
472
|
-
'Q': 'Q',
|
|
473
|
-
'R': 'R',
|
|
474
|
-
'S': 'S',
|
|
475
|
-
'T': 'T',
|
|
476
|
-
'U': 'U',
|
|
477
|
-
'V': 'V',
|
|
478
|
-
'W': 'W',
|
|
479
|
-
'X': 'X',
|
|
480
|
-
'Y': 'Y',
|
|
481
|
-
'Z': 'Z',
|
|
482
|
-
'a': 'A',
|
|
483
|
-
'b': 'B',
|
|
484
|
-
'c': 'C',
|
|
485
|
-
'd': 'D',
|
|
486
|
-
'e': 'E',
|
|
487
|
-
'f': 'F',
|
|
488
|
-
'g': 'G',
|
|
489
|
-
'h': 'H',
|
|
490
|
-
'i': 'I',
|
|
491
|
-
'j': 'J',
|
|
492
|
-
'k': 'K',
|
|
493
|
-
'l': 'L',
|
|
494
|
-
'm': 'M',
|
|
495
|
-
'n': 'N',
|
|
496
|
-
'o': 'O',
|
|
497
|
-
'p': 'P',
|
|
498
|
-
'q': 'Q',
|
|
499
|
-
'r': 'R',
|
|
500
|
-
's': 'S',
|
|
501
|
-
't': 'T',
|
|
502
|
-
'u': 'U',
|
|
503
|
-
'v': 'V',
|
|
504
|
-
'w': 'W',
|
|
505
|
-
'x': 'X',
|
|
506
|
-
'y': 'Y',
|
|
507
|
-
'z': 'Z',
|
|
508
|
-
'-': '-',
|
|
509
|
-
'\uFF0D': '-',
|
|
510
|
-
'\u2010': '-',
|
|
511
|
-
'\u2011': '-',
|
|
512
|
-
'\u2012': '-',
|
|
513
|
-
'\u2013': '-',
|
|
514
|
-
'\u2014': '-',
|
|
515
|
-
'\u2015': '-',
|
|
516
|
-
'\u2212': '-',
|
|
517
|
-
'/': '/',
|
|
518
|
-
'\uFF0F': '/',
|
|
519
|
-
' ': ' ',
|
|
520
|
-
'\u3000': ' ',
|
|
521
|
-
'\u2060': ' ',
|
|
522
|
-
'.': '.',
|
|
523
|
-
'\uFF0E': '.'
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
/**
|
|
528
|
-
* Pattern that makes it easy to distinguish whether a region has a unique
|
|
529
|
-
* international dialing prefix or not. If a region has a unique international
|
|
530
|
-
* prefix (e.g. 011 in USA), it will be represented as a string that contains a
|
|
531
|
-
* sequence of ASCII digits. If there are multiple available international
|
|
532
|
-
* prefixes in a region, they will be represented as a regex string that always
|
|
533
|
-
* contains character(s) other than ASCII digits. Note this regex also includes
|
|
534
|
-
* tilde, which signals waiting for the tone.
|
|
535
|
-
*
|
|
536
|
-
* @const
|
|
537
|
-
* @type {!RegExp}
|
|
538
|
-
* @private
|
|
539
|
-
*/
|
|
540
|
-
i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_ =
|
|
541
|
-
/[\d]+(?:[~\u2053\u223C\uFF5E][\d]+)?/;
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
/**
|
|
545
|
-
* Regular expression of acceptable punctuation found in phone numbers. This
|
|
546
|
-
* excludes punctuation found as a leading character only. This consists of dash
|
|
547
|
-
* characters, white space characters, full stops, slashes, square brackets,
|
|
548
|
-
* parentheses and tildes. It also includes the letter 'x' as that is found as a
|
|
549
|
-
* placeholder for carrier information in some phone numbers. Full-width
|
|
550
|
-
* variants are also present.
|
|
551
|
-
*
|
|
552
|
-
* @const
|
|
553
|
-
* @type {string}
|
|
554
|
-
*/
|
|
555
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION =
|
|
556
|
-
'-x\u2010-\u2015\u2212\u30FC\uFF0D-\uFF0F \u00A0\u00AD\u200B\u2060\u3000' +
|
|
557
|
-
'()\uFF08\uFF09\uFF3B\uFF3D.\\[\\]/~\u2053\u223C\uFF5E';
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* Digits accepted in phone numbers (ascii, fullwidth, arabic-indic, and eastern
|
|
562
|
-
* arabic digits).
|
|
563
|
-
*
|
|
564
|
-
* @const
|
|
565
|
-
* @type {string}
|
|
566
|
-
* @private
|
|
567
|
-
*/
|
|
568
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ =
|
|
569
|
-
'0-9\uFF10-\uFF19\u0660-\u0669\u06F0-\u06F9';
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* We accept alpha characters in phone numbers, ASCII only, upper and lower
|
|
574
|
-
* case.
|
|
575
|
-
*
|
|
576
|
-
* @const
|
|
577
|
-
* @type {string}
|
|
578
|
-
* @private
|
|
579
|
-
*/
|
|
580
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ = 'A-Za-z';
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* @const
|
|
585
|
-
* @type {string}
|
|
586
|
-
* @private
|
|
587
|
-
*/
|
|
588
|
-
i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ = '+\uFF0B';
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
/**
|
|
592
|
-
* @const
|
|
593
|
-
* @type {!RegExp}
|
|
594
|
-
*/
|
|
595
|
-
i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_PATTERN =
|
|
596
|
-
new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
/**
|
|
600
|
-
* @const
|
|
601
|
-
* @type {!RegExp}
|
|
602
|
-
* @private
|
|
603
|
-
*/
|
|
604
|
-
i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_ =
|
|
605
|
-
new RegExp('^[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']+');
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
/**
|
|
609
|
-
* @const
|
|
610
|
-
* @type {string}
|
|
611
|
-
* @private
|
|
612
|
-
*/
|
|
613
|
-
i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_ =
|
|
614
|
-
'[' + i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION + ']+';
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
* @const
|
|
619
|
-
* @type {!RegExp}
|
|
620
|
-
*/
|
|
621
|
-
i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN =
|
|
622
|
-
new RegExp('([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + '])');
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* Regular expression of acceptable characters that may start a phone number for
|
|
627
|
-
* the purposes of parsing. This allows us to strip away meaningless prefixes to
|
|
628
|
-
* phone numbers that may be mistakenly given to us. This consists of digits,
|
|
629
|
-
* the plus symbol and arabic-indic digits. This does not contain alpha
|
|
630
|
-
* characters, although they may be used later in the number. It also does not
|
|
631
|
-
* include other punctuation, as this will be stripped later during parsing and
|
|
632
|
-
* is of no information value when parsing a number.
|
|
633
|
-
*
|
|
634
|
-
* @const
|
|
635
|
-
* @type {!RegExp}
|
|
636
|
-
* @private
|
|
637
|
-
*/
|
|
638
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_ =
|
|
639
|
-
new RegExp('[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ +
|
|
640
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']');
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
/**
|
|
644
|
-
* Regular expression of characters typically used to start a second phone
|
|
645
|
-
* number for the purposes of parsing. This allows us to strip off parts of the
|
|
646
|
-
* number that are actually the start of another number, such as for:
|
|
647
|
-
* (530) 583-6985 x302/x2303 -> the second extension here makes this actually
|
|
648
|
-
* two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove
|
|
649
|
-
* the second extension so that the first number is parsed correctly.
|
|
650
|
-
*
|
|
651
|
-
* @const
|
|
652
|
-
* @type {!RegExp}
|
|
653
|
-
* @private
|
|
654
|
-
*/
|
|
655
|
-
i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_ = /[\\\/] *x/;
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
/**
|
|
659
|
-
* Regular expression of trailing characters that we want to remove. We remove
|
|
660
|
-
* all characters that are not alpha or numerical characters. The hash character
|
|
661
|
-
* is retained here, as it may signify the previous block was an extension.
|
|
662
|
-
*
|
|
663
|
-
* @const
|
|
664
|
-
* @type {!RegExp}
|
|
665
|
-
* @private
|
|
666
|
-
*/
|
|
667
|
-
i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_ =
|
|
668
|
-
new RegExp('[^' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ +
|
|
669
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ + '#]+$');
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
/**
|
|
673
|
-
* We use this pattern to check if the phone number has at least three letters
|
|
674
|
-
* in it - if so, then we treat it as a number where some phone-number digits
|
|
675
|
-
* are represented by letters.
|
|
676
|
-
*
|
|
677
|
-
* @const
|
|
678
|
-
* @type {!RegExp}
|
|
679
|
-
* @private
|
|
680
|
-
*/
|
|
681
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_ =
|
|
682
|
-
/(?:.*?[A-Za-z]){3}.*/;
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
|
-
* Regular expression of viable phone numbers. This is location independent.
|
|
687
|
-
* Checks we have at least three leading digits, and only valid punctuation,
|
|
688
|
-
* alpha characters and digits in the phone number. Does not include extension
|
|
689
|
-
* data. The symbol 'x' is allowed here as valid punctuation since it is often
|
|
690
|
-
* used as a placeholder for carrier codes, for example in Brazilian phone
|
|
691
|
-
* numbers. We also allow multiple '+' characters at the start.
|
|
692
|
-
* Corresponds to the following:
|
|
693
|
-
* [digits]{minLengthNsn}|
|
|
694
|
-
* plus_sign*
|
|
695
|
-
* (([punctuation]|[star])*[digits]){3,}([punctuation]|[star]|[digits]|[alpha])*
|
|
696
|
-
*
|
|
697
|
-
* The first reg-ex is to allow short numbers (two digits long) to be parsed if
|
|
698
|
-
* they are entered as "15" etc, but only if there is no punctuation in them.
|
|
699
|
-
* The second expression restricts the number of digits to three or more, but
|
|
700
|
-
* then allows them to be in international form, and to have alpha-characters
|
|
701
|
-
* and punctuation. We split up the two reg-exes here and combine them when
|
|
702
|
-
* creating the reg-ex VALID_PHONE_NUMBER_PATTERN_ itself so we can prefix it
|
|
703
|
-
* with ^ and append $ to each branch.
|
|
704
|
-
*
|
|
705
|
-
* Note VALID_PUNCTUATION starts with a -, so must be the first in the range.
|
|
706
|
-
*
|
|
707
|
-
* @const
|
|
708
|
-
* @type {string}
|
|
709
|
-
* @private
|
|
710
|
-
*/
|
|
711
|
-
i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ =
|
|
712
|
-
'[' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{' +
|
|
713
|
-
i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_ + '}';
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
/**
|
|
717
|
-
* See MIN_LENGTH_PHONE_NUMBER_PATTERN_ for a full description of this reg-exp.
|
|
718
|
-
*
|
|
719
|
-
* @const
|
|
720
|
-
* @type {string}
|
|
721
|
-
* @private
|
|
722
|
-
*/
|
|
723
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ =
|
|
724
|
-
'[' + i18n.phonenumbers.PhoneNumberUtil.PLUS_CHARS_ + ']*(?:[' +
|
|
725
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
|
|
726
|
-
i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ + ']*[' +
|
|
727
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']){3,}[' +
|
|
728
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_PUNCTUATION +
|
|
729
|
-
i18n.phonenumbers.PhoneNumberUtil.STAR_SIGN_ +
|
|
730
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_ +
|
|
731
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']*';
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
/**
|
|
735
|
-
* Default extension prefix to use when formatting. This will be put in front of
|
|
736
|
-
* any extension component of the number, after the main national number is
|
|
737
|
-
* formatted. For example, if you wish the default extension formatting to be
|
|
738
|
-
* ' extn: 3456', then you should specify ' extn: ' here as the default
|
|
739
|
-
* extension prefix. This can be overridden by region-specific preferences.
|
|
740
|
-
*
|
|
741
|
-
* @const
|
|
742
|
-
* @type {string}
|
|
743
|
-
* @private
|
|
744
|
-
*/
|
|
745
|
-
i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ = ' ext. ';
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
/**
|
|
749
|
-
* Pattern to capture digits used in an extension.
|
|
750
|
-
* Places a maximum length of '7' for an extension.
|
|
751
|
-
*
|
|
752
|
-
* @const
|
|
753
|
-
* @type {string}
|
|
754
|
-
* @private
|
|
755
|
-
*/
|
|
756
|
-
i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ =
|
|
757
|
-
'([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,7})';
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
/**
|
|
761
|
-
* Regexp of all possible ways to write extensions, for use when parsing. This
|
|
762
|
-
* will be run as a case-insensitive regexp match. Wide character versions are
|
|
763
|
-
* also provided after each ASCII version. There are three regular expressions
|
|
764
|
-
* here. The first covers RFC 3966 format, where the extension is added using
|
|
765
|
-
* ';ext='. The second more generic one starts with optional white space and
|
|
766
|
-
* ends with an optional full stop (.), followed by zero or more spaces/tabs and
|
|
767
|
-
* then the numbers themselves. The other one covers the special case of
|
|
768
|
-
* American numbers where the extension is written with a hash at the end, such
|
|
769
|
-
* as '- 503#'. Note that the only capturing groups should be around the digits
|
|
770
|
-
* that you want to capture as part of the extension, or else parsing will fail!
|
|
771
|
-
* We allow two options for representing the accented o - the character itself,
|
|
772
|
-
* and one in the unicode decomposed form with the combining acute accent.
|
|
773
|
-
*
|
|
774
|
-
* @const
|
|
775
|
-
* @type {string}
|
|
776
|
-
* @private
|
|
777
|
-
*/
|
|
778
|
-
i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ =
|
|
779
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
|
|
780
|
-
i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '|' +
|
|
781
|
-
'[ \u00A0\\t,]*' +
|
|
782
|
-
'(?:e?xt(?:ensi(?:o\u0301?|\u00F3))?n?|\uFF45?\uFF58\uFF54\uFF4E?|' +
|
|
783
|
-
'[,x\uFF58#\uFF03~\uFF5E]|int|anexo|\uFF49\uFF4E\uFF54)' +
|
|
784
|
-
'[:\\.\uFF0E]?[ \u00A0\\t,-]*' +
|
|
785
|
-
i18n.phonenumbers.PhoneNumberUtil.CAPTURING_EXTN_DIGITS_ + '#?|' +
|
|
786
|
-
'[- ]+([' + i18n.phonenumbers.PhoneNumberUtil.VALID_DIGITS_ + ']{1,5})#';
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
/**
|
|
790
|
-
* Regexp of all known extension prefixes used by different regions followed by
|
|
791
|
-
* 1 or more valid digits, for use when parsing.
|
|
792
|
-
*
|
|
793
|
-
* @const
|
|
794
|
-
* @type {!RegExp}
|
|
795
|
-
* @private
|
|
796
|
-
*/
|
|
797
|
-
i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_ =
|
|
798
|
-
new RegExp('(?:' +
|
|
799
|
-
i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
|
|
800
|
-
')$', 'i');
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
/**
|
|
804
|
-
* We append optionally the extension pattern to the end here, as a valid phone
|
|
805
|
-
* number may have an extension prefix appended, followed by 1 or more digits.
|
|
806
|
-
*
|
|
807
|
-
* @const
|
|
808
|
-
* @type {!RegExp}
|
|
809
|
-
* @private
|
|
810
|
-
*/
|
|
811
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_ =
|
|
812
|
-
new RegExp(
|
|
813
|
-
'^' +
|
|
814
|
-
i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_PHONE_NUMBER_PATTERN_ +
|
|
815
|
-
'$|' +
|
|
816
|
-
'^' + i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_ +
|
|
817
|
-
'(?:' + i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERNS_FOR_PARSING_ +
|
|
818
|
-
')?' + '$', 'i');
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
* @const
|
|
823
|
-
* @type {!RegExp}
|
|
824
|
-
* @private
|
|
825
|
-
*/
|
|
826
|
-
i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_ = /\D+/;
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
/**
|
|
830
|
-
* This was originally set to $1 but there are some countries for which the
|
|
831
|
-
* first group is not used in the national pattern (e.g. Argentina) so the $1
|
|
832
|
-
* group does not match correctly. Therefore, we use \d, so that the first
|
|
833
|
-
* group actually used in the pattern will be matched.
|
|
834
|
-
* @const
|
|
835
|
-
* @type {!RegExp}
|
|
836
|
-
* @private
|
|
837
|
-
*/
|
|
838
|
-
i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_ = /(\$\d)/;
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
/**
|
|
842
|
-
* @const
|
|
843
|
-
* @type {!RegExp}
|
|
844
|
-
* @private
|
|
845
|
-
*/
|
|
846
|
-
i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_ = /\$NP/;
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
/**
|
|
850
|
-
* @const
|
|
851
|
-
* @type {!RegExp}
|
|
852
|
-
* @private
|
|
853
|
-
*/
|
|
854
|
-
i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_ = /\$FG/;
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
/**
|
|
858
|
-
* @const
|
|
859
|
-
* @type {!RegExp}
|
|
860
|
-
* @private
|
|
861
|
-
*/
|
|
862
|
-
i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_ = /\$CC/;
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
/**
|
|
866
|
-
* A pattern that is used to determine if the national prefix formatting rule
|
|
867
|
-
* has the first group only, i.e., does not start with the national prefix.
|
|
868
|
-
* Note that the pattern explicitly allows for unbalanced parentheses.
|
|
869
|
-
* @const
|
|
870
|
-
* @type {!RegExp}
|
|
871
|
-
* @private
|
|
872
|
-
*/
|
|
873
|
-
i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_ =
|
|
874
|
-
/^\(?\$1\)?$/;
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
/**
|
|
878
|
-
* @const
|
|
879
|
-
* @type {string}
|
|
880
|
-
*/
|
|
881
|
-
i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY = '001';
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
/**
|
|
885
|
-
* INTERNATIONAL and NATIONAL formats are consistent with the definition in
|
|
886
|
-
* ITU-T Recommendation E123. For example, the number of the Google Switzerland
|
|
887
|
-
* office will be written as '+41 44 668 1800' in INTERNATIONAL format, and as
|
|
888
|
-
* '044 668 1800' in NATIONAL format. E164 format is as per INTERNATIONAL format
|
|
889
|
-
* but with no formatting applied, e.g. '+41446681800'. RFC3966 is as per
|
|
890
|
-
* INTERNATIONAL format, but with all spaces and other separating symbols
|
|
891
|
-
* replaced with a hyphen, and with any phone number extension appended with
|
|
892
|
-
* ';ext='. It also will have a prefix of 'tel:' added, e.g.
|
|
893
|
-
* 'tel:+41-44-668-1800'.
|
|
894
|
-
*
|
|
895
|
-
* Note: If you are considering storing the number in a neutral format, you are
|
|
896
|
-
* highly advised to use the PhoneNumber class.
|
|
897
|
-
* @enum {number}
|
|
898
|
-
*/
|
|
899
|
-
i18n.phonenumbers.PhoneNumberFormat = {
|
|
900
|
-
E164: 0,
|
|
901
|
-
INTERNATIONAL: 1,
|
|
902
|
-
NATIONAL: 2,
|
|
903
|
-
RFC3966: 3
|
|
904
|
-
};
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
/**
|
|
908
|
-
* Type of phone numbers.
|
|
909
|
-
*
|
|
910
|
-
* @enum {number}
|
|
911
|
-
*/
|
|
912
|
-
i18n.phonenumbers.PhoneNumberType = {
|
|
913
|
-
FIXED_LINE: 0,
|
|
914
|
-
MOBILE: 1,
|
|
915
|
-
// In some regions (e.g. the USA), it is impossible to distinguish between
|
|
916
|
-
// fixed-line and mobile numbers by looking at the phone number itself.
|
|
917
|
-
FIXED_LINE_OR_MOBILE: 2,
|
|
918
|
-
// Freephone lines
|
|
919
|
-
TOLL_FREE: 3,
|
|
920
|
-
PREMIUM_RATE: 4,
|
|
921
|
-
// The cost of this call is shared between the caller and the recipient, and
|
|
922
|
-
// is hence typically less than PREMIUM_RATE calls. See
|
|
923
|
-
// http://en.wikipedia.org/wiki/Shared_Cost_Service for more information.
|
|
924
|
-
SHARED_COST: 5,
|
|
925
|
-
// Voice over IP numbers. This includes TSoIP (Telephony Service over IP).
|
|
926
|
-
VOIP: 6,
|
|
927
|
-
// A personal number is associated with a particular person, and may be routed
|
|
928
|
-
// to either a MOBILE or FIXED_LINE number. Some more information can be found
|
|
929
|
-
// here: http://en.wikipedia.org/wiki/Personal_Numbers
|
|
930
|
-
PERSONAL_NUMBER: 7,
|
|
931
|
-
PAGER: 8,
|
|
932
|
-
// Used for 'Universal Access Numbers' or 'Company Numbers'. They may be
|
|
933
|
-
// further routed to specific offices, but allow one number to be used for a
|
|
934
|
-
// company.
|
|
935
|
-
UAN: 9,
|
|
936
|
-
// Used for 'Voice Mail Access Numbers'.
|
|
937
|
-
VOICEMAIL: 10,
|
|
938
|
-
// A phone number is of type UNKNOWN when it does not fit any of the known
|
|
939
|
-
// patterns for a specific region.
|
|
940
|
-
UNKNOWN: -1
|
|
941
|
-
};
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
/**
|
|
945
|
-
* Types of phone number matches. See detailed description beside the
|
|
946
|
-
* isNumberMatch() method.
|
|
947
|
-
*
|
|
948
|
-
* @enum {number}
|
|
949
|
-
*/
|
|
950
|
-
i18n.phonenumbers.PhoneNumberUtil.MatchType = {
|
|
951
|
-
NOT_A_NUMBER: 0,
|
|
952
|
-
NO_MATCH: 1,
|
|
953
|
-
SHORT_NSN_MATCH: 2,
|
|
954
|
-
NSN_MATCH: 3,
|
|
955
|
-
EXACT_MATCH: 4
|
|
956
|
-
};
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
/**
|
|
960
|
-
* Possible outcomes when testing if a PhoneNumber is possible.
|
|
961
|
-
*
|
|
962
|
-
* @enum {number}
|
|
963
|
-
*/
|
|
964
|
-
i18n.phonenumbers.PhoneNumberUtil.ValidationResult = {
|
|
965
|
-
IS_POSSIBLE: 0,
|
|
966
|
-
INVALID_COUNTRY_CODE: 1,
|
|
967
|
-
TOO_SHORT: 2,
|
|
968
|
-
TOO_LONG: 3
|
|
969
|
-
};
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
/**
|
|
973
|
-
* Attempts to extract a possible number from the string passed in. This
|
|
974
|
-
* currently strips all leading characters that cannot be used to start a phone
|
|
975
|
-
* number. Characters that can be used to start a phone number are defined in
|
|
976
|
-
* the VALID_START_CHAR_PATTERN. If none of these characters are found in the
|
|
977
|
-
* number passed in, an empty string is returned. This function also attempts to
|
|
978
|
-
* strip off any alternative extensions or endings if two or more are present,
|
|
979
|
-
* such as in the case of: (530) 583-6985 x302/x2303. The second extension here
|
|
980
|
-
* makes this actually two phone numbers, (530) 583-6985 x302 and (530) 583-6985
|
|
981
|
-
* x2303. We remove the second extension so that the first number is parsed
|
|
982
|
-
* correctly.
|
|
983
|
-
*
|
|
984
|
-
* @param {string} number the string that might contain a phone number.
|
|
985
|
-
* @return {string} the number, stripped of any non-phone-number prefix (such as
|
|
986
|
-
* 'Tel:') or an empty string if no character used to start phone numbers
|
|
987
|
-
* (such as + or any digit) is found in the number.
|
|
988
|
-
*/
|
|
989
|
-
i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber = function(number) {
|
|
990
|
-
/** @type {string} */
|
|
991
|
-
var possibleNumber;
|
|
992
|
-
|
|
993
|
-
/** @type {number} */
|
|
994
|
-
var start = number
|
|
995
|
-
.search(i18n.phonenumbers.PhoneNumberUtil.VALID_START_CHAR_PATTERN_);
|
|
996
|
-
if (start >= 0) {
|
|
997
|
-
possibleNumber = number.substring(start);
|
|
998
|
-
// Remove trailing non-alpha non-numerical characters.
|
|
999
|
-
possibleNumber = possibleNumber.replace(
|
|
1000
|
-
i18n.phonenumbers.PhoneNumberUtil.UNWANTED_END_CHAR_PATTERN_, '');
|
|
1001
|
-
|
|
1002
|
-
// Check for extra numbers at the end.
|
|
1003
|
-
/** @type {number} */
|
|
1004
|
-
var secondNumberStart = possibleNumber
|
|
1005
|
-
.search(i18n.phonenumbers.PhoneNumberUtil.SECOND_NUMBER_START_PATTERN_);
|
|
1006
|
-
if (secondNumberStart >= 0) {
|
|
1007
|
-
possibleNumber = possibleNumber.substring(0, secondNumberStart);
|
|
1008
|
-
}
|
|
1009
|
-
} else {
|
|
1010
|
-
possibleNumber = '';
|
|
1011
|
-
}
|
|
1012
|
-
return possibleNumber;
|
|
1013
|
-
};
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
/**
|
|
1017
|
-
* Checks to see if the string of characters could possibly be a phone number at
|
|
1018
|
-
* all. At the moment, checks to see that the string begins with at least 2
|
|
1019
|
-
* digits, ignoring any punctuation commonly found in phone numbers. This method
|
|
1020
|
-
* does not require the number to be normalized in advance - but does assume
|
|
1021
|
-
* that leading non-number symbols have been removed, such as by the method
|
|
1022
|
-
* extractPossibleNumber.
|
|
1023
|
-
*
|
|
1024
|
-
* @param {string} number string to be checked for viability as a phone number.
|
|
1025
|
-
* @return {boolean} true if the number could be a phone number of some sort,
|
|
1026
|
-
* otherwise false.
|
|
1027
|
-
*/
|
|
1028
|
-
i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber = function(number) {
|
|
1029
|
-
if (number.length < i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
|
|
1030
|
-
return false;
|
|
1031
|
-
}
|
|
1032
|
-
return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
1033
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_PHONE_NUMBER_PATTERN_, number);
|
|
1034
|
-
};
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
/**
|
|
1038
|
-
* Normalizes a string of characters representing a phone number. This performs
|
|
1039
|
-
* the following conversions:
|
|
1040
|
-
* Punctuation is stripped.
|
|
1041
|
-
* For ALPHA/VANITY numbers:
|
|
1042
|
-
* Letters are converted to their numeric representation on a telephone
|
|
1043
|
-
* keypad. The keypad used here is the one defined in ITU Recommendation
|
|
1044
|
-
* E.161. This is only done if there are 3 or more letters in the number,
|
|
1045
|
-
* to lessen the risk that such letters are typos.
|
|
1046
|
-
* For other numbers:
|
|
1047
|
-
* Wide-ascii digits are converted to normal ASCII (European) digits.
|
|
1048
|
-
* Arabic-Indic numerals are converted to European numerals.
|
|
1049
|
-
* Spurious alpha characters are stripped.
|
|
1050
|
-
*
|
|
1051
|
-
* @param {string} number a string of characters representing a phone number.
|
|
1052
|
-
* @return {string} the normalized string version of the phone number.
|
|
1053
|
-
*/
|
|
1054
|
-
i18n.phonenumbers.PhoneNumberUtil.normalize = function(number) {
|
|
1055
|
-
if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
1056
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_, number)) {
|
|
1057
|
-
return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
|
|
1058
|
-
i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, true);
|
|
1059
|
-
} else {
|
|
1060
|
-
return i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(number);
|
|
1061
|
-
}
|
|
1062
|
-
};
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
/**
|
|
1066
|
-
* Normalizes a string of characters representing a phone number. This is a
|
|
1067
|
-
* wrapper for normalize(String number) but does in-place normalization of the
|
|
1068
|
-
* StringBuffer provided.
|
|
1069
|
-
*
|
|
1070
|
-
* @param {!goog.string.StringBuffer} number a StringBuffer of characters
|
|
1071
|
-
* representing a phone number that will be normalized in place.
|
|
1072
|
-
* @private
|
|
1073
|
-
*/
|
|
1074
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeSB_ = function(number) {
|
|
1075
|
-
/** @type {string} */
|
|
1076
|
-
var normalizedNumber = i18n.phonenumbers.PhoneNumberUtil.normalize(number
|
|
1077
|
-
.toString());
|
|
1078
|
-
number.clear();
|
|
1079
|
-
number.append(normalizedNumber);
|
|
1080
|
-
};
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
/**
|
|
1084
|
-
* Normalizes a string of characters representing a phone number. This converts
|
|
1085
|
-
* wide-ascii and arabic-indic numerals to European numerals, and strips
|
|
1086
|
-
* punctuation and alpha characters.
|
|
1087
|
-
*
|
|
1088
|
-
* @param {string} number a string of characters representing a phone number.
|
|
1089
|
-
* @return {string} the normalized string version of the phone number.
|
|
1090
|
-
*/
|
|
1091
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly = function(number) {
|
|
1092
|
-
return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
|
|
1093
|
-
i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS, true);
|
|
1094
|
-
};
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
/**
|
|
1098
|
-
* Converts all alpha characters in a number to their respective digits on a
|
|
1099
|
-
* keypad, but retains existing formatting. Also converts wide-ascii digits to
|
|
1100
|
-
* normal ascii digits, and converts Arabic-Indic numerals to European numerals.
|
|
1101
|
-
*
|
|
1102
|
-
* @param {string} number a string of characters representing a phone number.
|
|
1103
|
-
* @return {string} the normalized string version of the phone number.
|
|
1104
|
-
*/
|
|
1105
|
-
i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
|
|
1106
|
-
function(number) {
|
|
1107
|
-
|
|
1108
|
-
return i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(number,
|
|
1109
|
-
i18n.phonenumbers.PhoneNumberUtil.ALL_NORMALIZATION_MAPPINGS_, false);
|
|
1110
|
-
};
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
/**
|
|
1114
|
-
* Gets the length of the geographical area code from the
|
|
1115
|
-
* {@code national_number} field of the PhoneNumber object passed in, so that
|
|
1116
|
-
* clients could use it to split a national significant number into geographical
|
|
1117
|
-
* area code and subscriber number. It works in such a way that the resultant
|
|
1118
|
-
* subscriber number should be diallable, at least on some devices. An example
|
|
1119
|
-
* of how this could be used:
|
|
1120
|
-
*
|
|
1121
|
-
* <pre>
|
|
1122
|
-
* var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
|
|
1123
|
-
* var number = phoneUtil.parse('16502530000', 'US');
|
|
1124
|
-
* var nationalSignificantNumber =
|
|
1125
|
-
* phoneUtil.getNationalSignificantNumber(number);
|
|
1126
|
-
* var areaCode;
|
|
1127
|
-
* var subscriberNumber;
|
|
1128
|
-
*
|
|
1129
|
-
* var areaCodeLength = phoneUtil.getLengthOfGeographicalAreaCode(number);
|
|
1130
|
-
* if (areaCodeLength > 0) {
|
|
1131
|
-
* areaCode = nationalSignificantNumber.substring(0, areaCodeLength);
|
|
1132
|
-
* subscriberNumber = nationalSignificantNumber.substring(areaCodeLength);
|
|
1133
|
-
* } else {
|
|
1134
|
-
* areaCode = '';
|
|
1135
|
-
* subscriberNumber = nationalSignificantNumber;
|
|
1136
|
-
* }
|
|
1137
|
-
* </pre>
|
|
1138
|
-
*
|
|
1139
|
-
* N.B.: area code is a very ambiguous concept, so the I18N team generally
|
|
1140
|
-
* recommends against using it for most purposes, but recommends using the more
|
|
1141
|
-
* general {@code national_number} instead. Read the following carefully before
|
|
1142
|
-
* deciding to use this method:
|
|
1143
|
-
* <ul>
|
|
1144
|
-
* <li> geographical area codes change over time, and this method honors those
|
|
1145
|
-
* changes; therefore, it doesn't guarantee the stability of the result it
|
|
1146
|
-
* produces.
|
|
1147
|
-
* <li> subscriber numbers may not be diallable from all devices (notably
|
|
1148
|
-
* mobile devices, which typically requires the full national_number to be
|
|
1149
|
-
* dialled in most regions).
|
|
1150
|
-
* <li> most non-geographical numbers have no area codes, including numbers
|
|
1151
|
-
* from non-geographical entities.
|
|
1152
|
-
* <li> some geographical numbers have no area codes.
|
|
1153
|
-
* </ul>
|
|
1154
|
-
*
|
|
1155
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
|
|
1156
|
-
* which clients want to know the length of the area code.
|
|
1157
|
-
* @return {number} the length of area code of the PhoneNumber object passed in.
|
|
1158
|
-
*/
|
|
1159
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode =
|
|
1160
|
-
function(number) {
|
|
1161
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1162
|
-
var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
|
|
1163
|
-
if (metadata == null) {
|
|
1164
|
-
return 0;
|
|
1165
|
-
}
|
|
1166
|
-
// If a country doesn't use a national prefix, and this number doesn't have
|
|
1167
|
-
// an Italian leading zero, we assume it is a closed dialling plan with no
|
|
1168
|
-
// area codes.
|
|
1169
|
-
if (!metadata.hasNationalPrefix() && !number.hasItalianLeadingZero()) {
|
|
1170
|
-
return 0;
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
if (!this.isNumberGeographical(number)) {
|
|
1174
|
-
return 0;
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
return this.getLengthOfNationalDestinationCode(number);
|
|
1178
|
-
};
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
/**
|
|
1182
|
-
* Gets the length of the national destination code (NDC) from the PhoneNumber
|
|
1183
|
-
* object passed in, so that clients could use it to split a national
|
|
1184
|
-
* significant number into NDC and subscriber number. The NDC of a phone number
|
|
1185
|
-
* is normally the first group of digit(s) right after the country calling code
|
|
1186
|
-
* when the number is formatted in the international format, if there is a
|
|
1187
|
-
* subscriber number part that follows. An example of how this could be used:
|
|
1188
|
-
*
|
|
1189
|
-
* <pre>
|
|
1190
|
-
* var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
|
|
1191
|
-
* var number = phoneUtil.parse('18002530000', 'US');
|
|
1192
|
-
* var nationalSignificantNumber =
|
|
1193
|
-
* phoneUtil.getNationalSignificantNumber(number);
|
|
1194
|
-
* var nationalDestinationCode;
|
|
1195
|
-
* var subscriberNumber;
|
|
1196
|
-
*
|
|
1197
|
-
* var nationalDestinationCodeLength =
|
|
1198
|
-
* phoneUtil.getLengthOfNationalDestinationCode(number);
|
|
1199
|
-
* if (nationalDestinationCodeLength > 0) {
|
|
1200
|
-
* nationalDestinationCode =
|
|
1201
|
-
* nationalSignificantNumber.substring(0, nationalDestinationCodeLength);
|
|
1202
|
-
* subscriberNumber =
|
|
1203
|
-
* nationalSignificantNumber.substring(nationalDestinationCodeLength);
|
|
1204
|
-
* } else {
|
|
1205
|
-
* nationalDestinationCode = '';
|
|
1206
|
-
* subscriberNumber = nationalSignificantNumber;
|
|
1207
|
-
* }
|
|
1208
|
-
* </pre>
|
|
1209
|
-
*
|
|
1210
|
-
* Refer to the unittests to see the difference between this function and
|
|
1211
|
-
* {@link #getLengthOfGeographicalAreaCode}.
|
|
1212
|
-
*
|
|
1213
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber object for
|
|
1214
|
-
* which clients want to know the length of the NDC.
|
|
1215
|
-
* @return {number} the length of NDC of the PhoneNumber object passed in.
|
|
1216
|
-
*/
|
|
1217
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfNationalDestinationCode =
|
|
1218
|
-
function(number) {
|
|
1219
|
-
|
|
1220
|
-
/** @type {i18n.phonenumbers.PhoneNumber} */
|
|
1221
|
-
var copiedProto;
|
|
1222
|
-
if (number.hasExtension()) {
|
|
1223
|
-
// We don't want to alter the proto given to us, but we don't want to
|
|
1224
|
-
// include the extension when we format it, so we copy it and clear the
|
|
1225
|
-
// extension here.
|
|
1226
|
-
copiedProto = number.clone();
|
|
1227
|
-
copiedProto.clearExtension();
|
|
1228
|
-
} else {
|
|
1229
|
-
copiedProto = number;
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
/** @type {string} */
|
|
1233
|
-
var nationalSignificantNumber = this.format(copiedProto,
|
|
1234
|
-
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
1235
|
-
/** @type {!Array.<string>} */
|
|
1236
|
-
var numberGroups = nationalSignificantNumber.split(
|
|
1237
|
-
i18n.phonenumbers.PhoneNumberUtil.NON_DIGITS_PATTERN_);
|
|
1238
|
-
// The pattern will start with '+COUNTRY_CODE ' so the first group will always
|
|
1239
|
-
// be the empty string (before the + symbol) and the second group will be the
|
|
1240
|
-
// country calling code. The third group will be area code if it is not the
|
|
1241
|
-
// last group.
|
|
1242
|
-
// NOTE: On IE the first group that is supposed to be the empty string does
|
|
1243
|
-
// not appear in the array of number groups... so make the result on non-IE
|
|
1244
|
-
// browsers to be that of IE.
|
|
1245
|
-
if (numberGroups[0].length == 0) {
|
|
1246
|
-
numberGroups.shift();
|
|
1247
|
-
}
|
|
1248
|
-
if (numberGroups.length <= 2) {
|
|
1249
|
-
return 0;
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
if (this.getNumberType(number) == i18n.phonenumbers.PhoneNumberType.MOBILE) {
|
|
1253
|
-
// For example Argentinian mobile numbers, when formatted in the
|
|
1254
|
-
// international format, are in the form of +54 9 NDC XXXX.... As a result,
|
|
1255
|
-
// we take the length of the third group (NDC) and add the length of the
|
|
1256
|
-
// mobile token, which also forms part of the national significant number.
|
|
1257
|
-
// This assumes that the mobile token is always formatted separately from
|
|
1258
|
-
// the rest of the phone number.
|
|
1259
|
-
/** @type {string} */
|
|
1260
|
-
var mobileToken = i18n.phonenumbers.PhoneNumberUtil.getCountryMobileToken(
|
|
1261
|
-
number.getCountryCodeOrDefault());
|
|
1262
|
-
if (mobileToken != '') {
|
|
1263
|
-
return numberGroups[2].length + mobileToken.length;
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
return numberGroups[1].length;
|
|
1267
|
-
};
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
/**
|
|
1271
|
-
* Returns the mobile token for the provided country calling code if it has
|
|
1272
|
-
* one, otherwise returns an empty string. A mobile token is a number inserted
|
|
1273
|
-
* before the area code when dialing a mobile number from that country from
|
|
1274
|
-
* abroad.
|
|
1275
|
-
*
|
|
1276
|
-
* @param {number} countryCallingCode the country calling code for which we
|
|
1277
|
-
* want the mobile token.
|
|
1278
|
-
* @return {string} the mobile token for the given country calling code.
|
|
1279
|
-
*/
|
|
1280
|
-
i18n.phonenumbers.PhoneNumberUtil.getCountryMobileToken =
|
|
1281
|
-
function(countryCallingCode) {
|
|
1282
|
-
return i18n.phonenumbers.PhoneNumberUtil.MOBILE_TOKEN_MAPPINGS_[
|
|
1283
|
-
countryCallingCode] || '';
|
|
1284
|
-
};
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
/**
|
|
1288
|
-
* Convenience method to get a list of what regions the library has metadata
|
|
1289
|
-
* for.
|
|
1290
|
-
* @return {!Array.<string>} region codes supported by the library.
|
|
1291
|
-
*/
|
|
1292
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getSupportedRegions = function() {
|
|
1293
|
-
return goog.array.filter(
|
|
1294
|
-
Object.keys(i18n.phonenumbers.metadata.countryToMetadata),
|
|
1295
|
-
function(regionCode) {
|
|
1296
|
-
return isNaN(regionCode);
|
|
1297
|
-
});
|
|
1298
|
-
};
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
/**
|
|
1302
|
-
* Convenience method to get a list of what global network calling codes the
|
|
1303
|
-
* library has metadata for.
|
|
1304
|
-
* @return {!Array.<number>} global network calling codes supported by the
|
|
1305
|
-
* library.
|
|
1306
|
-
*/
|
|
1307
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
1308
|
-
getSupportedGlobalNetworkCallingCodes = function() {
|
|
1309
|
-
var callingCodesAsStrings = goog.array.filter(
|
|
1310
|
-
Object.keys(i18n.phonenumbers.metadata.countryToMetadata),
|
|
1311
|
-
function(regionCode) {
|
|
1312
|
-
return !isNaN(regionCode);
|
|
1313
|
-
});
|
|
1314
|
-
return goog.array.map(callingCodesAsStrings,
|
|
1315
|
-
function(callingCode) {
|
|
1316
|
-
return parseInt(callingCode, 10);
|
|
1317
|
-
});
|
|
1318
|
-
};
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
/**
|
|
1322
|
-
* Normalizes a string of characters representing a phone number by replacing
|
|
1323
|
-
* all characters found in the accompanying map with the values therein, and
|
|
1324
|
-
* stripping all other characters if removeNonMatches is true.
|
|
1325
|
-
*
|
|
1326
|
-
* @param {string} number a string of characters representing a phone number.
|
|
1327
|
-
* @param {!Object.<string, string>} normalizationReplacements a mapping of
|
|
1328
|
-
* characters to what they should be replaced by in the normalized version
|
|
1329
|
-
* of the phone number.
|
|
1330
|
-
* @param {boolean} removeNonMatches indicates whether characters that are not
|
|
1331
|
-
* able to be replaced should be stripped from the number. If this is false,
|
|
1332
|
-
* they will be left unchanged in the number.
|
|
1333
|
-
* @return {string} the normalized string version of the phone number.
|
|
1334
|
-
* @private
|
|
1335
|
-
*/
|
|
1336
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_ =
|
|
1337
|
-
function(number, normalizationReplacements, removeNonMatches) {
|
|
1338
|
-
|
|
1339
|
-
/** @type {!goog.string.StringBuffer} */
|
|
1340
|
-
var normalizedNumber = new goog.string.StringBuffer();
|
|
1341
|
-
/** @type {string} */
|
|
1342
|
-
var character;
|
|
1343
|
-
/** @type {string} */
|
|
1344
|
-
var newDigit;
|
|
1345
|
-
/** @type {number} */
|
|
1346
|
-
var numberLength = number.length;
|
|
1347
|
-
for (var i = 0; i < numberLength; ++i) {
|
|
1348
|
-
character = number.charAt(i);
|
|
1349
|
-
newDigit = normalizationReplacements[character.toUpperCase()];
|
|
1350
|
-
if (newDigit != null) {
|
|
1351
|
-
normalizedNumber.append(newDigit);
|
|
1352
|
-
} else if (!removeNonMatches) {
|
|
1353
|
-
normalizedNumber.append(character);
|
|
1354
|
-
}
|
|
1355
|
-
// If neither of the above are true, we remove this character.
|
|
1356
|
-
}
|
|
1357
|
-
return normalizedNumber.toString();
|
|
1358
|
-
};
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
/**
|
|
1362
|
-
* Helper function to check if the national prefix formatting rule has the first
|
|
1363
|
-
* group only, i.e., does not start with the national prefix.
|
|
1364
|
-
*
|
|
1365
|
-
* @param {string} nationalPrefixFormattingRule The formatting rule for the
|
|
1366
|
-
* national prefix.
|
|
1367
|
-
* @return {boolean} true if the national prefix formatting rule has the first
|
|
1368
|
-
* group only.
|
|
1369
|
-
*/
|
|
1370
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.formattingRuleHasFirstGroupOnly =
|
|
1371
|
-
function(nationalPrefixFormattingRule) {
|
|
1372
|
-
return nationalPrefixFormattingRule.length == 0 ||
|
|
1373
|
-
i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_ONLY_PREFIX_PATTERN_.
|
|
1374
|
-
test(nationalPrefixFormattingRule);
|
|
1375
|
-
};
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
/**
|
|
1379
|
-
* Tests whether a phone number has a geographical association. It checks if
|
|
1380
|
-
* the number is associated to a certain region in the country where it belongs
|
|
1381
|
-
* to. Note that this doesn't verify if the number is actually in use.
|
|
1382
|
-
*
|
|
1383
|
-
* @param {i18n.phonenumbers.PhoneNumber} phoneNumber The phone number to test.
|
|
1384
|
-
* @return {boolean} true if the phone number has a geographical association.
|
|
1385
|
-
*/
|
|
1386
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberGeographical =
|
|
1387
|
-
function(phoneNumber) {
|
|
1388
|
-
/** @type {i18n.phonenumbers.PhoneNumberType} */
|
|
1389
|
-
var numberType = this.getNumberType(phoneNumber);
|
|
1390
|
-
|
|
1391
|
-
return numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE ||
|
|
1392
|
-
numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE ||
|
|
1393
|
-
(goog.array.contains(
|
|
1394
|
-
i18n.phonenumbers.PhoneNumberUtil.GEO_MOBILE_COUNTRIES_,
|
|
1395
|
-
phoneNumber.getCountryCodeOrDefault()) &&
|
|
1396
|
-
numberType == i18n.phonenumbers.PhoneNumberType.MOBILE);
|
|
1397
|
-
};
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
/**
|
|
1401
|
-
* Helper function to check region code is not unknown or null.
|
|
1402
|
-
*
|
|
1403
|
-
* @param {?string} regionCode the ISO 3166-1 two-letter region code.
|
|
1404
|
-
* @return {boolean} true if region code is valid.
|
|
1405
|
-
* @private
|
|
1406
|
-
*/
|
|
1407
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isValidRegionCode_ =
|
|
1408
|
-
function(regionCode) {
|
|
1409
|
-
|
|
1410
|
-
// In Java we check whether the regionCode is contained in supportedRegions
|
|
1411
|
-
// that is built out of all the values of countryCallingCodeToRegionCodeMap
|
|
1412
|
-
// (countryCodeToRegionCodeMap in JS) minus REGION_CODE_FOR_NON_GEO_ENTITY.
|
|
1413
|
-
// In JS we check whether the regionCode is contained in the keys of
|
|
1414
|
-
// countryToMetadata but since for non-geographical country calling codes
|
|
1415
|
-
// (e.g. +800) we use the country calling codes instead of the region code as
|
|
1416
|
-
// key in the map we have to make sure regionCode is not a number to prevent
|
|
1417
|
-
// returning true for non-geographical country calling codes.
|
|
1418
|
-
return regionCode != null &&
|
|
1419
|
-
isNaN(regionCode) &&
|
|
1420
|
-
regionCode.toUpperCase() in i18n.phonenumbers.metadata.countryToMetadata;
|
|
1421
|
-
};
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
/**
|
|
1425
|
-
* Helper function to check the country calling code is valid.
|
|
1426
|
-
*
|
|
1427
|
-
* @param {number} countryCallingCode the country calling code.
|
|
1428
|
-
* @return {boolean} true if country calling code code is valid.
|
|
1429
|
-
* @private
|
|
1430
|
-
*/
|
|
1431
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.hasValidCountryCallingCode_ =
|
|
1432
|
-
function(countryCallingCode) {
|
|
1433
|
-
|
|
1434
|
-
return countryCallingCode in
|
|
1435
|
-
i18n.phonenumbers.metadata.countryCodeToRegionCodeMap;
|
|
1436
|
-
};
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
/**
|
|
1440
|
-
* Formats a phone number in the specified format using default rules. Note that
|
|
1441
|
-
* this does not promise to produce a phone number that the user can dial from
|
|
1442
|
-
* where they are - although we do format in either 'national' or
|
|
1443
|
-
* 'international' format depending on what the client asks for, we do not
|
|
1444
|
-
* currently support a more abbreviated format, such as for users in the same
|
|
1445
|
-
* 'area' who could potentially dial the number without area code. Note that if
|
|
1446
|
-
* the phone number has a country calling code of 0 or an otherwise invalid
|
|
1447
|
-
* country calling code, we cannot work out which formatting rules to apply so
|
|
1448
|
-
* we return the national significant number with no formatting applied.
|
|
1449
|
-
*
|
|
1450
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
|
|
1451
|
-
* formatted.
|
|
1452
|
-
* @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
|
|
1453
|
-
* phone number should be formatted into.
|
|
1454
|
-
* @return {string} the formatted phone number.
|
|
1455
|
-
*/
|
|
1456
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.format =
|
|
1457
|
-
function(number, numberFormat) {
|
|
1458
|
-
|
|
1459
|
-
if (number.getNationalNumber() == 0 && number.hasRawInput()) {
|
|
1460
|
-
// Unparseable numbers that kept their raw input just use that.
|
|
1461
|
-
// This is the only case where a number can be formatted as E164 without a
|
|
1462
|
-
// leading '+' symbol (but the original number wasn't parseable anyway).
|
|
1463
|
-
// TODO: Consider removing the 'if' above so that unparseable strings
|
|
1464
|
-
// without raw input format to the empty string instead of "+00"
|
|
1465
|
-
/** @type {string} */
|
|
1466
|
-
var rawInput = number.getRawInputOrDefault();
|
|
1467
|
-
if (rawInput.length > 0) {
|
|
1468
|
-
return rawInput;
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
/** @type {number} */
|
|
1472
|
-
var countryCallingCode = number.getCountryCodeOrDefault();
|
|
1473
|
-
/** @type {string} */
|
|
1474
|
-
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
|
|
1475
|
-
if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.E164) {
|
|
1476
|
-
// Early exit for E164 case (even if the country calling code is invalid)
|
|
1477
|
-
// since no formatting of the national number needs to be applied.
|
|
1478
|
-
// Extensions are not formatted.
|
|
1479
|
-
return this.prefixNumberWithCountryCallingCode_(
|
|
1480
|
-
countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.E164,
|
|
1481
|
-
nationalSignificantNumber, '');
|
|
1482
|
-
}
|
|
1483
|
-
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
|
|
1484
|
-
return nationalSignificantNumber;
|
|
1485
|
-
}
|
|
1486
|
-
// Note getRegionCodeForCountryCode() is used because formatting information
|
|
1487
|
-
// for regions which share a country calling code is contained by only one
|
|
1488
|
-
// region for performance reasons. For example, for NANPA regions it will be
|
|
1489
|
-
// contained in the metadata for US.
|
|
1490
|
-
/** @type {string} */
|
|
1491
|
-
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
|
|
1492
|
-
|
|
1493
|
-
// Metadata cannot be null because the country calling code is valid (which
|
|
1494
|
-
// means that the region code cannot be ZZ and must be one of our supported
|
|
1495
|
-
// region codes).
|
|
1496
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1497
|
-
var metadata =
|
|
1498
|
-
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
|
|
1499
|
-
/** @type {string} */
|
|
1500
|
-
var formattedExtension =
|
|
1501
|
-
this.maybeGetFormattedExtension_(number, metadata, numberFormat);
|
|
1502
|
-
/** @type {string} */
|
|
1503
|
-
var formattedNationalNumber =
|
|
1504
|
-
this.formatNsn_(nationalSignificantNumber, metadata, numberFormat);
|
|
1505
|
-
return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
|
|
1506
|
-
numberFormat,
|
|
1507
|
-
formattedNationalNumber,
|
|
1508
|
-
formattedExtension);
|
|
1509
|
-
};
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
/**
|
|
1513
|
-
* Formats a phone number in the specified format using client-defined
|
|
1514
|
-
* formatting rules. Note that if the phone number has a country calling code of
|
|
1515
|
-
* zero or an otherwise invalid country calling code, we cannot work out things
|
|
1516
|
-
* like whether there should be a national prefix applied, or how to format
|
|
1517
|
-
* extensions, so we return the national significant number with no formatting
|
|
1518
|
-
* applied.
|
|
1519
|
-
*
|
|
1520
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
|
|
1521
|
-
* formatted.
|
|
1522
|
-
* @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
|
|
1523
|
-
* phone number should be formatted into.
|
|
1524
|
-
* @param {Array.<i18n.phonenumbers.NumberFormat>} userDefinedFormats formatting
|
|
1525
|
-
* rules specified by clients.
|
|
1526
|
-
* @return {string} the formatted phone number.
|
|
1527
|
-
*/
|
|
1528
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
|
|
1529
|
-
function(number, numberFormat, userDefinedFormats) {
|
|
1530
|
-
|
|
1531
|
-
/** @type {number} */
|
|
1532
|
-
var countryCallingCode = number.getCountryCodeOrDefault();
|
|
1533
|
-
/** @type {string} */
|
|
1534
|
-
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
|
|
1535
|
-
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
|
|
1536
|
-
return nationalSignificantNumber;
|
|
1537
|
-
}
|
|
1538
|
-
// Note getRegionCodeForCountryCode() is used because formatting information
|
|
1539
|
-
// for regions which share a country calling code is contained by only one
|
|
1540
|
-
// region for performance reasons. For example, for NANPA regions it will be
|
|
1541
|
-
// contained in the metadata for US.
|
|
1542
|
-
/** @type {string} */
|
|
1543
|
-
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
|
|
1544
|
-
// Metadata cannot be null because the country calling code is valid
|
|
1545
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1546
|
-
var metadata =
|
|
1547
|
-
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
|
|
1548
|
-
|
|
1549
|
-
/** @type {string} */
|
|
1550
|
-
var formattedNumber = '';
|
|
1551
|
-
|
|
1552
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
1553
|
-
var formattingPattern = this.chooseFormattingPatternForNumber_(
|
|
1554
|
-
userDefinedFormats, nationalSignificantNumber);
|
|
1555
|
-
if (formattingPattern == null) {
|
|
1556
|
-
// If no pattern above is matched, we format the number as a whole.
|
|
1557
|
-
formattedNumber = nationalSignificantNumber;
|
|
1558
|
-
} else {
|
|
1559
|
-
// Before we do a replacement of the national prefix pattern $NP with the
|
|
1560
|
-
// national prefix, we need to copy the rule so that subsequent replacements
|
|
1561
|
-
// for different numbers have the appropriate national prefix.
|
|
1562
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
1563
|
-
var numFormatCopy = formattingPattern.clone();
|
|
1564
|
-
/** @type {string} */
|
|
1565
|
-
var nationalPrefixFormattingRule =
|
|
1566
|
-
formattingPattern.getNationalPrefixFormattingRuleOrDefault();
|
|
1567
|
-
if (nationalPrefixFormattingRule.length > 0) {
|
|
1568
|
-
/** @type {string} */
|
|
1569
|
-
var nationalPrefix = metadata.getNationalPrefixOrDefault();
|
|
1570
|
-
if (nationalPrefix.length > 0) {
|
|
1571
|
-
// Replace $NP with national prefix and $FG with the first group ($1).
|
|
1572
|
-
nationalPrefixFormattingRule = nationalPrefixFormattingRule
|
|
1573
|
-
.replace(i18n.phonenumbers.PhoneNumberUtil.NP_PATTERN_,
|
|
1574
|
-
nationalPrefix)
|
|
1575
|
-
.replace(i18n.phonenumbers.PhoneNumberUtil.FG_PATTERN_, '$1');
|
|
1576
|
-
numFormatCopy.setNationalPrefixFormattingRule(
|
|
1577
|
-
nationalPrefixFormattingRule);
|
|
1578
|
-
} else {
|
|
1579
|
-
// We don't want to have a rule for how to format the national prefix if
|
|
1580
|
-
// there isn't one.
|
|
1581
|
-
numFormatCopy.clearNationalPrefixFormattingRule();
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
formattedNumber = this.formatNsnUsingPattern_(
|
|
1585
|
-
nationalSignificantNumber, numFormatCopy, numberFormat);
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
/** @type {string} */
|
|
1589
|
-
var formattedExtension =
|
|
1590
|
-
this.maybeGetFormattedExtension_(number, metadata, numberFormat);
|
|
1591
|
-
return this.prefixNumberWithCountryCallingCode_(countryCallingCode,
|
|
1592
|
-
numberFormat,
|
|
1593
|
-
formattedNumber,
|
|
1594
|
-
formattedExtension);
|
|
1595
|
-
};
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
/**
|
|
1599
|
-
* Formats a phone number in national format for dialing using the carrier as
|
|
1600
|
-
* specified in the {@code carrierCode}. The {@code carrierCode} will always be
|
|
1601
|
-
* used regardless of whether the phone number already has a preferred domestic
|
|
1602
|
-
* carrier code stored. If {@code carrierCode} contains an empty string, returns
|
|
1603
|
-
* the number in national format without any carrier code.
|
|
1604
|
-
*
|
|
1605
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
|
|
1606
|
-
* formatted.
|
|
1607
|
-
* @param {string} carrierCode the carrier selection code to be used.
|
|
1608
|
-
* @return {string} the formatted phone number in national format for dialing
|
|
1609
|
-
* using the carrier as specified in the {@code carrierCode}.
|
|
1610
|
-
*/
|
|
1611
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
1612
|
-
formatNationalNumberWithCarrierCode = function(number, carrierCode) {
|
|
1613
|
-
|
|
1614
|
-
/** @type {number} */
|
|
1615
|
-
var countryCallingCode = number.getCountryCodeOrDefault();
|
|
1616
|
-
/** @type {string} */
|
|
1617
|
-
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
|
|
1618
|
-
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
|
|
1619
|
-
return nationalSignificantNumber;
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
// Note getRegionCodeForCountryCode() is used because formatting information
|
|
1623
|
-
// for regions which share a country calling code is contained by only one
|
|
1624
|
-
// region for performance reasons. For example, for NANPA regions it will be
|
|
1625
|
-
// contained in the metadata for US.
|
|
1626
|
-
/** @type {string} */
|
|
1627
|
-
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
|
|
1628
|
-
// Metadata cannot be null because the country calling code is valid.
|
|
1629
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1630
|
-
var metadata =
|
|
1631
|
-
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
|
|
1632
|
-
/** @type {string} */
|
|
1633
|
-
var formattedExtension = this.maybeGetFormattedExtension_(
|
|
1634
|
-
number, metadata, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1635
|
-
/** @type {string} */
|
|
1636
|
-
var formattedNationalNumber = this.formatNsn_(
|
|
1637
|
-
nationalSignificantNumber, metadata,
|
|
1638
|
-
i18n.phonenumbers.PhoneNumberFormat.NATIONAL, carrierCode);
|
|
1639
|
-
return this.prefixNumberWithCountryCallingCode_(
|
|
1640
|
-
countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.NATIONAL,
|
|
1641
|
-
formattedNationalNumber, formattedExtension);
|
|
1642
|
-
};
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
/**
|
|
1646
|
-
* @param {number} countryCallingCode
|
|
1647
|
-
* @param {?string} regionCode
|
|
1648
|
-
* @return {i18n.phonenumbers.PhoneMetadata}
|
|
1649
|
-
* @private
|
|
1650
|
-
*/
|
|
1651
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegionOrCallingCode_ =
|
|
1652
|
-
function(countryCallingCode, regionCode) {
|
|
1653
|
-
return i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ==
|
|
1654
|
-
regionCode ?
|
|
1655
|
-
this.getMetadataForNonGeographicalRegion(countryCallingCode) :
|
|
1656
|
-
this.getMetadataForRegion(regionCode);
|
|
1657
|
-
};
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
/**
|
|
1661
|
-
* Formats a phone number in national format for dialing using the carrier as
|
|
1662
|
-
* specified in the preferred_domestic_carrier_code field of the PhoneNumber
|
|
1663
|
-
* object passed in. If that is missing, use the {@code fallbackCarrierCode}
|
|
1664
|
-
* passed in instead. If there is no {@code preferred_domestic_carrier_code},
|
|
1665
|
-
* and the {@code fallbackCarrierCode} contains an empty string, return the
|
|
1666
|
-
* number in national format without any carrier code.
|
|
1667
|
-
*
|
|
1668
|
-
* <p>Use {@link #formatNationalNumberWithCarrierCode} instead if the carrier
|
|
1669
|
-
* code passed in should take precedence over the number's
|
|
1670
|
-
* {@code preferred_domestic_carrier_code} when formatting.
|
|
1671
|
-
*
|
|
1672
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
|
|
1673
|
-
* formatted.
|
|
1674
|
-
* @param {string} fallbackCarrierCode the carrier selection code to be used, if
|
|
1675
|
-
* none is found in the phone number itself.
|
|
1676
|
-
* @return {string} the formatted phone number in national format for dialing
|
|
1677
|
-
* using the number's preferred_domestic_carrier_code, or the
|
|
1678
|
-
* {@code fallbackCarrierCode} passed in if none is found.
|
|
1679
|
-
*/
|
|
1680
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
1681
|
-
formatNationalNumberWithPreferredCarrierCode = function(
|
|
1682
|
-
number, fallbackCarrierCode) {
|
|
1683
|
-
return this.formatNationalNumberWithCarrierCode(
|
|
1684
|
-
number,
|
|
1685
|
-
number.hasPreferredDomesticCarrierCode() ?
|
|
1686
|
-
number.getPreferredDomesticCarrierCodeOrDefault() :
|
|
1687
|
-
fallbackCarrierCode);
|
|
1688
|
-
};
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
/**
|
|
1692
|
-
* Returns a number formatted in such a way that it can be dialed from a mobile
|
|
1693
|
-
* phone in a specific region. If the number cannot be reached from the region
|
|
1694
|
-
* (e.g. some countries block toll-free numbers from being called outside of the
|
|
1695
|
-
* country), the method returns an empty string.
|
|
1696
|
-
*
|
|
1697
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
|
|
1698
|
-
* formatted.
|
|
1699
|
-
* @param {string} regionCallingFrom the region where the call is being placed.
|
|
1700
|
-
* @param {boolean} withFormatting whether the number should be returned with
|
|
1701
|
-
* formatting symbols, such as spaces and dashes.
|
|
1702
|
-
* @return {string} the formatted phone number.
|
|
1703
|
-
*/
|
|
1704
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.formatNumberForMobileDialing =
|
|
1705
|
-
function(number, regionCallingFrom, withFormatting) {
|
|
1706
|
-
|
|
1707
|
-
/** @type {number} */
|
|
1708
|
-
var countryCallingCode = number.getCountryCodeOrDefault();
|
|
1709
|
-
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
|
|
1710
|
-
return number.hasRawInput() ? number.getRawInputOrDefault() : '';
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1713
|
-
/** @type {string} */
|
|
1714
|
-
var formattedNumber = '';
|
|
1715
|
-
// Clear the extension, as that part cannot normally be dialed together with
|
|
1716
|
-
// the main number.
|
|
1717
|
-
/** @type {i18n.phonenumbers.PhoneNumber} */
|
|
1718
|
-
var numberNoExt = number.clone();
|
|
1719
|
-
numberNoExt.clearExtension();
|
|
1720
|
-
/** @type {string} */
|
|
1721
|
-
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
|
|
1722
|
-
/** @type {i18n.phonenumbers.PhoneNumberType} */
|
|
1723
|
-
var numberType = this.getNumberType(numberNoExt);
|
|
1724
|
-
/** @type {boolean} */
|
|
1725
|
-
var isValidNumber = (numberType != i18n.phonenumbers.PhoneNumberType.UNKNOWN);
|
|
1726
|
-
if (regionCallingFrom == regionCode) {
|
|
1727
|
-
/** @type {boolean} */
|
|
1728
|
-
var isFixedLineOrMobile =
|
|
1729
|
-
(numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) ||
|
|
1730
|
-
(numberType == i18n.phonenumbers.PhoneNumberType.MOBILE) ||
|
|
1731
|
-
(numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE);
|
|
1732
|
-
// Carrier codes may be needed in some countries. We handle this here.
|
|
1733
|
-
if (regionCode == 'CO' &&
|
|
1734
|
-
numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE) {
|
|
1735
|
-
formattedNumber = this.formatNationalNumberWithCarrierCode(
|
|
1736
|
-
numberNoExt,
|
|
1737
|
-
i18n.phonenumbers.PhoneNumberUtil
|
|
1738
|
-
.COLOMBIA_MOBILE_TO_FIXED_LINE_PREFIX_);
|
|
1739
|
-
} else if (regionCode == 'BR' && isFixedLineOrMobile) {
|
|
1740
|
-
formattedNumber = numberNoExt.hasPreferredDomesticCarrierCode() ?
|
|
1741
|
-
this.formatNationalNumberWithPreferredCarrierCode(numberNoExt, '') :
|
|
1742
|
-
// Brazilian fixed line and mobile numbers need to be dialed with a
|
|
1743
|
-
// carrier code when called within Brazil. Without that, most of the
|
|
1744
|
-
// carriers won't connect the call. Because of that, we return an
|
|
1745
|
-
// empty string here.
|
|
1746
|
-
'';
|
|
1747
|
-
} else if (isValidNumber && regionCode == 'HU') {
|
|
1748
|
-
// The national format for HU numbers doesn't contain the national prefix,
|
|
1749
|
-
// because that is how numbers are normally written down. However, the
|
|
1750
|
-
// national prefix is obligatory when dialing from a mobile phone. As a
|
|
1751
|
-
// result, we add it back here if it is a valid regular length phone
|
|
1752
|
-
// number.
|
|
1753
|
-
formattedNumber =
|
|
1754
|
-
this.getNddPrefixForRegion(regionCode, true /* strip non-digits */) +
|
|
1755
|
-
' ' + this.format(numberNoExt,
|
|
1756
|
-
i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1757
|
-
} else if (countryCallingCode ==
|
|
1758
|
-
i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
|
|
1759
|
-
// For NANPA countries, we output international format for numbers that
|
|
1760
|
-
// can be dialed internationally, since that always works, except for
|
|
1761
|
-
// numbers which might potentially be short numbers, which are always
|
|
1762
|
-
// dialled in national format.
|
|
1763
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1764
|
-
var regionMetadata = this.getMetadataForRegion(regionCallingFrom);
|
|
1765
|
-
if (this.canBeInternationallyDialled(numberNoExt) &&
|
|
1766
|
-
!this.isShorterThanPossibleNormalNumber_(
|
|
1767
|
-
regionMetadata, this.getNationalSignificantNumber(numberNoExt))) {
|
|
1768
|
-
formattedNumber = this.format(
|
|
1769
|
-
numberNoExt, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
1770
|
-
} else {
|
|
1771
|
-
formattedNumber = this.format(
|
|
1772
|
-
numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1773
|
-
}
|
|
1774
|
-
} else {
|
|
1775
|
-
// For non-geographical countries, Mexican and Chilean fixed line and
|
|
1776
|
-
// mobile numbers, we output international format for numbers that can be
|
|
1777
|
-
// dialed internationally, as that always works.
|
|
1778
|
-
if ((regionCode ==
|
|
1779
|
-
i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY ||
|
|
1780
|
-
// MX fixed line and mobile numbers should always be formatted in
|
|
1781
|
-
// international format, even when dialed within MX. For national
|
|
1782
|
-
// format to work, a carrier code needs to be used, and the correct
|
|
1783
|
-
// carrier code depends on if the caller and callee are from the
|
|
1784
|
-
// same local area. It is trickier to get that to work correctly than
|
|
1785
|
-
// using international format, which is tested to work fine on all
|
|
1786
|
-
// carriers.
|
|
1787
|
-
// CL fixed line numbers need the national prefix when dialing in the
|
|
1788
|
-
// national format, but don't have it when used for display. The
|
|
1789
|
-
// reverse is true for mobile numbers. As a result, we output them in
|
|
1790
|
-
// the international format to make it work.
|
|
1791
|
-
((regionCode == 'MX' || regionCode == 'CL') &&
|
|
1792
|
-
isFixedLineOrMobile)) &&
|
|
1793
|
-
this.canBeInternationallyDialled(numberNoExt)) {
|
|
1794
|
-
formattedNumber = this.format(
|
|
1795
|
-
numberNoExt, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
1796
|
-
} else {
|
|
1797
|
-
formattedNumber = this.format(
|
|
1798
|
-
numberNoExt, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
} else if (isValidNumber && this.canBeInternationallyDialled(numberNoExt)) {
|
|
1802
|
-
// We assume that short numbers are not diallable from outside their region,
|
|
1803
|
-
// so if a number is not a valid regular length phone number, we treat it as
|
|
1804
|
-
// if it cannot be internationally dialled.
|
|
1805
|
-
return withFormatting ?
|
|
1806
|
-
this.format(numberNoExt,
|
|
1807
|
-
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL) :
|
|
1808
|
-
this.format(numberNoExt, i18n.phonenumbers.PhoneNumberFormat.E164);
|
|
1809
|
-
}
|
|
1810
|
-
return withFormatting ?
|
|
1811
|
-
formattedNumber :
|
|
1812
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
|
|
1813
|
-
i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_, true);
|
|
1814
|
-
};
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
/**
|
|
1818
|
-
* Formats a phone number for out-of-country dialing purposes. If no
|
|
1819
|
-
* regionCallingFrom is supplied, we format the number in its INTERNATIONAL
|
|
1820
|
-
* format. If the country calling code is the same as that of the region where
|
|
1821
|
-
* the number is from, then NATIONAL formatting will be applied.
|
|
1822
|
-
*
|
|
1823
|
-
* <p>If the number itself has a country calling code of zero or an otherwise
|
|
1824
|
-
* invalid country calling code, then we return the number with no formatting
|
|
1825
|
-
* applied.
|
|
1826
|
-
*
|
|
1827
|
-
* <p>Note this function takes care of the case for calling inside of NANPA and
|
|
1828
|
-
* between Russia and Kazakhstan (who share the same country calling code). In
|
|
1829
|
-
* those cases, no international prefix is used. For regions which have multiple
|
|
1830
|
-
* international prefixes, the number in its INTERNATIONAL format will be
|
|
1831
|
-
* returned instead.
|
|
1832
|
-
*
|
|
1833
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number to be
|
|
1834
|
-
* formatted.
|
|
1835
|
-
* @param {string} regionCallingFrom the region where the call is being placed.
|
|
1836
|
-
* @return {string} the formatted phone number.
|
|
1837
|
-
*/
|
|
1838
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
|
|
1839
|
-
function(number, regionCallingFrom) {
|
|
1840
|
-
|
|
1841
|
-
if (!this.isValidRegionCode_(regionCallingFrom)) {
|
|
1842
|
-
return this.format(number,
|
|
1843
|
-
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
1844
|
-
}
|
|
1845
|
-
/** @type {number} */
|
|
1846
|
-
var countryCallingCode = number.getCountryCodeOrDefault();
|
|
1847
|
-
/** @type {string} */
|
|
1848
|
-
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
|
|
1849
|
-
if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
|
|
1850
|
-
return nationalSignificantNumber;
|
|
1851
|
-
}
|
|
1852
|
-
if (countryCallingCode ==
|
|
1853
|
-
i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
|
|
1854
|
-
if (this.isNANPACountry(regionCallingFrom)) {
|
|
1855
|
-
// For NANPA regions, return the national format for these regions but
|
|
1856
|
-
// prefix it with the country calling code.
|
|
1857
|
-
return countryCallingCode + ' ' +
|
|
1858
|
-
this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1859
|
-
}
|
|
1860
|
-
} else if (countryCallingCode ==
|
|
1861
|
-
this.getCountryCodeForValidRegion_(regionCallingFrom)) {
|
|
1862
|
-
// If regions share a country calling code, the country calling code need
|
|
1863
|
-
// not be dialled. This also applies when dialling within a region, so this
|
|
1864
|
-
// if clause covers both these cases. Technically this is the case for
|
|
1865
|
-
// dialling from La Reunion to other overseas departments of France (French
|
|
1866
|
-
// Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover
|
|
1867
|
-
// this edge case for now and for those cases return the version including
|
|
1868
|
-
// country calling code. Details here:
|
|
1869
|
-
// http://www.petitfute.com/voyage/225-info-pratiques-reunion
|
|
1870
|
-
return this.format(number,
|
|
1871
|
-
i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1872
|
-
}
|
|
1873
|
-
// Metadata cannot be null because we checked 'isValidRegionCode()' above.
|
|
1874
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1875
|
-
var metadataForRegionCallingFrom =
|
|
1876
|
-
this.getMetadataForRegion(regionCallingFrom);
|
|
1877
|
-
/** @type {string} */
|
|
1878
|
-
var internationalPrefix =
|
|
1879
|
-
metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
|
|
1880
|
-
|
|
1881
|
-
// For regions that have multiple international prefixes, the international
|
|
1882
|
-
// format of the number is returned, unless there is a preferred international
|
|
1883
|
-
// prefix.
|
|
1884
|
-
/** @type {string} */
|
|
1885
|
-
var internationalPrefixForFormatting = '';
|
|
1886
|
-
if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
1887
|
-
i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
|
|
1888
|
-
internationalPrefix)) {
|
|
1889
|
-
internationalPrefixForFormatting = internationalPrefix;
|
|
1890
|
-
} else if (metadataForRegionCallingFrom.hasPreferredInternationalPrefix()) {
|
|
1891
|
-
internationalPrefixForFormatting =
|
|
1892
|
-
metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
|
|
1893
|
-
}
|
|
1894
|
-
|
|
1895
|
-
/** @type {string} */
|
|
1896
|
-
var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
|
|
1897
|
-
// Metadata cannot be null because the country calling code is valid.
|
|
1898
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1899
|
-
var metadataForRegion =
|
|
1900
|
-
this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
|
|
1901
|
-
/** @type {string} */
|
|
1902
|
-
var formattedNationalNumber = this.formatNsn_(
|
|
1903
|
-
nationalSignificantNumber, metadataForRegion,
|
|
1904
|
-
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
1905
|
-
/** @type {string} */
|
|
1906
|
-
var formattedExtension = this.maybeGetFormattedExtension_(number,
|
|
1907
|
-
metadataForRegion, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
1908
|
-
return internationalPrefixForFormatting.length > 0 ?
|
|
1909
|
-
internationalPrefixForFormatting + ' ' + countryCallingCode + ' ' +
|
|
1910
|
-
formattedNationalNumber + formattedExtension :
|
|
1911
|
-
this.prefixNumberWithCountryCallingCode_(
|
|
1912
|
-
countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
|
|
1913
|
-
formattedNationalNumber, formattedExtension);
|
|
1914
|
-
};
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
/**
|
|
1918
|
-
* Formats a phone number using the original phone number format that the number
|
|
1919
|
-
* is parsed from. The original format is embedded in the country_code_source
|
|
1920
|
-
* field of the PhoneNumber object passed in. If such information is missing,
|
|
1921
|
-
* the number will be formatted into the NATIONAL format by default. When the
|
|
1922
|
-
* number contains a leading zero and this is unexpected for this country, or we
|
|
1923
|
-
* don't have a formatting pattern for the number, the method returns the raw
|
|
1924
|
-
* input when it is available.
|
|
1925
|
-
*
|
|
1926
|
-
* Note this method guarantees no digit will be inserted, removed or modified as
|
|
1927
|
-
* a result of formatting.
|
|
1928
|
-
*
|
|
1929
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
|
|
1930
|
-
* be formatted in its original number format.
|
|
1931
|
-
* @param {string} regionCallingFrom the region whose IDD needs to be prefixed
|
|
1932
|
-
* if the original number has one.
|
|
1933
|
-
* @return {string} the formatted phone number in its original number format.
|
|
1934
|
-
*/
|
|
1935
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
|
|
1936
|
-
function(number, regionCallingFrom) {
|
|
1937
|
-
|
|
1938
|
-
if (number.hasRawInput() &&
|
|
1939
|
-
(this.hasUnexpectedItalianLeadingZero_(number) ||
|
|
1940
|
-
!this.hasFormattingPatternForNumber_(number))) {
|
|
1941
|
-
// We check if we have the formatting pattern because without that, we might
|
|
1942
|
-
// format the number as a group without national prefix.
|
|
1943
|
-
return number.getRawInputOrDefault();
|
|
1944
|
-
}
|
|
1945
|
-
if (!number.hasCountryCodeSource()) {
|
|
1946
|
-
return this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1947
|
-
}
|
|
1948
|
-
/** @type {string} */
|
|
1949
|
-
var formattedNumber;
|
|
1950
|
-
switch (number.getCountryCodeSource()) {
|
|
1951
|
-
case i18n.phonenumbers.PhoneNumber.CountryCodeSource
|
|
1952
|
-
.FROM_NUMBER_WITH_PLUS_SIGN:
|
|
1953
|
-
formattedNumber = this.format(number,
|
|
1954
|
-
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
1955
|
-
break;
|
|
1956
|
-
case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD:
|
|
1957
|
-
formattedNumber =
|
|
1958
|
-
this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
|
|
1959
|
-
break;
|
|
1960
|
-
case i18n.phonenumbers.PhoneNumber.CountryCodeSource
|
|
1961
|
-
.FROM_NUMBER_WITHOUT_PLUS_SIGN:
|
|
1962
|
-
formattedNumber = this.format(number,
|
|
1963
|
-
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL).substring(1);
|
|
1964
|
-
break;
|
|
1965
|
-
case i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY:
|
|
1966
|
-
// Fall-through to default case.
|
|
1967
|
-
default:
|
|
1968
|
-
/** @type {string} */
|
|
1969
|
-
var regionCode =
|
|
1970
|
-
this.getRegionCodeForCountryCode(number.getCountryCodeOrDefault());
|
|
1971
|
-
// We strip non-digits from the NDD here, and from the raw input later,
|
|
1972
|
-
// so that we can compare them easily.
|
|
1973
|
-
/** @type {?string} */
|
|
1974
|
-
var nationalPrefix = this.getNddPrefixForRegion(regionCode, true);
|
|
1975
|
-
/** @type {string} */
|
|
1976
|
-
var nationalFormat =
|
|
1977
|
-
this.format(number, i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
1978
|
-
if (nationalPrefix == null || nationalPrefix.length == 0) {
|
|
1979
|
-
// If the region doesn't have a national prefix at all, we can safely
|
|
1980
|
-
// return the national format without worrying about a national prefix
|
|
1981
|
-
// being added.
|
|
1982
|
-
formattedNumber = nationalFormat;
|
|
1983
|
-
break;
|
|
1984
|
-
}
|
|
1985
|
-
// Otherwise, we check if the original number was entered with a national
|
|
1986
|
-
// prefix.
|
|
1987
|
-
if (this.rawInputContainsNationalPrefix_(
|
|
1988
|
-
number.getRawInputOrDefault(), nationalPrefix, regionCode)) {
|
|
1989
|
-
// If so, we can safely return the national format.
|
|
1990
|
-
formattedNumber = nationalFormat;
|
|
1991
|
-
break;
|
|
1992
|
-
}
|
|
1993
|
-
// Metadata cannot be null here because getNddPrefixForRegion() (above)
|
|
1994
|
-
// returns null if there is no metadata for the region.
|
|
1995
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
1996
|
-
var metadata = this.getMetadataForRegion(regionCode);
|
|
1997
|
-
/** @type {string} */
|
|
1998
|
-
var nationalNumber = this.getNationalSignificantNumber(number);
|
|
1999
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
2000
|
-
var formatRule = this.chooseFormattingPatternForNumber_(
|
|
2001
|
-
metadata.numberFormatArray(), nationalNumber);
|
|
2002
|
-
// The format rule could still be null here if the national number was 0
|
|
2003
|
-
// and there was no raw input (this should not be possible for numbers
|
|
2004
|
-
// generated by the phonenumber library as they would also not have a
|
|
2005
|
-
// country calling code and we would have exited earlier).
|
|
2006
|
-
if (formatRule == null) {
|
|
2007
|
-
formattedNumber = nationalFormat;
|
|
2008
|
-
break;
|
|
2009
|
-
}
|
|
2010
|
-
// When the format we apply to this number doesn't contain national
|
|
2011
|
-
// prefix, we can just return the national format.
|
|
2012
|
-
// TODO: Refactor the code below with the code in
|
|
2013
|
-
// isNationalPrefixPresentIfRequired.
|
|
2014
|
-
/** @type {string} */
|
|
2015
|
-
var candidateNationalPrefixRule =
|
|
2016
|
-
formatRule.getNationalPrefixFormattingRuleOrDefault();
|
|
2017
|
-
// We assume that the first-group symbol will never be _before_ the
|
|
2018
|
-
// national prefix.
|
|
2019
|
-
/** @type {number} */
|
|
2020
|
-
var indexOfFirstGroup = candidateNationalPrefixRule.indexOf('$1');
|
|
2021
|
-
if (indexOfFirstGroup <= 0) {
|
|
2022
|
-
formattedNumber = nationalFormat;
|
|
2023
|
-
break;
|
|
2024
|
-
}
|
|
2025
|
-
candidateNationalPrefixRule =
|
|
2026
|
-
candidateNationalPrefixRule.substring(0, indexOfFirstGroup);
|
|
2027
|
-
candidateNationalPrefixRule = i18n.phonenumbers.PhoneNumberUtil
|
|
2028
|
-
.normalizeDigitsOnly(candidateNationalPrefixRule);
|
|
2029
|
-
if (candidateNationalPrefixRule.length == 0) {
|
|
2030
|
-
// National prefix not used when formatting this number.
|
|
2031
|
-
formattedNumber = nationalFormat;
|
|
2032
|
-
break;
|
|
2033
|
-
}
|
|
2034
|
-
// Otherwise, we need to remove the national prefix from our output.
|
|
2035
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
2036
|
-
var numFormatCopy = formatRule.clone();
|
|
2037
|
-
numFormatCopy.clearNationalPrefixFormattingRule();
|
|
2038
|
-
formattedNumber = this.formatByPattern(number,
|
|
2039
|
-
i18n.phonenumbers.PhoneNumberFormat.NATIONAL, [numFormatCopy]);
|
|
2040
|
-
break;
|
|
2041
|
-
}
|
|
2042
|
-
/** @type {string} */
|
|
2043
|
-
var rawInput = number.getRawInputOrDefault();
|
|
2044
|
-
// If no digit is inserted/removed/modified as a result of our formatting, we
|
|
2045
|
-
// return the formatted phone number; otherwise we return the raw input the
|
|
2046
|
-
// user entered.
|
|
2047
|
-
if (formattedNumber != null && rawInput.length > 0) {
|
|
2048
|
-
/** @type {string} */
|
|
2049
|
-
var normalizedFormattedNumber =
|
|
2050
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
|
|
2051
|
-
i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
|
|
2052
|
-
true /* remove non matches */);
|
|
2053
|
-
/** @type {string} */
|
|
2054
|
-
var normalizedRawInput =
|
|
2055
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(rawInput,
|
|
2056
|
-
i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
|
|
2057
|
-
true /* remove non matches */);
|
|
2058
|
-
if (normalizedFormattedNumber != normalizedRawInput) {
|
|
2059
|
-
formattedNumber = rawInput;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
return formattedNumber;
|
|
2063
|
-
};
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
/**
|
|
2067
|
-
* Check if rawInput, which is assumed to be in the national format, has a
|
|
2068
|
-
* national prefix. The national prefix is assumed to be in digits-only form.
|
|
2069
|
-
* @param {string} rawInput
|
|
2070
|
-
* @param {string} nationalPrefix
|
|
2071
|
-
* @param {string} regionCode
|
|
2072
|
-
* @return {boolean}
|
|
2073
|
-
* @private
|
|
2074
|
-
*/
|
|
2075
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.rawInputContainsNationalPrefix_ =
|
|
2076
|
-
function(rawInput, nationalPrefix, regionCode) {
|
|
2077
|
-
|
|
2078
|
-
/** @type {string} */
|
|
2079
|
-
var normalizedNationalNumber =
|
|
2080
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(rawInput);
|
|
2081
|
-
if (goog.string.startsWith(normalizedNationalNumber, nationalPrefix)) {
|
|
2082
|
-
try {
|
|
2083
|
-
// Some Japanese numbers (e.g. 00777123) might be mistaken to contain the
|
|
2084
|
-
// national prefix when written without it (e.g. 0777123) if we just do
|
|
2085
|
-
// prefix matching. To tackle that, we check the validity of the number if
|
|
2086
|
-
// the assumed national prefix is removed (777123 won't be valid in
|
|
2087
|
-
// Japan).
|
|
2088
|
-
return this.isValidNumber(
|
|
2089
|
-
this.parse(normalizedNationalNumber.substring(nationalPrefix.length),
|
|
2090
|
-
regionCode));
|
|
2091
|
-
} catch (e) {
|
|
2092
|
-
return false;
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
|
-
return false;
|
|
2096
|
-
};
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
/**
|
|
2100
|
-
* Returns true if a number is from a region whose national significant number
|
|
2101
|
-
* couldn't contain a leading zero, but has the italian_leading_zero field set
|
|
2102
|
-
* to true.
|
|
2103
|
-
* @param {i18n.phonenumbers.PhoneNumber} number
|
|
2104
|
-
* @return {boolean}
|
|
2105
|
-
* @private
|
|
2106
|
-
*/
|
|
2107
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.hasUnexpectedItalianLeadingZero_ =
|
|
2108
|
-
function(number) {
|
|
2109
|
-
|
|
2110
|
-
return number.hasItalianLeadingZero() &&
|
|
2111
|
-
!this.isLeadingZeroPossible(number.getCountryCodeOrDefault());
|
|
2112
|
-
};
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
/**
|
|
2116
|
-
* @param {i18n.phonenumbers.PhoneNumber} number
|
|
2117
|
-
* @return {boolean}
|
|
2118
|
-
* @private
|
|
2119
|
-
*/
|
|
2120
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.hasFormattingPatternForNumber_ =
|
|
2121
|
-
function(number) {
|
|
2122
|
-
|
|
2123
|
-
/** @type {number} */
|
|
2124
|
-
var countryCallingCode = number.getCountryCodeOrDefault();
|
|
2125
|
-
/** @type {string} */
|
|
2126
|
-
var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCallingCode);
|
|
2127
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2128
|
-
var metadata = this.getMetadataForRegionOrCallingCode_(
|
|
2129
|
-
countryCallingCode, phoneNumberRegion);
|
|
2130
|
-
if (metadata == null) {
|
|
2131
|
-
return false;
|
|
2132
|
-
}
|
|
2133
|
-
/** @type {string} */
|
|
2134
|
-
var nationalNumber = this.getNationalSignificantNumber(number);
|
|
2135
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
2136
|
-
var formatRule = this.chooseFormattingPatternForNumber_(
|
|
2137
|
-
metadata.numberFormatArray(), nationalNumber);
|
|
2138
|
-
return formatRule != null;
|
|
2139
|
-
};
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
/**
|
|
2143
|
-
* Formats a phone number for out-of-country dialing purposes.
|
|
2144
|
-
*
|
|
2145
|
-
* Note that in this version, if the number was entered originally using alpha
|
|
2146
|
-
* characters and this version of the number is stored in raw_input, this
|
|
2147
|
-
* representation of the number will be used rather than the digit
|
|
2148
|
-
* representation. Grouping information, as specified by characters such as '-'
|
|
2149
|
-
* and ' ', will be retained.
|
|
2150
|
-
*
|
|
2151
|
-
* <p><b>Caveats:</b></p>
|
|
2152
|
-
* <ul>
|
|
2153
|
-
* <li>This will not produce good results if the country calling code is both
|
|
2154
|
-
* present in the raw input _and_ is the start of the national number. This is
|
|
2155
|
-
* not a problem in the regions which typically use alpha numbers.
|
|
2156
|
-
* <li>This will also not produce good results if the raw input has any grouping
|
|
2157
|
-
* information within the first three digits of the national number, and if the
|
|
2158
|
-
* function needs to strip preceding digits/words in the raw input before these
|
|
2159
|
-
* digits. Normally people group the first three digits together so this is not
|
|
2160
|
-
* a huge problem - and will be fixed if it proves to be so.
|
|
2161
|
-
* </ul>
|
|
2162
|
-
*
|
|
2163
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number that needs to
|
|
2164
|
-
* be formatted.
|
|
2165
|
-
* @param {string} regionCallingFrom the region where the call is being placed.
|
|
2166
|
-
* @return {string} the formatted phone number.
|
|
2167
|
-
*/
|
|
2168
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
2169
|
-
formatOutOfCountryKeepingAlphaChars = function(number, regionCallingFrom) {
|
|
2170
|
-
/** @type {string} */
|
|
2171
|
-
var rawInput = number.getRawInputOrDefault();
|
|
2172
|
-
// If there is no raw input, then we can't keep alpha characters because there
|
|
2173
|
-
// aren't any. In this case, we return formatOutOfCountryCallingNumber.
|
|
2174
|
-
if (rawInput.length == 0) {
|
|
2175
|
-
return this.formatOutOfCountryCallingNumber(number, regionCallingFrom);
|
|
2176
|
-
}
|
|
2177
|
-
/** @type {number} */
|
|
2178
|
-
var countryCode = number.getCountryCodeOrDefault();
|
|
2179
|
-
if (!this.hasValidCountryCallingCode_(countryCode)) {
|
|
2180
|
-
return rawInput;
|
|
2181
|
-
}
|
|
2182
|
-
// Strip any prefix such as country calling code, IDD, that was present. We do
|
|
2183
|
-
// this by comparing the number in raw_input with the parsed number. To do
|
|
2184
|
-
// this, first we normalize punctuation. We retain number grouping symbols
|
|
2185
|
-
// such as ' ' only.
|
|
2186
|
-
rawInput = i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(
|
|
2187
|
-
rawInput,
|
|
2188
|
-
i18n.phonenumbers.PhoneNumberUtil.ALL_PLUS_NUMBER_GROUPING_SYMBOLS_,
|
|
2189
|
-
true);
|
|
2190
|
-
// Now we trim everything before the first three digits in the parsed number.
|
|
2191
|
-
// We choose three because all valid alpha numbers have 3 digits at the start
|
|
2192
|
-
// - if it does not, then we don't trim anything at all. Similarly, if the
|
|
2193
|
-
// national number was less than three digits, we don't trim anything at all.
|
|
2194
|
-
/** @type {string} */
|
|
2195
|
-
var nationalNumber = this.getNationalSignificantNumber(number);
|
|
2196
|
-
if (nationalNumber.length > 3) {
|
|
2197
|
-
/** @type {number} */
|
|
2198
|
-
var firstNationalNumberDigit =
|
|
2199
|
-
rawInput.indexOf(nationalNumber.substring(0, 3));
|
|
2200
|
-
if (firstNationalNumberDigit != -1) {
|
|
2201
|
-
rawInput = rawInput.substring(firstNationalNumberDigit);
|
|
2202
|
-
}
|
|
2203
|
-
}
|
|
2204
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2205
|
-
var metadataForRegionCallingFrom =
|
|
2206
|
-
this.getMetadataForRegion(regionCallingFrom);
|
|
2207
|
-
if (countryCode == i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_) {
|
|
2208
|
-
if (this.isNANPACountry(regionCallingFrom)) {
|
|
2209
|
-
return countryCode + ' ' + rawInput;
|
|
2210
|
-
}
|
|
2211
|
-
} else if (metadataForRegionCallingFrom != null &&
|
|
2212
|
-
countryCode == this.getCountryCodeForValidRegion_(regionCallingFrom)) {
|
|
2213
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
2214
|
-
var formattingPattern = this.chooseFormattingPatternForNumber_(
|
|
2215
|
-
metadataForRegionCallingFrom.numberFormatArray(), nationalNumber);
|
|
2216
|
-
if (formattingPattern == null) {
|
|
2217
|
-
// If no pattern above is matched, we format the original input.
|
|
2218
|
-
return rawInput;
|
|
2219
|
-
}
|
|
2220
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
2221
|
-
var newFormat = formattingPattern.clone();
|
|
2222
|
-
// The first group is the first group of digits that the user wrote
|
|
2223
|
-
// together.
|
|
2224
|
-
newFormat.setPattern('(\\d+)(.*)');
|
|
2225
|
-
// Here we just concatenate them back together after the national prefix
|
|
2226
|
-
// has been fixed.
|
|
2227
|
-
newFormat.setFormat('$1$2');
|
|
2228
|
-
// Now we format using this pattern instead of the default pattern, but
|
|
2229
|
-
// with the national prefix prefixed if necessary.
|
|
2230
|
-
// This will not work in the cases where the pattern (and not the leading
|
|
2231
|
-
// digits) decide whether a national prefix needs to be used, since we have
|
|
2232
|
-
// overridden the pattern to match anything, but that is not the case in the
|
|
2233
|
-
// metadata to date.
|
|
2234
|
-
return this.formatNsnUsingPattern_(rawInput, newFormat,
|
|
2235
|
-
i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
|
|
2236
|
-
}
|
|
2237
|
-
/** @type {string} */
|
|
2238
|
-
var internationalPrefixForFormatting = '';
|
|
2239
|
-
// If an unsupported region-calling-from is entered, or a country with
|
|
2240
|
-
// multiple international prefixes, the international format of the number is
|
|
2241
|
-
// returned, unless there is a preferred international prefix.
|
|
2242
|
-
if (metadataForRegionCallingFrom != null) {
|
|
2243
|
-
/** @type {string} */
|
|
2244
|
-
var internationalPrefix =
|
|
2245
|
-
metadataForRegionCallingFrom.getInternationalPrefixOrDefault();
|
|
2246
|
-
internationalPrefixForFormatting =
|
|
2247
|
-
i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
2248
|
-
i18n.phonenumbers.PhoneNumberUtil.UNIQUE_INTERNATIONAL_PREFIX_,
|
|
2249
|
-
internationalPrefix) ?
|
|
2250
|
-
internationalPrefix :
|
|
2251
|
-
metadataForRegionCallingFrom.getPreferredInternationalPrefixOrDefault();
|
|
2252
|
-
}
|
|
2253
|
-
/** @type {string} */
|
|
2254
|
-
var regionCode = this.getRegionCodeForCountryCode(countryCode);
|
|
2255
|
-
// Metadata cannot be null because the country calling code is valid.
|
|
2256
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2257
|
-
var metadataForRegion =
|
|
2258
|
-
this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
|
|
2259
|
-
/** @type {string} */
|
|
2260
|
-
var formattedExtension = this.maybeGetFormattedExtension_(
|
|
2261
|
-
number, metadataForRegion,
|
|
2262
|
-
i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL);
|
|
2263
|
-
if (internationalPrefixForFormatting.length > 0) {
|
|
2264
|
-
return internationalPrefixForFormatting + ' ' + countryCode + ' ' +
|
|
2265
|
-
rawInput + formattedExtension;
|
|
2266
|
-
} else {
|
|
2267
|
-
// Invalid region entered as country-calling-from (so no metadata was found
|
|
2268
|
-
// for it) or the region chosen has multiple international dialling
|
|
2269
|
-
// prefixes.
|
|
2270
|
-
return this.prefixNumberWithCountryCallingCode_(
|
|
2271
|
-
countryCode, i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL,
|
|
2272
|
-
rawInput, formattedExtension);
|
|
2273
|
-
}
|
|
2274
|
-
};
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
/**
|
|
2278
|
-
* Gets the national significant number of the a phone number. Note a national
|
|
2279
|
-
* significant number doesn't contain a national prefix or any formatting.
|
|
2280
|
-
*
|
|
2281
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number for which the
|
|
2282
|
-
* national significant number is needed.
|
|
2283
|
-
* @return {string} the national significant number of the PhoneNumber object
|
|
2284
|
-
* passed in.
|
|
2285
|
-
*/
|
|
2286
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getNationalSignificantNumber =
|
|
2287
|
-
function(number) {
|
|
2288
|
-
|
|
2289
|
-
// If leading zero(s) have been set, we prefix this now. Note this is not a
|
|
2290
|
-
// national prefix.
|
|
2291
|
-
/** @type {string} */
|
|
2292
|
-
var nationalNumber = '' + number.getNationalNumber();
|
|
2293
|
-
if (number.hasItalianLeadingZero() && number.getItalianLeadingZero()) {
|
|
2294
|
-
return Array(number.getNumberOfLeadingZerosOrDefault() + 1).join('0') +
|
|
2295
|
-
nationalNumber;
|
|
2296
|
-
}
|
|
2297
|
-
return nationalNumber;
|
|
2298
|
-
};
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
/**
|
|
2302
|
-
* A helper function that is used by format and formatByPattern.
|
|
2303
|
-
*
|
|
2304
|
-
* @param {number} countryCallingCode the country calling code.
|
|
2305
|
-
* @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
|
|
2306
|
-
* phone number should be formatted into.
|
|
2307
|
-
* @param {string} formattedNationalNumber
|
|
2308
|
-
* @param {string} formattedExtension
|
|
2309
|
-
* @return {string} the formatted phone number.
|
|
2310
|
-
* @private
|
|
2311
|
-
*/
|
|
2312
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
2313
|
-
prefixNumberWithCountryCallingCode_ = function(countryCallingCode,
|
|
2314
|
-
numberFormat,
|
|
2315
|
-
formattedNationalNumber,
|
|
2316
|
-
formattedExtension) {
|
|
2317
|
-
|
|
2318
|
-
switch (numberFormat) {
|
|
2319
|
-
case i18n.phonenumbers.PhoneNumberFormat.E164:
|
|
2320
|
-
return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
|
|
2321
|
-
formattedNationalNumber + formattedExtension;
|
|
2322
|
-
case i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL:
|
|
2323
|
-
return i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
|
|
2324
|
-
' ' + formattedNationalNumber + formattedExtension;
|
|
2325
|
-
case i18n.phonenumbers.PhoneNumberFormat.RFC3966:
|
|
2326
|
-
return i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_ +
|
|
2327
|
-
i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN + countryCallingCode +
|
|
2328
|
-
'-' + formattedNationalNumber + formattedExtension;
|
|
2329
|
-
case i18n.phonenumbers.PhoneNumberFormat.NATIONAL:
|
|
2330
|
-
default:
|
|
2331
|
-
return formattedNationalNumber + formattedExtension;
|
|
2332
|
-
}
|
|
2333
|
-
};
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
/**
|
|
2337
|
-
* Note in some regions, the national number can be written in two completely
|
|
2338
|
-
* different ways depending on whether it forms part of the NATIONAL format or
|
|
2339
|
-
* INTERNATIONAL format. The numberFormat parameter here is used to specify
|
|
2340
|
-
* which format to use for those cases. If a carrierCode is specified, this will
|
|
2341
|
-
* be inserted into the formatted string to replace $CC.
|
|
2342
|
-
*
|
|
2343
|
-
* @param {string} number a string of characters representing a phone number.
|
|
2344
|
-
* @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
|
|
2345
|
-
* region that we think this number is from.
|
|
2346
|
-
* @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
|
|
2347
|
-
* phone number should be formatted into.
|
|
2348
|
-
* @param {string=} opt_carrierCode
|
|
2349
|
-
* @return {string} the formatted phone number.
|
|
2350
|
-
* @private
|
|
2351
|
-
*/
|
|
2352
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsn_ =
|
|
2353
|
-
function(number, metadata, numberFormat, opt_carrierCode) {
|
|
2354
|
-
|
|
2355
|
-
/** @type {Array.<i18n.phonenumbers.NumberFormat>} */
|
|
2356
|
-
var intlNumberFormats = metadata.intlNumberFormatArray();
|
|
2357
|
-
// When the intlNumberFormats exists, we use that to format national number
|
|
2358
|
-
// for the INTERNATIONAL format instead of using the numberDesc.numberFormats.
|
|
2359
|
-
/** @type {Array.<i18n.phonenumbers.NumberFormat>} */
|
|
2360
|
-
var availableFormats =
|
|
2361
|
-
(intlNumberFormats.length == 0 ||
|
|
2362
|
-
numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL) ?
|
|
2363
|
-
metadata.numberFormatArray() : metadata.intlNumberFormatArray();
|
|
2364
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
2365
|
-
var formattingPattern = this.chooseFormattingPatternForNumber_(
|
|
2366
|
-
availableFormats, number);
|
|
2367
|
-
return (formattingPattern == null) ?
|
|
2368
|
-
number :
|
|
2369
|
-
this.formatNsnUsingPattern_(number, formattingPattern,
|
|
2370
|
-
numberFormat, opt_carrierCode);
|
|
2371
|
-
};
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
/**
|
|
2375
|
-
* @param {Array.<i18n.phonenumbers.NumberFormat>} availableFormats the
|
|
2376
|
-
* available formats the phone number could be formatted into.
|
|
2377
|
-
* @param {string} nationalNumber a string of characters representing a phone
|
|
2378
|
-
* number.
|
|
2379
|
-
* @return {i18n.phonenumbers.NumberFormat}
|
|
2380
|
-
* @private
|
|
2381
|
-
*/
|
|
2382
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.chooseFormattingPatternForNumber_ =
|
|
2383
|
-
function(availableFormats, nationalNumber) {
|
|
2384
|
-
|
|
2385
|
-
/** @type {i18n.phonenumbers.NumberFormat} */
|
|
2386
|
-
var numFormat;
|
|
2387
|
-
/** @type {number} */
|
|
2388
|
-
var l = availableFormats.length;
|
|
2389
|
-
for (var i = 0; i < l; ++i) {
|
|
2390
|
-
numFormat = availableFormats[i];
|
|
2391
|
-
/** @type {number} */
|
|
2392
|
-
var size = numFormat.leadingDigitsPatternCount();
|
|
2393
|
-
if (size == 0 ||
|
|
2394
|
-
// We always use the last leading_digits_pattern, as it is the most
|
|
2395
|
-
// detailed.
|
|
2396
|
-
nationalNumber
|
|
2397
|
-
.search(numFormat.getLeadingDigitsPattern(size - 1)) == 0) {
|
|
2398
|
-
/** @type {!RegExp} */
|
|
2399
|
-
var patternToMatch = new RegExp(numFormat.getPattern());
|
|
2400
|
-
if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(patternToMatch,
|
|
2401
|
-
nationalNumber)) {
|
|
2402
|
-
return numFormat;
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
return null;
|
|
2407
|
-
};
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
/**
|
|
2411
|
-
* Note that carrierCode is optional - if null or an empty string, no carrier
|
|
2412
|
-
* code replacement will take place.
|
|
2413
|
-
*
|
|
2414
|
-
* @param {string} nationalNumber a string of characters representing a phone
|
|
2415
|
-
* number.
|
|
2416
|
-
* @param {i18n.phonenumbers.NumberFormat} formattingPattern the formatting rule
|
|
2417
|
-
* the phone number should be formatted into.
|
|
2418
|
-
* @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
|
|
2419
|
-
* phone number should be formatted into.
|
|
2420
|
-
* @param {string=} opt_carrierCode
|
|
2421
|
-
* @return {string} the formatted phone number.
|
|
2422
|
-
* @private
|
|
2423
|
-
*/
|
|
2424
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.formatNsnUsingPattern_ =
|
|
2425
|
-
function(nationalNumber, formattingPattern, numberFormat, opt_carrierCode) {
|
|
2426
|
-
|
|
2427
|
-
/** @type {string} */
|
|
2428
|
-
var numberFormatRule = formattingPattern.getFormatOrDefault();
|
|
2429
|
-
/** @type {!RegExp} */
|
|
2430
|
-
var patternToMatch = new RegExp(formattingPattern.getPattern());
|
|
2431
|
-
/** @type {string} */
|
|
2432
|
-
var domesticCarrierCodeFormattingRule =
|
|
2433
|
-
formattingPattern.getDomesticCarrierCodeFormattingRuleOrDefault();
|
|
2434
|
-
/** @type {string} */
|
|
2435
|
-
var formattedNationalNumber = '';
|
|
2436
|
-
if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
|
|
2437
|
-
opt_carrierCode != null && opt_carrierCode.length > 0 &&
|
|
2438
|
-
domesticCarrierCodeFormattingRule.length > 0) {
|
|
2439
|
-
// Replace the $CC in the formatting rule with the desired carrier code.
|
|
2440
|
-
/** @type {string} */
|
|
2441
|
-
var carrierCodeFormattingRule = domesticCarrierCodeFormattingRule
|
|
2442
|
-
.replace(i18n.phonenumbers.PhoneNumberUtil.CC_PATTERN_,
|
|
2443
|
-
opt_carrierCode);
|
|
2444
|
-
// Now replace the $FG in the formatting rule with the first group and
|
|
2445
|
-
// the carrier code combined in the appropriate way.
|
|
2446
|
-
numberFormatRule = numberFormatRule.replace(
|
|
2447
|
-
i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
|
|
2448
|
-
carrierCodeFormattingRule);
|
|
2449
|
-
formattedNationalNumber =
|
|
2450
|
-
nationalNumber.replace(patternToMatch, numberFormatRule);
|
|
2451
|
-
} else {
|
|
2452
|
-
// Use the national prefix formatting rule instead.
|
|
2453
|
-
/** @type {string} */
|
|
2454
|
-
var nationalPrefixFormattingRule =
|
|
2455
|
-
formattingPattern.getNationalPrefixFormattingRuleOrDefault();
|
|
2456
|
-
if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.NATIONAL &&
|
|
2457
|
-
nationalPrefixFormattingRule != null &&
|
|
2458
|
-
nationalPrefixFormattingRule.length > 0) {
|
|
2459
|
-
formattedNationalNumber = nationalNumber.replace(patternToMatch,
|
|
2460
|
-
numberFormatRule.replace(
|
|
2461
|
-
i18n.phonenumbers.PhoneNumberUtil.FIRST_GROUP_PATTERN_,
|
|
2462
|
-
nationalPrefixFormattingRule));
|
|
2463
|
-
} else {
|
|
2464
|
-
formattedNationalNumber =
|
|
2465
|
-
nationalNumber.replace(patternToMatch, numberFormatRule);
|
|
2466
|
-
}
|
|
2467
|
-
}
|
|
2468
|
-
if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
|
|
2469
|
-
// Strip any leading punctuation.
|
|
2470
|
-
formattedNationalNumber = formattedNationalNumber.replace(
|
|
2471
|
-
new RegExp('^' + i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_),
|
|
2472
|
-
'');
|
|
2473
|
-
// Replace the rest with a dash between each number group.
|
|
2474
|
-
formattedNationalNumber = formattedNationalNumber.replace(
|
|
2475
|
-
new RegExp(i18n.phonenumbers.PhoneNumberUtil.SEPARATOR_PATTERN_, 'g'),
|
|
2476
|
-
'-');
|
|
2477
|
-
}
|
|
2478
|
-
return formattedNationalNumber;
|
|
2479
|
-
};
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
/**
|
|
2483
|
-
* Gets a valid number for the specified region.
|
|
2484
|
-
*
|
|
2485
|
-
* @param {string} regionCode the region for which an example number is needed.
|
|
2486
|
-
* @return {i18n.phonenumbers.PhoneNumber} a valid fixed-line number for the
|
|
2487
|
-
* specified region. Returns null when the metadata does not contain such
|
|
2488
|
-
* information, or the region 001 is passed in. For 001 (representing non-
|
|
2489
|
-
* geographical numbers), call {@link #getExampleNumberForNonGeoEntity}
|
|
2490
|
-
* instead.
|
|
2491
|
-
*/
|
|
2492
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumber =
|
|
2493
|
-
function(regionCode) {
|
|
2494
|
-
|
|
2495
|
-
return this.getExampleNumberForType(regionCode,
|
|
2496
|
-
i18n.phonenumbers.PhoneNumberType.FIXED_LINE);
|
|
2497
|
-
};
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
/**
|
|
2501
|
-
* Gets a valid number for the specified region and number type.
|
|
2502
|
-
*
|
|
2503
|
-
* @param {string} regionCode the region for which an example number is needed.
|
|
2504
|
-
* @param {i18n.phonenumbers.PhoneNumberType} type the type of number that is
|
|
2505
|
-
* needed.
|
|
2506
|
-
* @return {i18n.phonenumbers.PhoneNumber} a valid number for the specified
|
|
2507
|
-
* region and type. Returns null when the metadata does not contain such
|
|
2508
|
-
* information or if an invalid region or region 001 was entered.
|
|
2509
|
-
* For 001 (representing non-geographical numbers), call
|
|
2510
|
-
* {@link #getExampleNumberForNonGeoEntity} instead.
|
|
2511
|
-
*/
|
|
2512
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForType =
|
|
2513
|
-
function(regionCode, type) {
|
|
2514
|
-
|
|
2515
|
-
// Check the region code is valid.
|
|
2516
|
-
if (!this.isValidRegionCode_(regionCode)) {
|
|
2517
|
-
return null;
|
|
2518
|
-
}
|
|
2519
|
-
/** @type {i18n.phonenumbers.PhoneNumberDesc} */
|
|
2520
|
-
var desc = this.getNumberDescByType_(
|
|
2521
|
-
this.getMetadataForRegion(regionCode), type);
|
|
2522
|
-
try {
|
|
2523
|
-
if (desc.hasExampleNumber()) {
|
|
2524
|
-
return this.parse(desc.getExampleNumberOrDefault(), regionCode);
|
|
2525
|
-
}
|
|
2526
|
-
} catch (e) {
|
|
2527
|
-
}
|
|
2528
|
-
return null;
|
|
2529
|
-
};
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
/**
|
|
2533
|
-
* Gets a valid number for the specified country calling code for a
|
|
2534
|
-
* non-geographical entity.
|
|
2535
|
-
*
|
|
2536
|
-
* @param {number} countryCallingCode the country calling code for a
|
|
2537
|
-
* non-geographical entity.
|
|
2538
|
-
* @return {i18n.phonenumbers.PhoneNumber} a valid number for the
|
|
2539
|
-
* non-geographical entity. Returns null when the metadata does not contain
|
|
2540
|
-
* such information, or the country calling code passed in does not belong
|
|
2541
|
-
* to a non-geographical entity.
|
|
2542
|
-
*/
|
|
2543
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getExampleNumberForNonGeoEntity =
|
|
2544
|
-
function(countryCallingCode) {
|
|
2545
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2546
|
-
var metadata =
|
|
2547
|
-
this.getMetadataForNonGeographicalRegion(countryCallingCode);
|
|
2548
|
-
if (metadata != null) {
|
|
2549
|
-
/** @type {i18n.phonenumbers.PhoneNumberDesc} */
|
|
2550
|
-
var desc = metadata.getGeneralDesc();
|
|
2551
|
-
try {
|
|
2552
|
-
if (desc.hasExampleNumber()) {
|
|
2553
|
-
return this.parse('+' + countryCallingCode + desc.getExampleNumber(),
|
|
2554
|
-
'ZZ');
|
|
2555
|
-
}
|
|
2556
|
-
} catch (e) {
|
|
2557
|
-
}
|
|
2558
|
-
}
|
|
2559
|
-
return null;
|
|
2560
|
-
};
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
/**
|
|
2564
|
-
* Gets the formatted extension of a phone number, if the phone number had an
|
|
2565
|
-
* extension specified. If not, it returns an empty string.
|
|
2566
|
-
*
|
|
2567
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the PhoneNumber that might have
|
|
2568
|
-
* an extension.
|
|
2569
|
-
* @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
|
|
2570
|
-
* region that we think this number is from.
|
|
2571
|
-
* @param {i18n.phonenumbers.PhoneNumberFormat} numberFormat the format the
|
|
2572
|
-
* phone number should be formatted into.
|
|
2573
|
-
* @return {string} the formatted extension if any.
|
|
2574
|
-
* @private
|
|
2575
|
-
*/
|
|
2576
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.maybeGetFormattedExtension_ =
|
|
2577
|
-
function(number, metadata, numberFormat) {
|
|
2578
|
-
|
|
2579
|
-
if (!number.hasExtension() || number.getExtension().length == 0) {
|
|
2580
|
-
return '';
|
|
2581
|
-
} else {
|
|
2582
|
-
if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.RFC3966) {
|
|
2583
|
-
return i18n.phonenumbers.PhoneNumberUtil.RFC3966_EXTN_PREFIX_ +
|
|
2584
|
-
number.getExtension();
|
|
2585
|
-
} else {
|
|
2586
|
-
if (metadata.hasPreferredExtnPrefix()) {
|
|
2587
|
-
return metadata.getPreferredExtnPrefix() +
|
|
2588
|
-
number.getExtensionOrDefault();
|
|
2589
|
-
} else {
|
|
2590
|
-
return i18n.phonenumbers.PhoneNumberUtil.DEFAULT_EXTN_PREFIX_ +
|
|
2591
|
-
number.getExtensionOrDefault();
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
}
|
|
2595
|
-
};
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
/**
|
|
2599
|
-
* @param {i18n.phonenumbers.PhoneMetadata} metadata
|
|
2600
|
-
* @param {i18n.phonenumbers.PhoneNumberType} type
|
|
2601
|
-
* @return {i18n.phonenumbers.PhoneNumberDesc}
|
|
2602
|
-
* @private
|
|
2603
|
-
*/
|
|
2604
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberDescByType_ =
|
|
2605
|
-
function(metadata, type) {
|
|
2606
|
-
|
|
2607
|
-
switch (type) {
|
|
2608
|
-
case i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE:
|
|
2609
|
-
return metadata.getPremiumRate();
|
|
2610
|
-
case i18n.phonenumbers.PhoneNumberType.TOLL_FREE:
|
|
2611
|
-
return metadata.getTollFree();
|
|
2612
|
-
case i18n.phonenumbers.PhoneNumberType.MOBILE:
|
|
2613
|
-
return metadata.getMobile();
|
|
2614
|
-
case i18n.phonenumbers.PhoneNumberType.FIXED_LINE:
|
|
2615
|
-
case i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE:
|
|
2616
|
-
return metadata.getFixedLine();
|
|
2617
|
-
case i18n.phonenumbers.PhoneNumberType.SHARED_COST:
|
|
2618
|
-
return metadata.getSharedCost();
|
|
2619
|
-
case i18n.phonenumbers.PhoneNumberType.VOIP:
|
|
2620
|
-
return metadata.getVoip();
|
|
2621
|
-
case i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER:
|
|
2622
|
-
return metadata.getPersonalNumber();
|
|
2623
|
-
case i18n.phonenumbers.PhoneNumberType.PAGER:
|
|
2624
|
-
return metadata.getPager();
|
|
2625
|
-
case i18n.phonenumbers.PhoneNumberType.UAN:
|
|
2626
|
-
return metadata.getUan();
|
|
2627
|
-
case i18n.phonenumbers.PhoneNumberType.VOICEMAIL:
|
|
2628
|
-
return metadata.getVoicemail();
|
|
2629
|
-
default:
|
|
2630
|
-
return metadata.getGeneralDesc();
|
|
2631
|
-
}
|
|
2632
|
-
};
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
/**
|
|
2636
|
-
* Gets the type of a phone number.
|
|
2637
|
-
*
|
|
2638
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
|
|
2639
|
-
* to know the type.
|
|
2640
|
-
* @return {i18n.phonenumbers.PhoneNumberType} the type of the phone number.
|
|
2641
|
-
*/
|
|
2642
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType =
|
|
2643
|
-
function(number) {
|
|
2644
|
-
|
|
2645
|
-
/** @type {?string} */
|
|
2646
|
-
var regionCode = this.getRegionCodeForNumber(number);
|
|
2647
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2648
|
-
var metadata = this.getMetadataForRegionOrCallingCode_(
|
|
2649
|
-
number.getCountryCodeOrDefault(), regionCode);
|
|
2650
|
-
if (metadata == null) {
|
|
2651
|
-
return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
|
|
2652
|
-
}
|
|
2653
|
-
/** @type {string} */
|
|
2654
|
-
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
|
|
2655
|
-
return this.getNumberTypeHelper_(nationalSignificantNumber, metadata);
|
|
2656
|
-
};
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
/**
|
|
2660
|
-
* @param {string} nationalNumber
|
|
2661
|
-
* @param {i18n.phonenumbers.PhoneMetadata} metadata
|
|
2662
|
-
* @return {i18n.phonenumbers.PhoneNumberType}
|
|
2663
|
-
* @private
|
|
2664
|
-
*/
|
|
2665
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberTypeHelper_ =
|
|
2666
|
-
function(nationalNumber, metadata) {
|
|
2667
|
-
|
|
2668
|
-
if (!this.isNumberMatchingDesc_(nationalNumber, metadata.getGeneralDesc())) {
|
|
2669
|
-
return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
|
|
2670
|
-
}
|
|
2671
|
-
|
|
2672
|
-
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPremiumRate())) {
|
|
2673
|
-
return i18n.phonenumbers.PhoneNumberType.PREMIUM_RATE;
|
|
2674
|
-
}
|
|
2675
|
-
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getTollFree())) {
|
|
2676
|
-
return i18n.phonenumbers.PhoneNumberType.TOLL_FREE;
|
|
2677
|
-
}
|
|
2678
|
-
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getSharedCost())) {
|
|
2679
|
-
return i18n.phonenumbers.PhoneNumberType.SHARED_COST;
|
|
2680
|
-
}
|
|
2681
|
-
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoip())) {
|
|
2682
|
-
return i18n.phonenumbers.PhoneNumberType.VOIP;
|
|
2683
|
-
}
|
|
2684
|
-
if (this.isNumberMatchingDesc_(nationalNumber,
|
|
2685
|
-
metadata.getPersonalNumber())) {
|
|
2686
|
-
return i18n.phonenumbers.PhoneNumberType.PERSONAL_NUMBER;
|
|
2687
|
-
}
|
|
2688
|
-
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getPager())) {
|
|
2689
|
-
return i18n.phonenumbers.PhoneNumberType.PAGER;
|
|
2690
|
-
}
|
|
2691
|
-
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getUan())) {
|
|
2692
|
-
return i18n.phonenumbers.PhoneNumberType.UAN;
|
|
2693
|
-
}
|
|
2694
|
-
if (this.isNumberMatchingDesc_(nationalNumber, metadata.getVoicemail())) {
|
|
2695
|
-
return i18n.phonenumbers.PhoneNumberType.VOICEMAIL;
|
|
2696
|
-
}
|
|
2697
|
-
|
|
2698
|
-
/** @type {boolean} */
|
|
2699
|
-
var isFixedLine = this.isNumberMatchingDesc_(nationalNumber, metadata
|
|
2700
|
-
.getFixedLine());
|
|
2701
|
-
if (isFixedLine) {
|
|
2702
|
-
if (metadata.getSameMobileAndFixedLinePattern()) {
|
|
2703
|
-
return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
|
|
2704
|
-
} else if (this.isNumberMatchingDesc_(nationalNumber,
|
|
2705
|
-
metadata.getMobile())) {
|
|
2706
|
-
return i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
|
|
2707
|
-
}
|
|
2708
|
-
return i18n.phonenumbers.PhoneNumberType.FIXED_LINE;
|
|
2709
|
-
}
|
|
2710
|
-
// Otherwise, test to see if the number is mobile. Only do this if certain
|
|
2711
|
-
// that the patterns for mobile and fixed line aren't the same.
|
|
2712
|
-
if (!metadata.getSameMobileAndFixedLinePattern() &&
|
|
2713
|
-
this.isNumberMatchingDesc_(nationalNumber, metadata.getMobile())) {
|
|
2714
|
-
return i18n.phonenumbers.PhoneNumberType.MOBILE;
|
|
2715
|
-
}
|
|
2716
|
-
return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
|
|
2717
|
-
};
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
/**
|
|
2721
|
-
* Returns the metadata for the given region code or {@code null} if the region
|
|
2722
|
-
* code is invalid or unknown.
|
|
2723
|
-
*
|
|
2724
|
-
* @param {?string} regionCode
|
|
2725
|
-
* @return {i18n.phonenumbers.PhoneMetadata}
|
|
2726
|
-
*/
|
|
2727
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getMetadataForRegion =
|
|
2728
|
-
function(regionCode) {
|
|
2729
|
-
|
|
2730
|
-
if (regionCode == null) {
|
|
2731
|
-
return null;
|
|
2732
|
-
}
|
|
2733
|
-
regionCode = regionCode.toUpperCase();
|
|
2734
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2735
|
-
var metadata = this.regionToMetadataMap[regionCode];
|
|
2736
|
-
if (metadata == null) {
|
|
2737
|
-
/** @type {goog.proto2.PbLiteSerializer} */
|
|
2738
|
-
var serializer = new goog.proto2.PbLiteSerializer();
|
|
2739
|
-
/** @type {Array} */
|
|
2740
|
-
var metadataSerialized =
|
|
2741
|
-
i18n.phonenumbers.metadata.countryToMetadata[regionCode];
|
|
2742
|
-
if (metadataSerialized == null) {
|
|
2743
|
-
return null;
|
|
2744
|
-
}
|
|
2745
|
-
metadata = /** @type {i18n.phonenumbers.PhoneMetadata} */ (
|
|
2746
|
-
serializer.deserialize(i18n.phonenumbers.PhoneMetadata.getDescriptor(),
|
|
2747
|
-
metadataSerialized));
|
|
2748
|
-
this.regionToMetadataMap[regionCode] = metadata;
|
|
2749
|
-
}
|
|
2750
|
-
return metadata;
|
|
2751
|
-
};
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
/**
|
|
2755
|
-
* @param {number} countryCallingCode
|
|
2756
|
-
* @return {i18n.phonenumbers.PhoneMetadata}
|
|
2757
|
-
*/
|
|
2758
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
2759
|
-
getMetadataForNonGeographicalRegion = function(countryCallingCode) {
|
|
2760
|
-
|
|
2761
|
-
return this.getMetadataForRegion('' + countryCallingCode);
|
|
2762
|
-
};
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
/**
|
|
2766
|
-
* @param {string} nationalNumber
|
|
2767
|
-
* @param {i18n.phonenumbers.PhoneNumberDesc} numberDesc
|
|
2768
|
-
* @return {boolean}
|
|
2769
|
-
* @private
|
|
2770
|
-
*/
|
|
2771
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatchingDesc_ =
|
|
2772
|
-
function(nationalNumber, numberDesc) {
|
|
2773
|
-
|
|
2774
|
-
return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
2775
|
-
numberDesc.getPossibleNumberPatternOrDefault(), nationalNumber) &&
|
|
2776
|
-
i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
2777
|
-
numberDesc.getNationalNumberPatternOrDefault(), nationalNumber);
|
|
2778
|
-
};
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
/**
|
|
2782
|
-
* Tests whether a phone number matches a valid pattern. Note this doesn't
|
|
2783
|
-
* verify the number is actually in use, which is impossible to tell by just
|
|
2784
|
-
* looking at a number itself.
|
|
2785
|
-
*
|
|
2786
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
|
|
2787
|
-
* to validate.
|
|
2788
|
-
* @return {boolean} a boolean that indicates whether the number is of a valid
|
|
2789
|
-
* pattern.
|
|
2790
|
-
*/
|
|
2791
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
|
|
2792
|
-
/** @type {?string} */
|
|
2793
|
-
var regionCode = this.getRegionCodeForNumber(number);
|
|
2794
|
-
return this.isValidNumberForRegion(number, regionCode);
|
|
2795
|
-
};
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
/**
|
|
2799
|
-
* Tests whether a phone number is valid for a certain region. Note this doesn't
|
|
2800
|
-
* verify the number is actually in use, which is impossible to tell by just
|
|
2801
|
-
* looking at a number itself. If the country calling code is not the same as
|
|
2802
|
-
* the country calling code for the region, this immediately exits with false.
|
|
2803
|
-
* After this, the specific number pattern rules for the region are examined.
|
|
2804
|
-
* This is useful for determining for example whether a particular number is
|
|
2805
|
-
* valid for Canada, rather than just a valid NANPA number.
|
|
2806
|
-
* Warning: In most cases, you want to use {@link #isValidNumber} instead. For
|
|
2807
|
-
* example, this method will mark numbers from British Crown dependencies such
|
|
2808
|
-
* as the Isle of Man as invalid for the region "GB" (United Kingdom), since it
|
|
2809
|
-
* has its own region code, "IM", which may be undesirable.
|
|
2810
|
-
*
|
|
2811
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
|
|
2812
|
-
* to validate.
|
|
2813
|
-
* @param {?string} regionCode the region that we want to validate the phone
|
|
2814
|
-
* number for.
|
|
2815
|
-
* @return {boolean} a boolean that indicates whether the number is of a valid
|
|
2816
|
-
* pattern.
|
|
2817
|
-
*/
|
|
2818
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumberForRegion =
|
|
2819
|
-
function(number, regionCode) {
|
|
2820
|
-
|
|
2821
|
-
/** @type {number} */
|
|
2822
|
-
var countryCode = number.getCountryCodeOrDefault();
|
|
2823
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2824
|
-
var metadata =
|
|
2825
|
-
this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
|
|
2826
|
-
if (metadata == null ||
|
|
2827
|
-
(i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY !=
|
|
2828
|
-
regionCode &&
|
|
2829
|
-
countryCode != this.getCountryCodeForValidRegion_(regionCode))) {
|
|
2830
|
-
// Either the region code was invalid, or the country calling code for this
|
|
2831
|
-
// number does not match that of the region code.
|
|
2832
|
-
return false;
|
|
2833
|
-
}
|
|
2834
|
-
/** @type {string} */
|
|
2835
|
-
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
|
|
2836
|
-
|
|
2837
|
-
return this.getNumberTypeHelper_(nationalSignificantNumber, metadata) !=
|
|
2838
|
-
i18n.phonenumbers.PhoneNumberType.UNKNOWN;
|
|
2839
|
-
};
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
/**
|
|
2843
|
-
* Returns the region where a phone number is from. This could be used for
|
|
2844
|
-
* geocoding at the region level.
|
|
2845
|
-
*
|
|
2846
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone number whose origin
|
|
2847
|
-
* we want to know.
|
|
2848
|
-
* @return {?string} the region where the phone number is from, or null
|
|
2849
|
-
* if no region matches this calling code.
|
|
2850
|
-
*/
|
|
2851
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForNumber =
|
|
2852
|
-
function(number) {
|
|
2853
|
-
|
|
2854
|
-
if (number == null) {
|
|
2855
|
-
return null;
|
|
2856
|
-
}
|
|
2857
|
-
/** @type {number} */
|
|
2858
|
-
var countryCode = number.getCountryCodeOrDefault();
|
|
2859
|
-
/** @type {Array.<string>} */
|
|
2860
|
-
var regions =
|
|
2861
|
-
i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCode];
|
|
2862
|
-
if (regions == null) {
|
|
2863
|
-
return null;
|
|
2864
|
-
}
|
|
2865
|
-
if (regions.length == 1) {
|
|
2866
|
-
return regions[0];
|
|
2867
|
-
} else {
|
|
2868
|
-
return this.getRegionCodeForNumberFromRegionList_(number, regions);
|
|
2869
|
-
}
|
|
2870
|
-
};
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
/**
|
|
2874
|
-
* @param {i18n.phonenumbers.PhoneNumber} number
|
|
2875
|
-
* @param {Array.<string>} regionCodes
|
|
2876
|
-
* @return {?string}
|
|
2877
|
-
* @private
|
|
2878
|
-
*/
|
|
2879
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
2880
|
-
getRegionCodeForNumberFromRegionList_ = function(number, regionCodes) {
|
|
2881
|
-
|
|
2882
|
-
/** @type {string} */
|
|
2883
|
-
var nationalNumber = this.getNationalSignificantNumber(number);
|
|
2884
|
-
/** @type {string} */
|
|
2885
|
-
var regionCode;
|
|
2886
|
-
/** @type {number} */
|
|
2887
|
-
var regionCodesLength = regionCodes.length;
|
|
2888
|
-
for (var i = 0; i < regionCodesLength; i++) {
|
|
2889
|
-
regionCode = regionCodes[i];
|
|
2890
|
-
// If leadingDigits is present, use this. Otherwise, do full validation.
|
|
2891
|
-
// Metadata cannot be null because the region codes come from the country
|
|
2892
|
-
// calling code map.
|
|
2893
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2894
|
-
var metadata = this.getMetadataForRegion(regionCode);
|
|
2895
|
-
if (metadata.hasLeadingDigits()) {
|
|
2896
|
-
if (nationalNumber.search(metadata.getLeadingDigits()) == 0) {
|
|
2897
|
-
return regionCode;
|
|
2898
|
-
}
|
|
2899
|
-
} else if (this.getNumberTypeHelper_(nationalNumber, metadata) !=
|
|
2900
|
-
i18n.phonenumbers.PhoneNumberType.UNKNOWN) {
|
|
2901
|
-
return regionCode;
|
|
2902
|
-
}
|
|
2903
|
-
}
|
|
2904
|
-
return null;
|
|
2905
|
-
};
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
/**
|
|
2909
|
-
* Returns the region code that matches the specific country calling code. In
|
|
2910
|
-
* the case of no region code being found, ZZ will be returned. In the case of
|
|
2911
|
-
* multiple regions, the one designated in the metadata as the 'main' region for
|
|
2912
|
-
* this calling code will be returned.
|
|
2913
|
-
*
|
|
2914
|
-
* @param {number} countryCallingCode the country calling code.
|
|
2915
|
-
* @return {string}
|
|
2916
|
-
*/
|
|
2917
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode =
|
|
2918
|
-
function(countryCallingCode) {
|
|
2919
|
-
|
|
2920
|
-
/** @type {Array.<string>} */
|
|
2921
|
-
var regionCodes =
|
|
2922
|
-
i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
|
|
2923
|
-
return regionCodes == null ?
|
|
2924
|
-
i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_ : regionCodes[0];
|
|
2925
|
-
};
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
/**
|
|
2929
|
-
* Returns a list with the region codes that match the specific country calling
|
|
2930
|
-
* code. For non-geographical country calling codes, the region code 001 is
|
|
2931
|
-
* returned. Also, in the case of no region code being found, an empty list is
|
|
2932
|
-
* returned.
|
|
2933
|
-
*
|
|
2934
|
-
* @param {number} countryCallingCode the country calling code.
|
|
2935
|
-
* @return {Array.<string>}
|
|
2936
|
-
*/
|
|
2937
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodesForCountryCode =
|
|
2938
|
-
function(countryCallingCode) {
|
|
2939
|
-
|
|
2940
|
-
/** @type {Array.<string>} */
|
|
2941
|
-
var regionCodes =
|
|
2942
|
-
i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
|
|
2943
|
-
return regionCodes == null ? [] : regionCodes;
|
|
2944
|
-
};
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
/**
|
|
2948
|
-
* Returns the country calling code for a specific region. For example, this
|
|
2949
|
-
* would be 1 for the United States, and 64 for New Zealand.
|
|
2950
|
-
*
|
|
2951
|
-
* @param {?string} regionCode the region that we want to get the country
|
|
2952
|
-
* calling code for.
|
|
2953
|
-
* @return {number} the country calling code for the region denoted by
|
|
2954
|
-
* regionCode.
|
|
2955
|
-
*/
|
|
2956
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion =
|
|
2957
|
-
function(regionCode) {
|
|
2958
|
-
|
|
2959
|
-
if (!this.isValidRegionCode_(regionCode)) {
|
|
2960
|
-
return 0;
|
|
2961
|
-
}
|
|
2962
|
-
return this.getCountryCodeForValidRegion_(regionCode);
|
|
2963
|
-
};
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
/**
|
|
2967
|
-
* Returns the country calling code for a specific region. For example, this
|
|
2968
|
-
* would be 1 for the United States, and 64 for New Zealand. Assumes the region
|
|
2969
|
-
* is already valid.
|
|
2970
|
-
*
|
|
2971
|
-
* @param {?string} regionCode the region that we want to get the country
|
|
2972
|
-
* calling code for.
|
|
2973
|
-
* @return {number} the country calling code for the region denoted by
|
|
2974
|
-
* regionCode.
|
|
2975
|
-
* @throws {Error} if the region is invalid
|
|
2976
|
-
* @private
|
|
2977
|
-
*/
|
|
2978
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForValidRegion_ =
|
|
2979
|
-
function(regionCode) {
|
|
2980
|
-
|
|
2981
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
2982
|
-
var metadata = this.getMetadataForRegion(regionCode);
|
|
2983
|
-
if (metadata == null) {
|
|
2984
|
-
throw new Error('Invalid region code: ' + regionCode);
|
|
2985
|
-
}
|
|
2986
|
-
return metadata.getCountryCodeOrDefault();
|
|
2987
|
-
};
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
/**
|
|
2991
|
-
* Returns the national dialling prefix for a specific region. For example, this
|
|
2992
|
-
* would be 1 for the United States, and 0 for New Zealand. Set stripNonDigits
|
|
2993
|
-
* to true to strip symbols like '~' (which indicates a wait for a dialling
|
|
2994
|
-
* tone) from the prefix returned. If no national prefix is present, we return
|
|
2995
|
-
* null.
|
|
2996
|
-
*
|
|
2997
|
-
* <p>Warning: Do not use this method for do-your-own formatting - for some
|
|
2998
|
-
* regions, the national dialling prefix is used only for certain types of
|
|
2999
|
-
* numbers. Use the library's formatting functions to prefix the national prefix
|
|
3000
|
-
* when required.
|
|
3001
|
-
*
|
|
3002
|
-
* @param {?string} regionCode the region that we want to get the dialling
|
|
3003
|
-
* prefix for.
|
|
3004
|
-
* @param {boolean} stripNonDigits true to strip non-digits from the national
|
|
3005
|
-
* dialling prefix.
|
|
3006
|
-
* @return {?string} the dialling prefix for the region denoted by
|
|
3007
|
-
* regionCode.
|
|
3008
|
-
*/
|
|
3009
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function(
|
|
3010
|
-
regionCode, stripNonDigits) {
|
|
3011
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
3012
|
-
var metadata = this.getMetadataForRegion(regionCode);
|
|
3013
|
-
if (metadata == null) {
|
|
3014
|
-
return null;
|
|
3015
|
-
}
|
|
3016
|
-
/** @type {string} */
|
|
3017
|
-
var nationalPrefix = metadata.getNationalPrefixOrDefault();
|
|
3018
|
-
// If no national prefix was found, we return null.
|
|
3019
|
-
if (nationalPrefix.length == 0) {
|
|
3020
|
-
return null;
|
|
3021
|
-
}
|
|
3022
|
-
if (stripNonDigits) {
|
|
3023
|
-
// Note: if any other non-numeric symbols are ever used in national
|
|
3024
|
-
// prefixes, these would have to be removed here as well.
|
|
3025
|
-
nationalPrefix = nationalPrefix.replace('~', '');
|
|
3026
|
-
}
|
|
3027
|
-
return nationalPrefix;
|
|
3028
|
-
};
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
/**
|
|
3032
|
-
* Checks if this is a region under the North American Numbering Plan
|
|
3033
|
-
* Administration (NANPA).
|
|
3034
|
-
*
|
|
3035
|
-
* @param {?string} regionCode the ISO 3166-1 two-letter region code.
|
|
3036
|
-
* @return {boolean} true if regionCode is one of the regions under NANPA.
|
|
3037
|
-
*/
|
|
3038
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry =
|
|
3039
|
-
function(regionCode) {
|
|
3040
|
-
|
|
3041
|
-
return regionCode != null && goog.array.contains(
|
|
3042
|
-
i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[
|
|
3043
|
-
i18n.phonenumbers.PhoneNumberUtil.NANPA_COUNTRY_CODE_],
|
|
3044
|
-
regionCode.toUpperCase());
|
|
3045
|
-
};
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
/**
|
|
3049
|
-
* Checks whether countryCode represents the country calling code from a region
|
|
3050
|
-
* whose national significant number could contain a leading zero. An example of
|
|
3051
|
-
* such a region is Italy. Returns false if no metadata for the country is
|
|
3052
|
-
* found.
|
|
3053
|
-
*
|
|
3054
|
-
* @param {number} countryCallingCode the country calling code.
|
|
3055
|
-
* @return {boolean}
|
|
3056
|
-
*/
|
|
3057
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isLeadingZeroPossible =
|
|
3058
|
-
function(countryCallingCode) {
|
|
3059
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
3060
|
-
var mainMetadataForCallingCode = this.getMetadataForRegionOrCallingCode_(
|
|
3061
|
-
countryCallingCode,
|
|
3062
|
-
this.getRegionCodeForCountryCode(countryCallingCode));
|
|
3063
|
-
return mainMetadataForCallingCode != null &&
|
|
3064
|
-
mainMetadataForCallingCode.getLeadingZeroPossibleOrDefault();
|
|
3065
|
-
};
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
/**
|
|
3069
|
-
* Checks if the number is a valid vanity (alpha) number such as 800 MICROSOFT.
|
|
3070
|
-
* A valid vanity number will start with at least 3 digits and will have three
|
|
3071
|
-
* or more alpha characters. This does not do region-specific checks - to work
|
|
3072
|
-
* out if this number is actually valid for a region, it should be parsed and
|
|
3073
|
-
* methods such as {@link #isPossibleNumberWithReason} and
|
|
3074
|
-
* {@link #isValidNumber} should be used.
|
|
3075
|
-
*
|
|
3076
|
-
* @param {string} number the number that needs to be checked.
|
|
3077
|
-
* @return {boolean} true if the number is a valid vanity number.
|
|
3078
|
-
*/
|
|
3079
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isAlphaNumber = function(number) {
|
|
3080
|
-
if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(number)) {
|
|
3081
|
-
// Number is too short, or doesn't match the basic phone number pattern.
|
|
3082
|
-
return false;
|
|
3083
|
-
}
|
|
3084
|
-
/** @type {!goog.string.StringBuffer} */
|
|
3085
|
-
var strippedNumber = new goog.string.StringBuffer(number);
|
|
3086
|
-
this.maybeStripExtension(strippedNumber);
|
|
3087
|
-
return i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
3088
|
-
i18n.phonenumbers.PhoneNumberUtil.VALID_ALPHA_PHONE_PATTERN_,
|
|
3089
|
-
strippedNumber.toString());
|
|
3090
|
-
};
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
/**
|
|
3094
|
-
* Convenience wrapper around {@link #isPossibleNumberWithReason}. Instead of
|
|
3095
|
-
* returning the reason for failure, this method returns a boolean value.
|
|
3096
|
-
*
|
|
3097
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
|
|
3098
|
-
* checked.
|
|
3099
|
-
* @return {boolean} true if the number is possible.
|
|
3100
|
-
*/
|
|
3101
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumber =
|
|
3102
|
-
function(number) {
|
|
3103
|
-
|
|
3104
|
-
return this.isPossibleNumberWithReason(number) ==
|
|
3105
|
-
i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
|
|
3106
|
-
};
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
/**
|
|
3110
|
-
* Helper method to check a number against a particular pattern and determine
|
|
3111
|
-
* whether it matches, or is too short or too long. Currently, if a number
|
|
3112
|
-
* pattern suggests that numbers of length 7 and 10 are possible, and a number
|
|
3113
|
-
* in between these possible lengths is entered, such as of length 8, this will
|
|
3114
|
-
* return TOO_LONG.
|
|
3115
|
-
*
|
|
3116
|
-
* @param {string} numberPattern
|
|
3117
|
-
* @param {string} number
|
|
3118
|
-
* @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult}
|
|
3119
|
-
* @private
|
|
3120
|
-
*/
|
|
3121
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.testNumberLengthAgainstPattern_ =
|
|
3122
|
-
function(numberPattern, number) {
|
|
3123
|
-
if (i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(numberPattern,
|
|
3124
|
-
number)) {
|
|
3125
|
-
return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.IS_POSSIBLE;
|
|
3126
|
-
}
|
|
3127
|
-
if (number.search(numberPattern) == 0) {
|
|
3128
|
-
return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG;
|
|
3129
|
-
} else {
|
|
3130
|
-
return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
|
|
3131
|
-
}
|
|
3132
|
-
};
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
/**
|
|
3136
|
-
* Helper method to check whether a number is too short to be a regular length
|
|
3137
|
-
* phone number in a region.
|
|
3138
|
-
*
|
|
3139
|
-
* @param {i18n.phonenumbers.PhoneMetadata} regionMetadata
|
|
3140
|
-
* @param {string} number
|
|
3141
|
-
* @return {boolean}
|
|
3142
|
-
* @private
|
|
3143
|
-
*/
|
|
3144
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isShorterThanPossibleNormalNumber_ =
|
|
3145
|
-
function(regionMetadata, number) {
|
|
3146
|
-
/** @type {string} */
|
|
3147
|
-
var possibleNumberPattern =
|
|
3148
|
-
regionMetadata.getGeneralDesc().getPossibleNumberPatternOrDefault();
|
|
3149
|
-
return this.testNumberLengthAgainstPattern_(possibleNumberPattern, number) ==
|
|
3150
|
-
i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT;
|
|
3151
|
-
};
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
/**
|
|
3155
|
-
* Check whether a phone number is a possible number. It provides a more lenient
|
|
3156
|
-
* check than {@link #isValidNumber} in the following sense:
|
|
3157
|
-
* <ol>
|
|
3158
|
-
* <li>It only checks the length of phone numbers. In particular, it doesn't
|
|
3159
|
-
* check starting digits of the number.
|
|
3160
|
-
* <li>It doesn't attempt to figure out the type of the number, but uses general
|
|
3161
|
-
* rules which applies to all types of phone numbers in a region. Therefore, it
|
|
3162
|
-
* is much faster than isValidNumber.
|
|
3163
|
-
* <li>For fixed line numbers, many regions have the concept of area code, which
|
|
3164
|
-
* together with subscriber number constitute the national significant number.
|
|
3165
|
-
* It is sometimes okay to dial the subscriber number only when dialing in the
|
|
3166
|
-
* same area. This function will return true if the subscriber-number-only
|
|
3167
|
-
* version is passed in. On the other hand, because isValidNumber validates
|
|
3168
|
-
* using information on both starting digits (for fixed line numbers, that would
|
|
3169
|
-
* most likely be area codes) and length (obviously includes the length of area
|
|
3170
|
-
* codes for fixed line numbers), it will return false for the
|
|
3171
|
-
* subscriber-number-only version.
|
|
3172
|
-
* </ol>
|
|
3173
|
-
*
|
|
3174
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the number that needs to be
|
|
3175
|
-
* checked.
|
|
3176
|
-
* @return {i18n.phonenumbers.PhoneNumberUtil.ValidationResult} a
|
|
3177
|
-
* ValidationResult object which indicates whether the number is possible.
|
|
3178
|
-
*/
|
|
3179
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason =
|
|
3180
|
-
function(number) {
|
|
3181
|
-
|
|
3182
|
-
/** @type {string} */
|
|
3183
|
-
var nationalNumber = this.getNationalSignificantNumber(number);
|
|
3184
|
-
/** @type {number} */
|
|
3185
|
-
var countryCode = number.getCountryCodeOrDefault();
|
|
3186
|
-
// Note: For Russian Fed and NANPA numbers, we just use the rules from the
|
|
3187
|
-
// default region (US or Russia) since the getRegionCodeForNumber will not
|
|
3188
|
-
// work if the number is possible but not valid. This would need to be
|
|
3189
|
-
// revisited if the possible number pattern ever differed between various
|
|
3190
|
-
// regions within those plans.
|
|
3191
|
-
if (!this.hasValidCountryCallingCode_(countryCode)) {
|
|
3192
|
-
return i18n.phonenumbers.PhoneNumberUtil.ValidationResult
|
|
3193
|
-
.INVALID_COUNTRY_CODE;
|
|
3194
|
-
}
|
|
3195
|
-
/** @type {string} */
|
|
3196
|
-
var regionCode = this.getRegionCodeForCountryCode(countryCode);
|
|
3197
|
-
// Metadata cannot be null because the country calling code is valid.
|
|
3198
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
3199
|
-
var metadata =
|
|
3200
|
-
this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
|
|
3201
|
-
/** @type {string} */
|
|
3202
|
-
var possibleNumberPattern =
|
|
3203
|
-
metadata.getGeneralDesc().getPossibleNumberPatternOrDefault();
|
|
3204
|
-
return this.testNumberLengthAgainstPattern_(possibleNumberPattern,
|
|
3205
|
-
nationalNumber);
|
|
3206
|
-
};
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
/**
|
|
3210
|
-
* Check whether a phone number is a possible number given a number in the form
|
|
3211
|
-
* of a string, and the region where the number could be dialed from. It
|
|
3212
|
-
* provides a more lenient check than {@link #isValidNumber}. See
|
|
3213
|
-
* {@link #isPossibleNumber} for details.
|
|
3214
|
-
*
|
|
3215
|
-
* <p>This method first parses the number, then invokes
|
|
3216
|
-
* {@link #isPossibleNumber} with the resultant PhoneNumber object.
|
|
3217
|
-
*
|
|
3218
|
-
* @param {string} number the number that needs to be checked, in the form of a
|
|
3219
|
-
* string.
|
|
3220
|
-
* @param {string} regionDialingFrom the region that we are expecting the number
|
|
3221
|
-
* to be dialed from.
|
|
3222
|
-
* Note this is different from the region where the number belongs.
|
|
3223
|
-
* For example, the number +1 650 253 0000 is a number that belongs to US.
|
|
3224
|
-
* When written in this form, it can be dialed from any region. When it is
|
|
3225
|
-
* written as 00 1 650 253 0000, it can be dialed from any region which uses
|
|
3226
|
-
* an international dialling prefix of 00. When it is written as
|
|
3227
|
-
* 650 253 0000, it can only be dialed from within the US, and when written
|
|
3228
|
-
* as 253 0000, it can only be dialed from within a smaller area in the US
|
|
3229
|
-
* (Mountain View, CA, to be more specific).
|
|
3230
|
-
* @return {boolean} true if the number is possible.
|
|
3231
|
-
*/
|
|
3232
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberString =
|
|
3233
|
-
function(number, regionDialingFrom) {
|
|
3234
|
-
|
|
3235
|
-
try {
|
|
3236
|
-
return this.isPossibleNumber(this.parse(number, regionDialingFrom));
|
|
3237
|
-
} catch (e) {
|
|
3238
|
-
return false;
|
|
3239
|
-
}
|
|
3240
|
-
};
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
/**
|
|
3244
|
-
* Attempts to extract a valid number from a phone number that is too long to be
|
|
3245
|
-
* valid, and resets the PhoneNumber object passed in to that valid version. If
|
|
3246
|
-
* no valid number could be extracted, the PhoneNumber object passed in will not
|
|
3247
|
-
* be modified.
|
|
3248
|
-
* @param {i18n.phonenumbers.PhoneNumber} number a PhoneNumber object which
|
|
3249
|
-
* contains a number that is too long to be valid.
|
|
3250
|
-
* @return {boolean} true if a valid phone number can be successfully extracted.
|
|
3251
|
-
*/
|
|
3252
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.truncateTooLongNumber =
|
|
3253
|
-
function(number) {
|
|
3254
|
-
|
|
3255
|
-
if (this.isValidNumber(number)) {
|
|
3256
|
-
return true;
|
|
3257
|
-
}
|
|
3258
|
-
/** @type {i18n.phonenumbers.PhoneNumber} */
|
|
3259
|
-
var numberCopy = number.clone();
|
|
3260
|
-
/** @type {number} */
|
|
3261
|
-
var nationalNumber = number.getNationalNumberOrDefault();
|
|
3262
|
-
do {
|
|
3263
|
-
nationalNumber = Math.floor(nationalNumber / 10);
|
|
3264
|
-
numberCopy.setNationalNumber(nationalNumber);
|
|
3265
|
-
if (nationalNumber == 0 ||
|
|
3266
|
-
this.isPossibleNumberWithReason(numberCopy) ==
|
|
3267
|
-
i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT) {
|
|
3268
|
-
return false;
|
|
3269
|
-
}
|
|
3270
|
-
} while (!this.isValidNumber(numberCopy));
|
|
3271
|
-
number.setNationalNumber(nationalNumber);
|
|
3272
|
-
return true;
|
|
3273
|
-
};
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
/**
|
|
3277
|
-
* Extracts country calling code from fullNumber, returns it and places the
|
|
3278
|
-
* remaining number in nationalNumber. It assumes that the leading plus sign or
|
|
3279
|
-
* IDD has already been removed. Returns 0 if fullNumber doesn't start with a
|
|
3280
|
-
* valid country calling code, and leaves nationalNumber unmodified.
|
|
3281
|
-
*
|
|
3282
|
-
* @param {!goog.string.StringBuffer} fullNumber
|
|
3283
|
-
* @param {!goog.string.StringBuffer} nationalNumber
|
|
3284
|
-
* @return {number}
|
|
3285
|
-
*/
|
|
3286
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.extractCountryCode =
|
|
3287
|
-
function(fullNumber, nationalNumber) {
|
|
3288
|
-
|
|
3289
|
-
/** @type {string} */
|
|
3290
|
-
var fullNumberStr = fullNumber.toString();
|
|
3291
|
-
if ((fullNumberStr.length == 0) || (fullNumberStr.charAt(0) == '0')) {
|
|
3292
|
-
// Country codes do not begin with a '0'.
|
|
3293
|
-
return 0;
|
|
3294
|
-
}
|
|
3295
|
-
/** @type {number} */
|
|
3296
|
-
var potentialCountryCode;
|
|
3297
|
-
/** @type {number} */
|
|
3298
|
-
var numberLength = fullNumberStr.length;
|
|
3299
|
-
for (var i = 1;
|
|
3300
|
-
i <= i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_COUNTRY_CODE_ &&
|
|
3301
|
-
i <= numberLength; ++i) {
|
|
3302
|
-
potentialCountryCode = parseInt(fullNumberStr.substring(0, i), 10);
|
|
3303
|
-
if (potentialCountryCode in
|
|
3304
|
-
i18n.phonenumbers.metadata.countryCodeToRegionCodeMap) {
|
|
3305
|
-
nationalNumber.append(fullNumberStr.substring(i));
|
|
3306
|
-
return potentialCountryCode;
|
|
3307
|
-
}
|
|
3308
|
-
}
|
|
3309
|
-
return 0;
|
|
3310
|
-
};
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
/**
|
|
3314
|
-
* Tries to extract a country calling code from a number. This method will
|
|
3315
|
-
* return zero if no country calling code is considered to be present. Country
|
|
3316
|
-
* calling codes are extracted in the following ways:
|
|
3317
|
-
* <ul>
|
|
3318
|
-
* <li>by stripping the international dialing prefix of the region the person is
|
|
3319
|
-
* dialing from, if this is present in the number, and looking at the next
|
|
3320
|
-
* digits
|
|
3321
|
-
* <li>by stripping the '+' sign if present and then looking at the next digits
|
|
3322
|
-
* <li>by comparing the start of the number and the country calling code of the
|
|
3323
|
-
* default region. If the number is not considered possible for the numbering
|
|
3324
|
-
* plan of the default region initially, but starts with the country calling
|
|
3325
|
-
* code of this region, validation will be reattempted after stripping this
|
|
3326
|
-
* country calling code. If this number is considered a possible number, then
|
|
3327
|
-
* the first digits will be considered the country calling code and removed as
|
|
3328
|
-
* such.
|
|
3329
|
-
* </ul>
|
|
3330
|
-
*
|
|
3331
|
-
* It will throw a i18n.phonenumbers.Error if the number starts with a '+' but
|
|
3332
|
-
* the country calling code supplied after this does not match that of any known
|
|
3333
|
-
* region.
|
|
3334
|
-
*
|
|
3335
|
-
* @param {string} number non-normalized telephone number that we wish to
|
|
3336
|
-
* extract a country calling code from - may begin with '+'.
|
|
3337
|
-
* @param {i18n.phonenumbers.PhoneMetadata} defaultRegionMetadata metadata
|
|
3338
|
-
* about the region this number may be from.
|
|
3339
|
-
* @param {!goog.string.StringBuffer} nationalNumber a string buffer to store
|
|
3340
|
-
* the national significant number in, in the case that a country calling
|
|
3341
|
-
* code was extracted. The number is appended to any existing contents. If
|
|
3342
|
-
* no country calling code was extracted, this will be left unchanged.
|
|
3343
|
-
* @param {boolean} keepRawInput true if the country_code_source and
|
|
3344
|
-
* preferred_carrier_code fields of phoneNumber should be populated.
|
|
3345
|
-
* @param {i18n.phonenumbers.PhoneNumber} phoneNumber the PhoneNumber object
|
|
3346
|
-
* where the country_code and country_code_source need to be populated.
|
|
3347
|
-
* Note the country_code is always populated, whereas country_code_source is
|
|
3348
|
-
* only populated when keepCountryCodeSource is true.
|
|
3349
|
-
* @return {number} the country calling code extracted or 0 if none could be
|
|
3350
|
-
* extracted.
|
|
3351
|
-
* @throws {Error}
|
|
3352
|
-
*/
|
|
3353
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.maybeExtractCountryCode =
|
|
3354
|
-
function(number, defaultRegionMetadata, nationalNumber,
|
|
3355
|
-
keepRawInput, phoneNumber) {
|
|
3356
|
-
|
|
3357
|
-
if (number.length == 0) {
|
|
3358
|
-
return 0;
|
|
3359
|
-
}
|
|
3360
|
-
/** @type {!goog.string.StringBuffer} */
|
|
3361
|
-
var fullNumber = new goog.string.StringBuffer(number);
|
|
3362
|
-
// Set the default prefix to be something that will never match.
|
|
3363
|
-
/** @type {?string} */
|
|
3364
|
-
var possibleCountryIddPrefix;
|
|
3365
|
-
if (defaultRegionMetadata != null) {
|
|
3366
|
-
possibleCountryIddPrefix = defaultRegionMetadata.getInternationalPrefix();
|
|
3367
|
-
}
|
|
3368
|
-
if (possibleCountryIddPrefix == null) {
|
|
3369
|
-
possibleCountryIddPrefix = 'NonMatch';
|
|
3370
|
-
}
|
|
3371
|
-
|
|
3372
|
-
/** @type {i18n.phonenumbers.PhoneNumber.CountryCodeSource} */
|
|
3373
|
-
var countryCodeSource = this.maybeStripInternationalPrefixAndNormalize(
|
|
3374
|
-
fullNumber, possibleCountryIddPrefix);
|
|
3375
|
-
if (keepRawInput) {
|
|
3376
|
-
phoneNumber.setCountryCodeSource(countryCodeSource);
|
|
3377
|
-
}
|
|
3378
|
-
if (countryCodeSource !=
|
|
3379
|
-
i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY) {
|
|
3380
|
-
if (fullNumber.getLength() <=
|
|
3381
|
-
i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
|
|
3382
|
-
throw new Error(i18n.phonenumbers.Error.TOO_SHORT_AFTER_IDD);
|
|
3383
|
-
}
|
|
3384
|
-
/** @type {number} */
|
|
3385
|
-
var potentialCountryCode = this.extractCountryCode(fullNumber,
|
|
3386
|
-
nationalNumber);
|
|
3387
|
-
if (potentialCountryCode != 0) {
|
|
3388
|
-
phoneNumber.setCountryCode(potentialCountryCode);
|
|
3389
|
-
return potentialCountryCode;
|
|
3390
|
-
}
|
|
3391
|
-
|
|
3392
|
-
// If this fails, they must be using a strange country calling code that we
|
|
3393
|
-
// don't recognize, or that doesn't exist.
|
|
3394
|
-
throw new Error(i18n.phonenumbers.Error.INVALID_COUNTRY_CODE);
|
|
3395
|
-
} else if (defaultRegionMetadata != null) {
|
|
3396
|
-
// Check to see if the number starts with the country calling code for the
|
|
3397
|
-
// default region. If so, we remove the country calling code, and do some
|
|
3398
|
-
// checks on the validity of the number before and after.
|
|
3399
|
-
/** @type {number} */
|
|
3400
|
-
var defaultCountryCode = defaultRegionMetadata.getCountryCodeOrDefault();
|
|
3401
|
-
/** @type {string} */
|
|
3402
|
-
var defaultCountryCodeString = '' + defaultCountryCode;
|
|
3403
|
-
/** @type {string} */
|
|
3404
|
-
var normalizedNumber = fullNumber.toString();
|
|
3405
|
-
if (goog.string.startsWith(normalizedNumber, defaultCountryCodeString)) {
|
|
3406
|
-
/** @type {!goog.string.StringBuffer} */
|
|
3407
|
-
var potentialNationalNumber = new goog.string.StringBuffer(
|
|
3408
|
-
normalizedNumber.substring(defaultCountryCodeString.length));
|
|
3409
|
-
/** @type {i18n.phonenumbers.PhoneNumberDesc} */
|
|
3410
|
-
var generalDesc = defaultRegionMetadata.getGeneralDesc();
|
|
3411
|
-
/** @type {!RegExp} */
|
|
3412
|
-
var validNumberPattern =
|
|
3413
|
-
new RegExp(generalDesc.getNationalNumberPatternOrDefault());
|
|
3414
|
-
// Passing null since we don't need the carrier code.
|
|
3415
|
-
this.maybeStripNationalPrefixAndCarrierCode(
|
|
3416
|
-
potentialNationalNumber, defaultRegionMetadata, null);
|
|
3417
|
-
/** @type {string} */
|
|
3418
|
-
var potentialNationalNumberStr = potentialNationalNumber.toString();
|
|
3419
|
-
/** @type {string} */
|
|
3420
|
-
var possibleNumberPattern =
|
|
3421
|
-
generalDesc.getPossibleNumberPatternOrDefault();
|
|
3422
|
-
// If the number was not valid before but is valid now, or if it was too
|
|
3423
|
-
// long before, we consider the number with the country calling code
|
|
3424
|
-
// stripped to be a better result and keep that instead.
|
|
3425
|
-
if ((!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
3426
|
-
validNumberPattern, fullNumber.toString()) &&
|
|
3427
|
-
i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
3428
|
-
validNumberPattern, potentialNationalNumberStr)) ||
|
|
3429
|
-
this.testNumberLengthAgainstPattern_(possibleNumberPattern,
|
|
3430
|
-
fullNumber.toString()) ==
|
|
3431
|
-
i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG) {
|
|
3432
|
-
nationalNumber.append(potentialNationalNumberStr);
|
|
3433
|
-
if (keepRawInput) {
|
|
3434
|
-
phoneNumber.setCountryCodeSource(
|
|
3435
|
-
i18n.phonenumbers.PhoneNumber.CountryCodeSource
|
|
3436
|
-
.FROM_NUMBER_WITHOUT_PLUS_SIGN);
|
|
3437
|
-
}
|
|
3438
|
-
phoneNumber.setCountryCode(defaultCountryCode);
|
|
3439
|
-
return defaultCountryCode;
|
|
3440
|
-
}
|
|
3441
|
-
}
|
|
3442
|
-
}
|
|
3443
|
-
// No country calling code present.
|
|
3444
|
-
phoneNumber.setCountryCode(0);
|
|
3445
|
-
return 0;
|
|
3446
|
-
};
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
/**
|
|
3450
|
-
* Strips the IDD from the start of the number if present. Helper function used
|
|
3451
|
-
* by maybeStripInternationalPrefixAndNormalize.
|
|
3452
|
-
*
|
|
3453
|
-
* @param {!RegExp} iddPattern the regular expression for the international
|
|
3454
|
-
* prefix.
|
|
3455
|
-
* @param {!goog.string.StringBuffer} number the phone number that we wish to
|
|
3456
|
-
* strip any international dialing prefix from.
|
|
3457
|
-
* @return {boolean} true if an international prefix was present.
|
|
3458
|
-
* @private
|
|
3459
|
-
*/
|
|
3460
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.parsePrefixAsIdd_ =
|
|
3461
|
-
function(iddPattern, number) {
|
|
3462
|
-
|
|
3463
|
-
/** @type {string} */
|
|
3464
|
-
var numberStr = number.toString();
|
|
3465
|
-
if (numberStr.search(iddPattern) == 0) {
|
|
3466
|
-
/** @type {number} */
|
|
3467
|
-
var matchEnd = numberStr.match(iddPattern)[0].length;
|
|
3468
|
-
/** @type {Array.<string>} */
|
|
3469
|
-
var matchedGroups = numberStr.substring(matchEnd).match(
|
|
3470
|
-
i18n.phonenumbers.PhoneNumberUtil.CAPTURING_DIGIT_PATTERN);
|
|
3471
|
-
if (matchedGroups && matchedGroups[1] != null &&
|
|
3472
|
-
matchedGroups[1].length > 0) {
|
|
3473
|
-
/** @type {string} */
|
|
3474
|
-
var normalizedGroup =
|
|
3475
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeDigitsOnly(
|
|
3476
|
-
matchedGroups[1]);
|
|
3477
|
-
if (normalizedGroup == '0') {
|
|
3478
|
-
return false;
|
|
3479
|
-
}
|
|
3480
|
-
}
|
|
3481
|
-
number.clear();
|
|
3482
|
-
number.append(numberStr.substring(matchEnd));
|
|
3483
|
-
return true;
|
|
3484
|
-
}
|
|
3485
|
-
return false;
|
|
3486
|
-
};
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
/**
|
|
3490
|
-
* Strips any international prefix (such as +, 00, 011) present in the number
|
|
3491
|
-
* provided, normalizes the resulting number, and indicates if an international
|
|
3492
|
-
* prefix was present.
|
|
3493
|
-
*
|
|
3494
|
-
* @param {!goog.string.StringBuffer} number the non-normalized telephone number
|
|
3495
|
-
* that we wish to strip any international dialing prefix from.
|
|
3496
|
-
* @param {string} possibleIddPrefix the international direct dialing prefix
|
|
3497
|
-
* from the region we think this number may be dialed in.
|
|
3498
|
-
* @return {i18n.phonenumbers.PhoneNumber.CountryCodeSource} the corresponding
|
|
3499
|
-
* CountryCodeSource if an international dialing prefix could be removed
|
|
3500
|
-
* from the number, otherwise CountryCodeSource.FROM_DEFAULT_COUNTRY if
|
|
3501
|
-
* the number did not seem to be in international format.
|
|
3502
|
-
*/
|
|
3503
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
3504
|
-
maybeStripInternationalPrefixAndNormalize = function(number,
|
|
3505
|
-
possibleIddPrefix) {
|
|
3506
|
-
/** @type {string} */
|
|
3507
|
-
var numberStr = number.toString();
|
|
3508
|
-
if (numberStr.length == 0) {
|
|
3509
|
-
return i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
|
|
3510
|
-
}
|
|
3511
|
-
// Check to see if the number begins with one or more plus signs.
|
|
3512
|
-
if (i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
|
|
3513
|
-
.test(numberStr)) {
|
|
3514
|
-
numberStr = numberStr.replace(
|
|
3515
|
-
i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
|
|
3516
|
-
// Can now normalize the rest of the number since we've consumed the '+'
|
|
3517
|
-
// sign at the start.
|
|
3518
|
-
number.clear();
|
|
3519
|
-
number.append(i18n.phonenumbers.PhoneNumberUtil.normalize(numberStr));
|
|
3520
|
-
return i18n.phonenumbers.PhoneNumber.CountryCodeSource
|
|
3521
|
-
.FROM_NUMBER_WITH_PLUS_SIGN;
|
|
3522
|
-
}
|
|
3523
|
-
// Attempt to parse the first digits as an international prefix.
|
|
3524
|
-
/** @type {!RegExp} */
|
|
3525
|
-
var iddPattern = new RegExp(possibleIddPrefix);
|
|
3526
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(number);
|
|
3527
|
-
return this.parsePrefixAsIdd_(iddPattern, number) ?
|
|
3528
|
-
i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_IDD :
|
|
3529
|
-
i18n.phonenumbers.PhoneNumber.CountryCodeSource.FROM_DEFAULT_COUNTRY;
|
|
3530
|
-
};
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
/**
|
|
3534
|
-
* Strips any national prefix (such as 0, 1) present in the number provided.
|
|
3535
|
-
*
|
|
3536
|
-
* @param {!goog.string.StringBuffer} number the normalized telephone number
|
|
3537
|
-
* that we wish to strip any national dialing prefix from.
|
|
3538
|
-
* @param {i18n.phonenumbers.PhoneMetadata} metadata the metadata for the
|
|
3539
|
-
* region that we think this number is from.
|
|
3540
|
-
* @param {goog.string.StringBuffer} carrierCode a place to insert the carrier
|
|
3541
|
-
* code if one is extracted.
|
|
3542
|
-
* @return {boolean} true if a national prefix or carrier code (or both) could
|
|
3543
|
-
* be extracted.
|
|
3544
|
-
*/
|
|
3545
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.
|
|
3546
|
-
maybeStripNationalPrefixAndCarrierCode = function(number, metadata,
|
|
3547
|
-
carrierCode) {
|
|
3548
|
-
/** @type {string} */
|
|
3549
|
-
var numberStr = number.toString();
|
|
3550
|
-
/** @type {number} */
|
|
3551
|
-
var numberLength = numberStr.length;
|
|
3552
|
-
/** @type {?string} */
|
|
3553
|
-
var possibleNationalPrefix = metadata.getNationalPrefixForParsing();
|
|
3554
|
-
if (numberLength == 0 || possibleNationalPrefix == null ||
|
|
3555
|
-
possibleNationalPrefix.length == 0) {
|
|
3556
|
-
// Early return for numbers of zero length.
|
|
3557
|
-
return false;
|
|
3558
|
-
}
|
|
3559
|
-
// Attempt to parse the first digits as a national prefix.
|
|
3560
|
-
/** @type {!RegExp} */
|
|
3561
|
-
var prefixPattern = new RegExp('^(?:' + possibleNationalPrefix + ')');
|
|
3562
|
-
/** @type {Array.<string>} */
|
|
3563
|
-
var prefixMatcher = prefixPattern.exec(numberStr);
|
|
3564
|
-
if (prefixMatcher) {
|
|
3565
|
-
/** @type {!RegExp} */
|
|
3566
|
-
var nationalNumberRule = new RegExp(
|
|
3567
|
-
metadata.getGeneralDesc().getNationalNumberPatternOrDefault());
|
|
3568
|
-
// Check if the original number is viable.
|
|
3569
|
-
/** @type {boolean} */
|
|
3570
|
-
var isViableOriginalNumber =
|
|
3571
|
-
i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
3572
|
-
nationalNumberRule, numberStr);
|
|
3573
|
-
// prefixMatcher[numOfGroups] == null implies nothing was captured by the
|
|
3574
|
-
// capturing groups in possibleNationalPrefix; therefore, no transformation
|
|
3575
|
-
// is necessary, and we just remove the national prefix.
|
|
3576
|
-
/** @type {number} */
|
|
3577
|
-
var numOfGroups = prefixMatcher.length - 1;
|
|
3578
|
-
/** @type {?string} */
|
|
3579
|
-
var transformRule = metadata.getNationalPrefixTransformRule();
|
|
3580
|
-
/** @type {boolean} */
|
|
3581
|
-
var noTransform = transformRule == null || transformRule.length == 0 ||
|
|
3582
|
-
prefixMatcher[numOfGroups] == null ||
|
|
3583
|
-
prefixMatcher[numOfGroups].length == 0;
|
|
3584
|
-
if (noTransform) {
|
|
3585
|
-
// If the original number was viable, and the resultant number is not,
|
|
3586
|
-
// we return.
|
|
3587
|
-
if (isViableOriginalNumber &&
|
|
3588
|
-
!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
3589
|
-
nationalNumberRule,
|
|
3590
|
-
numberStr.substring(prefixMatcher[0].length))) {
|
|
3591
|
-
return false;
|
|
3592
|
-
}
|
|
3593
|
-
if (carrierCode != null &&
|
|
3594
|
-
numOfGroups > 0 && prefixMatcher[numOfGroups] != null) {
|
|
3595
|
-
carrierCode.append(prefixMatcher[1]);
|
|
3596
|
-
}
|
|
3597
|
-
number.set(numberStr.substring(prefixMatcher[0].length));
|
|
3598
|
-
return true;
|
|
3599
|
-
} else {
|
|
3600
|
-
// Check that the resultant number is still viable. If not, return. Check
|
|
3601
|
-
// this by copying the string buffer and making the transformation on the
|
|
3602
|
-
// copy first.
|
|
3603
|
-
/** @type {string} */
|
|
3604
|
-
var transformedNumber;
|
|
3605
|
-
transformedNumber = numberStr.replace(prefixPattern, transformRule);
|
|
3606
|
-
if (isViableOriginalNumber &&
|
|
3607
|
-
!i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_(
|
|
3608
|
-
nationalNumberRule, transformedNumber)) {
|
|
3609
|
-
return false;
|
|
3610
|
-
}
|
|
3611
|
-
if (carrierCode != null && numOfGroups > 0) {
|
|
3612
|
-
carrierCode.append(prefixMatcher[1]);
|
|
3613
|
-
}
|
|
3614
|
-
number.set(transformedNumber);
|
|
3615
|
-
return true;
|
|
3616
|
-
}
|
|
3617
|
-
}
|
|
3618
|
-
return false;
|
|
3619
|
-
};
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
/**
|
|
3623
|
-
* Strips any extension (as in, the part of the number dialled after the call is
|
|
3624
|
-
* connected, usually indicated with extn, ext, x or similar) from the end of
|
|
3625
|
-
* the number, and returns it.
|
|
3626
|
-
*
|
|
3627
|
-
* @param {!goog.string.StringBuffer} number the non-normalized telephone number
|
|
3628
|
-
* that we wish to strip the extension from.
|
|
3629
|
-
* @return {string} the phone extension.
|
|
3630
|
-
*/
|
|
3631
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.maybeStripExtension =
|
|
3632
|
-
function(number) {
|
|
3633
|
-
|
|
3634
|
-
/** @type {string} */
|
|
3635
|
-
var numberStr = number.toString();
|
|
3636
|
-
/** @type {number} */
|
|
3637
|
-
var mStart =
|
|
3638
|
-
numberStr.search(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
|
|
3639
|
-
// If we find a potential extension, and the number preceding this is a viable
|
|
3640
|
-
// number, we assume it is an extension.
|
|
3641
|
-
if (mStart >= 0 && i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
|
|
3642
|
-
numberStr.substring(0, mStart))) {
|
|
3643
|
-
// The numbers are captured into groups in the regular expression.
|
|
3644
|
-
/** @type {Array.<string>} */
|
|
3645
|
-
var matchedGroups =
|
|
3646
|
-
numberStr.match(i18n.phonenumbers.PhoneNumberUtil.EXTN_PATTERN_);
|
|
3647
|
-
/** @type {number} */
|
|
3648
|
-
var matchedGroupsLength = matchedGroups.length;
|
|
3649
|
-
for (var i = 1; i < matchedGroupsLength; ++i) {
|
|
3650
|
-
if (matchedGroups[i] != null && matchedGroups[i].length > 0) {
|
|
3651
|
-
// We go through the capturing groups until we find one that captured
|
|
3652
|
-
// some digits. If none did, then we will return the empty string.
|
|
3653
|
-
number.clear();
|
|
3654
|
-
number.append(numberStr.substring(0, mStart));
|
|
3655
|
-
return matchedGroups[i];
|
|
3656
|
-
}
|
|
3657
|
-
}
|
|
3658
|
-
}
|
|
3659
|
-
return '';
|
|
3660
|
-
};
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
/**
|
|
3664
|
-
* Checks to see that the region code used is valid, or if it is not valid, that
|
|
3665
|
-
* the number to parse starts with a + symbol so that we can attempt to infer
|
|
3666
|
-
* the region from the number.
|
|
3667
|
-
* @param {string} numberToParse number that we are attempting to parse.
|
|
3668
|
-
* @param {?string} defaultRegion region that we are expecting the number to be
|
|
3669
|
-
* from.
|
|
3670
|
-
* @return {boolean} false if it cannot use the region provided and the region
|
|
3671
|
-
* cannot be inferred.
|
|
3672
|
-
* @private
|
|
3673
|
-
*/
|
|
3674
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.checkRegionForParsing_ = function(
|
|
3675
|
-
numberToParse, defaultRegion) {
|
|
3676
|
-
// If the number is null or empty, we can't infer the region.
|
|
3677
|
-
return this.isValidRegionCode_(defaultRegion) ||
|
|
3678
|
-
(numberToParse != null && numberToParse.length > 0 &&
|
|
3679
|
-
i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_.test(
|
|
3680
|
-
numberToParse));
|
|
3681
|
-
};
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
/**
|
|
3685
|
-
* Parses a string and returns it as a phone number in proto buffer format. The
|
|
3686
|
-
* method is quite lenient and looks for a number in the input text (raw input)
|
|
3687
|
-
* and does not check whether the string is definitely only a phone number. To
|
|
3688
|
-
* do this, it ignores punctuation and white-space, as well as any text before
|
|
3689
|
-
* the number (e.g. a leading “Tel: ”) and trims the non-number bits. It will
|
|
3690
|
-
* accept a number in any format (E164, national, international etc), assuming
|
|
3691
|
-
* it can be interpreted with the defaultRegion supplied. It also attempts to
|
|
3692
|
-
* convert any alpha characters into digits if it thinks this is a vanity number
|
|
3693
|
-
* of the type "1800 MICROSOFT".
|
|
3694
|
-
*
|
|
3695
|
-
* This method will throw a {@link i18n.phonenumbers.Error} if the number is not
|
|
3696
|
-
* considered to be a possible number. Note that validation of whether the
|
|
3697
|
-
* number is actually a valid number for a particular region is not performed.
|
|
3698
|
-
* This can be done separately with {@link #isValidNumber}.
|
|
3699
|
-
*
|
|
3700
|
-
* @param {?string} numberToParse number that we are attempting to parse. This
|
|
3701
|
-
* can contain formatting such as +, ( and -, as well as a phone number
|
|
3702
|
-
* extension. It can also be provided in RFC3966 format.
|
|
3703
|
-
* @param {?string} defaultRegion region that we are expecting the number to be
|
|
3704
|
-
* from. This is only used if the number being parsed is not written in
|
|
3705
|
-
* international format. The country_code for the number in this case would
|
|
3706
|
-
* be stored as that of the default region supplied. If the number is
|
|
3707
|
-
* guaranteed to start with a '+' followed by the country calling code, then
|
|
3708
|
-
* 'ZZ' or null can be supplied.
|
|
3709
|
-
* @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
|
|
3710
|
-
* with the parsed number.
|
|
3711
|
-
* @throws {Error} if the string is not considered to be a
|
|
3712
|
-
* viable phone number (e.g. too few or too many digits) or if no default
|
|
3713
|
-
* region was supplied and the number is not in international format (does
|
|
3714
|
-
* not start with +).
|
|
3715
|
-
*/
|
|
3716
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.parse = function(numberToParse,
|
|
3717
|
-
defaultRegion) {
|
|
3718
|
-
return this.parseHelper_(numberToParse, defaultRegion, false, true);
|
|
3719
|
-
};
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
/**
|
|
3723
|
-
* Parses a string and returns it in proto buffer format. This method differs
|
|
3724
|
-
* from {@link #parse} in that it always populates the raw_input field of the
|
|
3725
|
-
* protocol buffer with numberToParse as well as the country_code_source field.
|
|
3726
|
-
*
|
|
3727
|
-
* @param {string} numberToParse number that we are attempting to parse. This
|
|
3728
|
-
* can contain formatting such as +, ( and -, as well as a phone number
|
|
3729
|
-
* extension.
|
|
3730
|
-
* @param {?string} defaultRegion region that we are expecting the number to be
|
|
3731
|
-
* from. This is only used if the number being parsed is not written in
|
|
3732
|
-
* international format. The country calling code for the number in this
|
|
3733
|
-
* case would be stored as that of the default region supplied.
|
|
3734
|
-
* @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
|
|
3735
|
-
* with the parsed number.
|
|
3736
|
-
* @throws {Error} if the string is not considered to be a
|
|
3737
|
-
* viable phone number or if no default region was supplied.
|
|
3738
|
-
*/
|
|
3739
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.parseAndKeepRawInput =
|
|
3740
|
-
function(numberToParse, defaultRegion) {
|
|
3741
|
-
|
|
3742
|
-
if (!this.isValidRegionCode_(defaultRegion)) {
|
|
3743
|
-
if (numberToParse.length > 0 && numberToParse.charAt(0) !=
|
|
3744
|
-
i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
|
|
3745
|
-
throw new Error(i18n.phonenumbers.Error.INVALID_COUNTRY_CODE);
|
|
3746
|
-
}
|
|
3747
|
-
}
|
|
3748
|
-
return this.parseHelper_(numberToParse, defaultRegion, true, true);
|
|
3749
|
-
};
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
/**
|
|
3753
|
-
* A helper function to set the values related to leading zeros in a
|
|
3754
|
-
* PhoneNumber.
|
|
3755
|
-
*
|
|
3756
|
-
* @param {string} nationalNumber the number we are parsing.
|
|
3757
|
-
* @param {i18n.phonenumbers.PhoneNumber} phoneNumber a phone number proto
|
|
3758
|
-
* buffer to fill in.
|
|
3759
|
-
* @private
|
|
3760
|
-
*/
|
|
3761
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.setItalianLeadingZerosForPhoneNumber_ =
|
|
3762
|
-
function(nationalNumber, phoneNumber) {
|
|
3763
|
-
if (nationalNumber.length > 1 && nationalNumber.charAt(0) == '0') {
|
|
3764
|
-
phoneNumber.setItalianLeadingZero(true);
|
|
3765
|
-
var numberOfLeadingZeros = 1;
|
|
3766
|
-
// Note that if the national number is all "0"s, the last "0" is not counted
|
|
3767
|
-
// as a leading zero.
|
|
3768
|
-
while (numberOfLeadingZeros < nationalNumber.length - 1 &&
|
|
3769
|
-
nationalNumber.charAt(numberOfLeadingZeros) == '0') {
|
|
3770
|
-
numberOfLeadingZeros++;
|
|
3771
|
-
}
|
|
3772
|
-
if (numberOfLeadingZeros != 1) {
|
|
3773
|
-
phoneNumber.setNumberOfLeadingZeros(numberOfLeadingZeros);
|
|
3774
|
-
}
|
|
3775
|
-
}
|
|
3776
|
-
};
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
/**
|
|
3780
|
-
* Parses a string and returns it in proto buffer format. This method is the
|
|
3781
|
-
* same as the public {@link #parse} method, with the exception that it allows
|
|
3782
|
-
* the default region to be null, for use by {@link #isNumberMatch}.
|
|
3783
|
-
*
|
|
3784
|
-
* @param {?string} numberToParse number that we are attempting to parse. This
|
|
3785
|
-
* can contain formatting such as +, ( and -, as well as a phone number
|
|
3786
|
-
* extension.
|
|
3787
|
-
* @param {?string} defaultRegion region that we are expecting the number to be
|
|
3788
|
-
* from. This is only used if the number being parsed is not written in
|
|
3789
|
-
* international format. The country calling code for the number in this
|
|
3790
|
-
* case would be stored as that of the default region supplied.
|
|
3791
|
-
* @param {boolean} keepRawInput whether to populate the raw_input field of the
|
|
3792
|
-
* phoneNumber with numberToParse.
|
|
3793
|
-
* @param {boolean} checkRegion should be set to false if it is permitted for
|
|
3794
|
-
* the default coregion to be null or unknown ('ZZ').
|
|
3795
|
-
* @return {i18n.phonenumbers.PhoneNumber} a phone number proto buffer filled
|
|
3796
|
-
* with the parsed number.
|
|
3797
|
-
* @throws {Error}
|
|
3798
|
-
* @private
|
|
3799
|
-
*/
|
|
3800
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ =
|
|
3801
|
-
function(numberToParse, defaultRegion, keepRawInput, checkRegion) {
|
|
3802
|
-
|
|
3803
|
-
if (numberToParse == null) {
|
|
3804
|
-
throw new Error(i18n.phonenumbers.Error.NOT_A_NUMBER);
|
|
3805
|
-
} else if (numberToParse.length >
|
|
3806
|
-
i18n.phonenumbers.PhoneNumberUtil.MAX_INPUT_STRING_LENGTH_) {
|
|
3807
|
-
throw new Error(i18n.phonenumbers.Error.TOO_LONG);
|
|
3808
|
-
}
|
|
3809
|
-
|
|
3810
|
-
/** @type {!goog.string.StringBuffer} */
|
|
3811
|
-
var nationalNumber = new goog.string.StringBuffer();
|
|
3812
|
-
this.buildNationalNumberForParsing_(numberToParse, nationalNumber);
|
|
3813
|
-
|
|
3814
|
-
if (!i18n.phonenumbers.PhoneNumberUtil.isViablePhoneNumber(
|
|
3815
|
-
nationalNumber.toString())) {
|
|
3816
|
-
throw new Error(i18n.phonenumbers.Error.NOT_A_NUMBER);
|
|
3817
|
-
}
|
|
3818
|
-
|
|
3819
|
-
// Check the region supplied is valid, or that the extracted number starts
|
|
3820
|
-
// with some sort of + sign so the number's region can be determined.
|
|
3821
|
-
if (checkRegion &&
|
|
3822
|
-
!this.checkRegionForParsing_(nationalNumber.toString(), defaultRegion)) {
|
|
3823
|
-
throw new Error(i18n.phonenumbers.Error.INVALID_COUNTRY_CODE);
|
|
3824
|
-
}
|
|
3825
|
-
|
|
3826
|
-
/** @type {i18n.phonenumbers.PhoneNumber} */
|
|
3827
|
-
var phoneNumber = new i18n.phonenumbers.PhoneNumber();
|
|
3828
|
-
if (keepRawInput) {
|
|
3829
|
-
phoneNumber.setRawInput(numberToParse);
|
|
3830
|
-
}
|
|
3831
|
-
// Attempt to parse extension first, since it doesn't require region-specific
|
|
3832
|
-
// data and we want to have the non-normalised number here.
|
|
3833
|
-
/** @type {string} */
|
|
3834
|
-
var extension = this.maybeStripExtension(nationalNumber);
|
|
3835
|
-
if (extension.length > 0) {
|
|
3836
|
-
phoneNumber.setExtension(extension);
|
|
3837
|
-
}
|
|
3838
|
-
|
|
3839
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
3840
|
-
var regionMetadata = this.getMetadataForRegion(defaultRegion);
|
|
3841
|
-
// Check to see if the number is given in international format so we know
|
|
3842
|
-
// whether this number is from the default region or not.
|
|
3843
|
-
/** @type {!goog.string.StringBuffer} */
|
|
3844
|
-
var normalizedNationalNumber = new goog.string.StringBuffer();
|
|
3845
|
-
/** @type {number} */
|
|
3846
|
-
var countryCode = 0;
|
|
3847
|
-
/** @type {string} */
|
|
3848
|
-
var nationalNumberStr = nationalNumber.toString();
|
|
3849
|
-
try {
|
|
3850
|
-
countryCode = this.maybeExtractCountryCode(nationalNumberStr,
|
|
3851
|
-
regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
|
|
3852
|
-
} catch (e) {
|
|
3853
|
-
if (e.message == i18n.phonenumbers.Error.INVALID_COUNTRY_CODE &&
|
|
3854
|
-
i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_
|
|
3855
|
-
.test(nationalNumberStr)) {
|
|
3856
|
-
// Strip the plus-char, and try again.
|
|
3857
|
-
nationalNumberStr = nationalNumberStr.replace(
|
|
3858
|
-
i18n.phonenumbers.PhoneNumberUtil.LEADING_PLUS_CHARS_PATTERN_, '');
|
|
3859
|
-
countryCode = this.maybeExtractCountryCode(nationalNumberStr,
|
|
3860
|
-
regionMetadata, normalizedNationalNumber, keepRawInput, phoneNumber);
|
|
3861
|
-
if (countryCode == 0) {
|
|
3862
|
-
throw e;
|
|
3863
|
-
}
|
|
3864
|
-
} else {
|
|
3865
|
-
throw e;
|
|
3866
|
-
}
|
|
3867
|
-
}
|
|
3868
|
-
if (countryCode != 0) {
|
|
3869
|
-
/** @type {string} */
|
|
3870
|
-
var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode);
|
|
3871
|
-
if (phoneNumberRegion != defaultRegion) {
|
|
3872
|
-
// Metadata cannot be null because the country calling code is valid.
|
|
3873
|
-
regionMetadata = this.getMetadataForRegionOrCallingCode_(
|
|
3874
|
-
countryCode, phoneNumberRegion);
|
|
3875
|
-
}
|
|
3876
|
-
} else {
|
|
3877
|
-
// If no extracted country calling code, use the region supplied instead.
|
|
3878
|
-
// The national number is just the normalized version of the number we were
|
|
3879
|
-
// given to parse.
|
|
3880
|
-
i18n.phonenumbers.PhoneNumberUtil.normalizeSB_(nationalNumber);
|
|
3881
|
-
normalizedNationalNumber.append(nationalNumber.toString());
|
|
3882
|
-
if (defaultRegion != null) {
|
|
3883
|
-
countryCode = regionMetadata.getCountryCodeOrDefault();
|
|
3884
|
-
phoneNumber.setCountryCode(countryCode);
|
|
3885
|
-
} else if (keepRawInput) {
|
|
3886
|
-
phoneNumber.clearCountryCodeSource();
|
|
3887
|
-
}
|
|
3888
|
-
}
|
|
3889
|
-
if (normalizedNationalNumber.getLength() <
|
|
3890
|
-
i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
|
|
3891
|
-
throw new Error(i18n.phonenumbers.Error.TOO_SHORT_NSN);
|
|
3892
|
-
}
|
|
3893
|
-
|
|
3894
|
-
if (regionMetadata != null) {
|
|
3895
|
-
/** @type {!goog.string.StringBuffer} */
|
|
3896
|
-
var carrierCode = new goog.string.StringBuffer();
|
|
3897
|
-
/** @type {!goog.string.StringBuffer} */
|
|
3898
|
-
var potentialNationalNumber =
|
|
3899
|
-
new goog.string.StringBuffer(normalizedNationalNumber.toString());
|
|
3900
|
-
this.maybeStripNationalPrefixAndCarrierCode(
|
|
3901
|
-
potentialNationalNumber, regionMetadata, carrierCode);
|
|
3902
|
-
if (!this.isShorterThanPossibleNormalNumber_(
|
|
3903
|
-
regionMetadata, potentialNationalNumber.toString())) {
|
|
3904
|
-
normalizedNationalNumber = potentialNationalNumber;
|
|
3905
|
-
if (keepRawInput) {
|
|
3906
|
-
phoneNumber.setPreferredDomesticCarrierCode(carrierCode.toString());
|
|
3907
|
-
}
|
|
3908
|
-
}
|
|
3909
|
-
}
|
|
3910
|
-
/** @type {string} */
|
|
3911
|
-
var normalizedNationalNumberStr = normalizedNationalNumber.toString();
|
|
3912
|
-
/** @type {number} */
|
|
3913
|
-
var lengthOfNationalNumber = normalizedNationalNumberStr.length;
|
|
3914
|
-
if (lengthOfNationalNumber <
|
|
3915
|
-
i18n.phonenumbers.PhoneNumberUtil.MIN_LENGTH_FOR_NSN_) {
|
|
3916
|
-
throw new Error(i18n.phonenumbers.Error.TOO_SHORT_NSN);
|
|
3917
|
-
}
|
|
3918
|
-
if (lengthOfNationalNumber >
|
|
3919
|
-
i18n.phonenumbers.PhoneNumberUtil.MAX_LENGTH_FOR_NSN_) {
|
|
3920
|
-
throw new Error(i18n.phonenumbers.Error.TOO_LONG);
|
|
3921
|
-
}
|
|
3922
|
-
this.setItalianLeadingZerosForPhoneNumber_(
|
|
3923
|
-
normalizedNationalNumberStr, phoneNumber);
|
|
3924
|
-
phoneNumber.setNationalNumber(parseInt(normalizedNationalNumberStr, 10));
|
|
3925
|
-
return phoneNumber;
|
|
3926
|
-
};
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
/**
|
|
3930
|
-
* Converts numberToParse to a form that we can parse and write it to
|
|
3931
|
-
* nationalNumber if it is written in RFC3966; otherwise extract a possible
|
|
3932
|
-
* number out of it and write to nationalNumber.
|
|
3933
|
-
*
|
|
3934
|
-
* @param {?string} numberToParse number that we are attempting to parse. This
|
|
3935
|
-
* can contain formatting such as +, ( and -, as well as a phone number
|
|
3936
|
-
* extension.
|
|
3937
|
-
* @param {!goog.string.StringBuffer} nationalNumber a string buffer for storing
|
|
3938
|
-
* the national significant number.
|
|
3939
|
-
* @private
|
|
3940
|
-
*/
|
|
3941
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.buildNationalNumberForParsing_ =
|
|
3942
|
-
function(numberToParse, nationalNumber) {
|
|
3943
|
-
|
|
3944
|
-
/** @type {number} */
|
|
3945
|
-
var indexOfPhoneContext = numberToParse.indexOf(
|
|
3946
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_);
|
|
3947
|
-
if (indexOfPhoneContext > 0) {
|
|
3948
|
-
var phoneContextStart = indexOfPhoneContext +
|
|
3949
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_PHONE_CONTEXT_.length;
|
|
3950
|
-
// If the phone context contains a phone number prefix, we need to capture
|
|
3951
|
-
// it, whereas domains will be ignored.
|
|
3952
|
-
if (numberToParse.charAt(phoneContextStart) ==
|
|
3953
|
-
i18n.phonenumbers.PhoneNumberUtil.PLUS_SIGN) {
|
|
3954
|
-
// Additional parameters might follow the phone context. If so, we will
|
|
3955
|
-
// remove them here because the parameters after phone context are not
|
|
3956
|
-
// important for parsing the phone number.
|
|
3957
|
-
var phoneContextEnd = numberToParse.indexOf(';', phoneContextStart);
|
|
3958
|
-
if (phoneContextEnd > 0) {
|
|
3959
|
-
nationalNumber.append(numberToParse.substring(phoneContextStart,
|
|
3960
|
-
phoneContextEnd));
|
|
3961
|
-
} else {
|
|
3962
|
-
nationalNumber.append(numberToParse.substring(phoneContextStart));
|
|
3963
|
-
}
|
|
3964
|
-
}
|
|
3965
|
-
|
|
3966
|
-
// Now append everything between the "tel:" prefix and the phone-context.
|
|
3967
|
-
// This should include the national number, an optional extension or
|
|
3968
|
-
// isdn-subaddress component. Note we also handle the case when "tel:" is
|
|
3969
|
-
// missing, as we have seen in some of the phone number inputs.
|
|
3970
|
-
// In that case, we append everything from the beginning.
|
|
3971
|
-
var indexOfRfc3966Prefix = numberToParse.indexOf(
|
|
3972
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_);
|
|
3973
|
-
var indexOfNationalNumber = (indexOfRfc3966Prefix >= 0) ?
|
|
3974
|
-
indexOfRfc3966Prefix +
|
|
3975
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_PREFIX_.length : 0;
|
|
3976
|
-
nationalNumber.append(numberToParse.substring(indexOfNationalNumber,
|
|
3977
|
-
indexOfPhoneContext));
|
|
3978
|
-
} else {
|
|
3979
|
-
// Extract a possible number from the string passed in (this strips leading
|
|
3980
|
-
// characters that could not be the start of a phone number.)
|
|
3981
|
-
nationalNumber.append(
|
|
3982
|
-
i18n.phonenumbers.PhoneNumberUtil.extractPossibleNumber(numberToParse));
|
|
3983
|
-
}
|
|
3984
|
-
|
|
3985
|
-
// Delete the isdn-subaddress and everything after it if it is present.
|
|
3986
|
-
// Note extension won't appear at the same time with isdn-subaddress
|
|
3987
|
-
// according to paragraph 5.3 of the RFC3966 spec,
|
|
3988
|
-
/** @type {string} */
|
|
3989
|
-
var nationalNumberStr = nationalNumber.toString();
|
|
3990
|
-
var indexOfIsdn = nationalNumberStr.indexOf(
|
|
3991
|
-
i18n.phonenumbers.PhoneNumberUtil.RFC3966_ISDN_SUBADDRESS_);
|
|
3992
|
-
if (indexOfIsdn > 0) {
|
|
3993
|
-
nationalNumber.clear();
|
|
3994
|
-
nationalNumber.append(nationalNumberStr.substring(0, indexOfIsdn));
|
|
3995
|
-
}
|
|
3996
|
-
// If both phone context and isdn-subaddress are absent but other
|
|
3997
|
-
// parameters are present, the parameters are left in nationalNumber. This
|
|
3998
|
-
// is because we are concerned about deleting content from a potential
|
|
3999
|
-
// number string when there is no strong evidence that the number is
|
|
4000
|
-
// actually written in RFC3966.
|
|
4001
|
-
};
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
/**
|
|
4005
|
-
* Takes two phone numbers and compares them for equality.
|
|
4006
|
-
*
|
|
4007
|
-
* <p>Returns EXACT_MATCH if the country_code, NSN, presence of a leading zero
|
|
4008
|
-
* for Italian numbers and any extension present are the same. Returns NSN_MATCH
|
|
4009
|
-
* if either or both has no region specified, and the NSNs and extensions are
|
|
4010
|
-
* the same. Returns SHORT_NSN_MATCH if either or both has no region specified,
|
|
4011
|
-
* or the region specified is the same, and one NSN could be a shorter version
|
|
4012
|
-
* of the other number. This includes the case where one has an extension
|
|
4013
|
-
* specified, and the other does not. Returns NO_MATCH otherwise. For example,
|
|
4014
|
-
* the numbers +1 345 657 1234 and 657 1234 are a SHORT_NSN_MATCH. The numbers
|
|
4015
|
-
* +1 345 657 1234 and 345 657 are a NO_MATCH.
|
|
4016
|
-
*
|
|
4017
|
-
* @param {i18n.phonenumbers.PhoneNumber|string} firstNumberIn first number to
|
|
4018
|
-
* compare. If it is a string it can contain formatting, and can have
|
|
4019
|
-
* country calling code specified with + at the start.
|
|
4020
|
-
* @param {i18n.phonenumbers.PhoneNumber|string} secondNumberIn second number to
|
|
4021
|
-
* compare. If it is a string it can contain formatting, and can have
|
|
4022
|
-
* country calling code specified with + at the start.
|
|
4023
|
-
* @return {i18n.phonenumbers.PhoneNumberUtil.MatchType} NOT_A_NUMBER, NO_MATCH,
|
|
4024
|
-
* SHORT_NSN_MATCH, NSN_MATCH or EXACT_MATCH depending on the level of
|
|
4025
|
-
* equality of the two numbers, described in the method definition.
|
|
4026
|
-
*/
|
|
4027
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberMatch =
|
|
4028
|
-
function(firstNumberIn, secondNumberIn) {
|
|
4029
|
-
|
|
4030
|
-
// If the input arguements are strings parse them to a proto buffer format.
|
|
4031
|
-
// Else make copies of the phone numbers so that the numbers passed in are not
|
|
4032
|
-
// edited.
|
|
4033
|
-
/** @type {i18n.phonenumbers.PhoneNumber} */
|
|
4034
|
-
var firstNumber;
|
|
4035
|
-
/** @type {i18n.phonenumbers.PhoneNumber} */
|
|
4036
|
-
var secondNumber;
|
|
4037
|
-
if (typeof firstNumberIn == 'string') {
|
|
4038
|
-
// First see if the first number has an implicit country calling code, by
|
|
4039
|
-
// attempting to parse it.
|
|
4040
|
-
try {
|
|
4041
|
-
firstNumber = this.parse(
|
|
4042
|
-
firstNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
|
|
4043
|
-
} catch (e) {
|
|
4044
|
-
if (e.message != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
|
|
4045
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
|
|
4046
|
-
}
|
|
4047
|
-
// The first number has no country calling code. EXACT_MATCH is no longer
|
|
4048
|
-
// possible. We parse it as if the region was the same as that for the
|
|
4049
|
-
// second number, and if EXACT_MATCH is returned, we replace this with
|
|
4050
|
-
// NSN_MATCH.
|
|
4051
|
-
if (typeof secondNumberIn != 'string') {
|
|
4052
|
-
/** @type {string} */
|
|
4053
|
-
var secondNumberRegion = this.getRegionCodeForCountryCode(
|
|
4054
|
-
secondNumberIn.getCountryCodeOrDefault());
|
|
4055
|
-
if (secondNumberRegion !=
|
|
4056
|
-
i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_) {
|
|
4057
|
-
try {
|
|
4058
|
-
firstNumber = this.parse(firstNumberIn, secondNumberRegion);
|
|
4059
|
-
} catch (e2) {
|
|
4060
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
|
|
4061
|
-
}
|
|
4062
|
-
/** @type {i18n.phonenumbers.PhoneNumberUtil.MatchType} */
|
|
4063
|
-
var match = this.isNumberMatch(firstNumber, secondNumberIn);
|
|
4064
|
-
if (match ==
|
|
4065
|
-
i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH) {
|
|
4066
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
|
|
4067
|
-
}
|
|
4068
|
-
return match;
|
|
4069
|
-
}
|
|
4070
|
-
}
|
|
4071
|
-
// If the second number is a string or doesn't have a valid country
|
|
4072
|
-
// calling code, we parse the first number without country calling code.
|
|
4073
|
-
try {
|
|
4074
|
-
firstNumber = this.parseHelper_(firstNumberIn, null, false, false);
|
|
4075
|
-
} catch (e2) {
|
|
4076
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
|
|
4077
|
-
}
|
|
4078
|
-
}
|
|
4079
|
-
} else {
|
|
4080
|
-
firstNumber = firstNumberIn.clone();
|
|
4081
|
-
}
|
|
4082
|
-
if (typeof secondNumberIn == 'string') {
|
|
4083
|
-
try {
|
|
4084
|
-
secondNumber = this.parse(
|
|
4085
|
-
secondNumberIn, i18n.phonenumbers.PhoneNumberUtil.UNKNOWN_REGION_);
|
|
4086
|
-
return this.isNumberMatch(firstNumberIn, secondNumber);
|
|
4087
|
-
} catch (e) {
|
|
4088
|
-
if (e.message != i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) {
|
|
4089
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NOT_A_NUMBER;
|
|
4090
|
-
}
|
|
4091
|
-
return this.isNumberMatch(secondNumberIn, firstNumber);
|
|
4092
|
-
}
|
|
4093
|
-
} else {
|
|
4094
|
-
secondNumber = secondNumberIn.clone();
|
|
4095
|
-
}
|
|
4096
|
-
// First clear raw_input, country_code_source and
|
|
4097
|
-
// preferred_domestic_carrier_code fields and any empty-string extensions so
|
|
4098
|
-
// that we can use the proto-buffer equality method.
|
|
4099
|
-
firstNumber.clearRawInput();
|
|
4100
|
-
firstNumber.clearCountryCodeSource();
|
|
4101
|
-
firstNumber.clearPreferredDomesticCarrierCode();
|
|
4102
|
-
secondNumber.clearRawInput();
|
|
4103
|
-
secondNumber.clearCountryCodeSource();
|
|
4104
|
-
secondNumber.clearPreferredDomesticCarrierCode();
|
|
4105
|
-
if (firstNumber.hasExtension() && firstNumber.getExtension().length == 0) {
|
|
4106
|
-
firstNumber.clearExtension();
|
|
4107
|
-
}
|
|
4108
|
-
if (secondNumber.hasExtension() && secondNumber.getExtension().length == 0) {
|
|
4109
|
-
secondNumber.clearExtension();
|
|
4110
|
-
}
|
|
4111
|
-
|
|
4112
|
-
// Early exit if both had extensions and these are different.
|
|
4113
|
-
if (firstNumber.hasExtension() && secondNumber.hasExtension() &&
|
|
4114
|
-
firstNumber.getExtension() != secondNumber.getExtension()) {
|
|
4115
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
|
|
4116
|
-
}
|
|
4117
|
-
/** @type {number} */
|
|
4118
|
-
var firstNumberCountryCode = firstNumber.getCountryCodeOrDefault();
|
|
4119
|
-
/** @type {number} */
|
|
4120
|
-
var secondNumberCountryCode = secondNumber.getCountryCodeOrDefault();
|
|
4121
|
-
// Both had country_code specified.
|
|
4122
|
-
if (firstNumberCountryCode != 0 && secondNumberCountryCode != 0) {
|
|
4123
|
-
if (firstNumber.equals(secondNumber)) {
|
|
4124
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.EXACT_MATCH;
|
|
4125
|
-
} else if (firstNumberCountryCode == secondNumberCountryCode &&
|
|
4126
|
-
this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
|
|
4127
|
-
// A SHORT_NSN_MATCH occurs if there is a difference because of the
|
|
4128
|
-
// presence or absence of an 'Italian leading zero', the presence or
|
|
4129
|
-
// absence of an extension, or one NSN being a shorter variant of the
|
|
4130
|
-
// other.
|
|
4131
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
|
|
4132
|
-
}
|
|
4133
|
-
// This is not a match.
|
|
4134
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
|
|
4135
|
-
}
|
|
4136
|
-
// Checks cases where one or both country_code fields were not specified. To
|
|
4137
|
-
// make equality checks easier, we first set the country_code fields to be
|
|
4138
|
-
// equal.
|
|
4139
|
-
firstNumber.setCountryCode(0);
|
|
4140
|
-
secondNumber.setCountryCode(0);
|
|
4141
|
-
// If all else was the same, then this is an NSN_MATCH.
|
|
4142
|
-
if (firstNumber.equals(secondNumber)) {
|
|
4143
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NSN_MATCH;
|
|
4144
|
-
}
|
|
4145
|
-
if (this.isNationalNumberSuffixOfTheOther_(firstNumber, secondNumber)) {
|
|
4146
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.SHORT_NSN_MATCH;
|
|
4147
|
-
}
|
|
4148
|
-
return i18n.phonenumbers.PhoneNumberUtil.MatchType.NO_MATCH;
|
|
4149
|
-
};
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
/**
|
|
4153
|
-
* Returns true when one national number is the suffix of the other or both are
|
|
4154
|
-
* the same.
|
|
4155
|
-
*
|
|
4156
|
-
* @param {i18n.phonenumbers.PhoneNumber} firstNumber the first PhoneNumber
|
|
4157
|
-
* object.
|
|
4158
|
-
* @param {i18n.phonenumbers.PhoneNumber} secondNumber the second PhoneNumber
|
|
4159
|
-
* object.
|
|
4160
|
-
* @return {boolean} true if one PhoneNumber is the suffix of the other one.
|
|
4161
|
-
* @private
|
|
4162
|
-
*/
|
|
4163
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ =
|
|
4164
|
-
function(firstNumber, secondNumber) {
|
|
4165
|
-
|
|
4166
|
-
/** @type {string} */
|
|
4167
|
-
var firstNumberNationalNumber = '' + firstNumber.getNationalNumber();
|
|
4168
|
-
/** @type {string} */
|
|
4169
|
-
var secondNumberNationalNumber = '' + secondNumber.getNationalNumber();
|
|
4170
|
-
// Note that endsWith returns true if the numbers are equal.
|
|
4171
|
-
return goog.string.endsWith(firstNumberNationalNumber,
|
|
4172
|
-
secondNumberNationalNumber) ||
|
|
4173
|
-
goog.string.endsWith(secondNumberNationalNumber,
|
|
4174
|
-
firstNumberNationalNumber);
|
|
4175
|
-
};
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
/**
|
|
4179
|
-
* Returns true if the number can be dialled from outside the region, or
|
|
4180
|
-
* unknown. If the number can only be dialled from within the region, returns
|
|
4181
|
-
* false. Does not check the number is a valid number.
|
|
4182
|
-
* TODO: Make this method public when we have enough metadata to make it
|
|
4183
|
-
* worthwhile. Currently visible for testing purposes only.
|
|
4184
|
-
*
|
|
4185
|
-
* @param {i18n.phonenumbers.PhoneNumber} number the phone-number for which we
|
|
4186
|
-
* want to know whether it is diallable from outside the region.
|
|
4187
|
-
* @return {boolean} true if the number can only be dialled from within the
|
|
4188
|
-
* country.
|
|
4189
|
-
*/
|
|
4190
|
-
i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled =
|
|
4191
|
-
function(number) {
|
|
4192
|
-
/** @type {i18n.phonenumbers.PhoneMetadata} */
|
|
4193
|
-
var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
|
|
4194
|
-
if (metadata == null) {
|
|
4195
|
-
// Note numbers belonging to non-geographical entities (e.g. +800 numbers)
|
|
4196
|
-
// are always internationally diallable, and will be caught here.
|
|
4197
|
-
return true;
|
|
4198
|
-
}
|
|
4199
|
-
/** @type {string} */
|
|
4200
|
-
var nationalSignificantNumber = this.getNationalSignificantNumber(number);
|
|
4201
|
-
return !this.isNumberMatchingDesc_(nationalSignificantNumber,
|
|
4202
|
-
metadata.getNoInternationalDialling());
|
|
4203
|
-
};
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
/**
|
|
4207
|
-
* Check whether the entire input sequence can be matched against the regular
|
|
4208
|
-
* expression.
|
|
4209
|
-
*
|
|
4210
|
-
* @param {!RegExp|string} regex the regular expression to match against.
|
|
4211
|
-
* @param {string} str the string to test.
|
|
4212
|
-
* @return {boolean} true if str can be matched entirely against regex.
|
|
4213
|
-
* @private
|
|
4214
|
-
*/
|
|
4215
|
-
i18n.phonenumbers.PhoneNumberUtil.matchesEntirely_ = function(regex, str) {
|
|
4216
|
-
/** @type {Array.<string>} */
|
|
4217
|
-
var matchedGroups = (typeof regex == 'string') ?
|
|
4218
|
-
str.match('^(?:' + regex + ')$') : str.match(regex);
|
|
4219
|
-
if (matchedGroups && matchedGroups[0].length == str.length) {
|
|
4220
|
-
return true;
|
|
4221
|
-
}
|
|
4222
|
-
return false;
|
|
4223
|
-
};
|