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.
@@ -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
- };