@yext/phonenumber-util 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +6 -0
- package/.prettierrc +6 -0
- package/CODEOWNERS +2 -0
- package/LICENSE +28 -0
- package/README.md +153 -0
- package/THIRD-PARTY-NOTICES +5 -0
- package/eslint.config.mjs +7 -0
- package/package.json +40 -0
- package/src/__tests__/index.test.js +239 -0
- package/src/areaCodeList.js +417 -0
- package/src/index.d.ts +37 -0
- package/src/index.js +380 -0
- package/src/phoneFormats.js +212 -0
- package/vitest.config.js +6 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { AREA_CODE_LIST } from './areaCodeList.js';
|
|
2
|
+
import { PHONE_FORMATS } from './phoneFormats.js';
|
|
3
|
+
|
|
4
|
+
const DASHES = '-\u2010-\u2015\u2212\u30FC\uFF0D';
|
|
5
|
+
const SLASHES = '\uFF0F/';
|
|
6
|
+
const DOTS = '\uFF0E.';
|
|
7
|
+
const WHITESPACE = ' \u00A0\u00AD\u200B\u2060\u3000';
|
|
8
|
+
const BRACKETS = '()\\[\\]\uFF08\uFF09\uFF3B\uFF3D';
|
|
9
|
+
const TILDES = '~\u2053\u223C\uFF5E';
|
|
10
|
+
const VALID_DIGITS = '0-9';
|
|
11
|
+
const PLUS_CHARS = '\\+';
|
|
12
|
+
|
|
13
|
+
const VALID_PUNCTUATION = `${DASHES}${SLASHES}${DOTS}${WHITESPACE}${BRACKETS}${TILDES}`;
|
|
14
|
+
|
|
15
|
+
const VALID_PHONE_NUMBER = new RegExp(
|
|
16
|
+
`(?:(?:${PLUS_CHARS}?[${VALID_DIGITS}]{1,3}[${VALID_PUNCTUATION}]*)?` + // Country code (optional)
|
|
17
|
+
`(?:\\(?[${VALID_DIGITS}]{1,4}\\)?[${VALID_PUNCTUATION}]*)?` + // Area code (optional)
|
|
18
|
+
`(?:[${VALID_DIGITS}]{1,4}[${VALID_PUNCTUATION}]*){1,5}` + // Phone number segments
|
|
19
|
+
`[${VALID_DIGITS}]{1,4})`, // Final segment
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Formats a phone number into the E.164 international standard.
|
|
24
|
+
*
|
|
25
|
+
* This function takes the components of a phone number and formats it into the
|
|
26
|
+
* E.164 standard, which includes the region code and the local number. The format
|
|
27
|
+
*
|
|
28
|
+
* @param {Object} phoneParts - An object containing parts of the phone number.
|
|
29
|
+
* @param {string} phoneParts.areaCode - The area code of the phone number.
|
|
30
|
+
* @param {string} phoneParts.regionCode - The region code of the phone number.
|
|
31
|
+
* @param {string} phoneParts.localNumber - The local part of the phone number.
|
|
32
|
+
* @returns {string|null} The formatted phone number in E.164 format, or null if the region code or local number is not present.
|
|
33
|
+
*/
|
|
34
|
+
export const formatPhoneNumberForE164 = ({
|
|
35
|
+
regionCode,
|
|
36
|
+
areaCode,
|
|
37
|
+
localNumber,
|
|
38
|
+
}) => {
|
|
39
|
+
if ((regionCode !== '1' || areaCode) && regionCode && localNumber) {
|
|
40
|
+
// A US number passed with area code decoupled from the localNumber. Assumes the format:
|
|
41
|
+
// regionCode: 1, areaCode: 310, localNumber: 3496200
|
|
42
|
+
if (regionCode === '1' && areaCode && localNumber.length === 7) {
|
|
43
|
+
return `+1${areaCode}${localNumber}`;
|
|
44
|
+
}
|
|
45
|
+
// Combine the region code and the formatted local number - this assumes US localNumber includes area code
|
|
46
|
+
// This is for all intl and all US with format:
|
|
47
|
+
// regionCode: 1, localNumber: 3103496200
|
|
48
|
+
return areaCode ? `+1${localNumber}` : `+${regionCode}${localNumber}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return null;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Formats a phone number into a tel: link format.
|
|
56
|
+
*
|
|
57
|
+
* This function takes the components of a phone number and formats it into a
|
|
58
|
+
* `tel:` link, which can be used in HTML for clickable phone numbers.
|
|
59
|
+
*
|
|
60
|
+
* @param {Object} phoneParts - An object containing parts of the phone number.
|
|
61
|
+
* @param {string} phoneParts.regionCode - The region code of the phone number.
|
|
62
|
+
* @param {string} phoneParts.areaCode - The area code of the phone number.
|
|
63
|
+
* @param {string} phoneParts.localNumber - The local part of the phone number.
|
|
64
|
+
* @returns {string|null} The formatted phone number link, or null if the local number is not present.
|
|
65
|
+
*/
|
|
66
|
+
export const formatPhoneNumberLink = ({
|
|
67
|
+
regionCode,
|
|
68
|
+
areaCode,
|
|
69
|
+
localNumber,
|
|
70
|
+
}) => {
|
|
71
|
+
if (localNumber) {
|
|
72
|
+
if (regionCode === '1') {
|
|
73
|
+
return areaCode
|
|
74
|
+
? `tel:+1${areaCode}${localNumber}`
|
|
75
|
+
: `tel:${localNumber}`;
|
|
76
|
+
} else {
|
|
77
|
+
return `tel:+${regionCode}${localNumber}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return null;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Validates a phone number based on a regex pattern and the ability to extract useful parts.
|
|
86
|
+
*
|
|
87
|
+
* This function first checks the phone number against a predefined regular expression pattern
|
|
88
|
+
* to determine its validity. It then uses the `getPhoneParts` function to extract relevant parts
|
|
89
|
+
* of the phone number and further confirms its validity based on the presence of these parts.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} phoneNumber - The phone number to validate.
|
|
92
|
+
* @returns {boolean} Returns true if the phone number is valid, otherwise false.
|
|
93
|
+
*/
|
|
94
|
+
export const isValidPhoneNumber = (phoneNumber) => {
|
|
95
|
+
// Check the big chunky regex for phone validity
|
|
96
|
+
const phonePattern = new RegExp(VALID_PHONE_NUMBER, 'ig');
|
|
97
|
+
if (phonePattern.test(phoneNumber)) {
|
|
98
|
+
const phoneParts = getPhoneParts(phoneNumber);
|
|
99
|
+
|
|
100
|
+
// Also check for phone validity by ability to extract useful parts.
|
|
101
|
+
// This will also confirm area codes / region codes are valid.
|
|
102
|
+
if (
|
|
103
|
+
phoneParts &&
|
|
104
|
+
phoneParts.localNumber &&
|
|
105
|
+
phoneParts.regionCode &&
|
|
106
|
+
(phoneParts.areaCode || phoneParts.regionCode !== '1')
|
|
107
|
+
) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Extracts and formats parts of a phone number, including area code, region code, and local number.
|
|
116
|
+
*
|
|
117
|
+
* This function takes a phone number and optionally a region code, then processes it to extract
|
|
118
|
+
* relevant parts like the area code, region code, and local number. It also validates the phone
|
|
119
|
+
* number and ensures it conforms to specific formats, particularly for US numbers.
|
|
120
|
+
*
|
|
121
|
+
* @param {string} phoneNumber - The phone number to process.
|
|
122
|
+
* @returns {Object} An object containing relevant phone number information.
|
|
123
|
+
* @property {string|null} areaCode - The area code of the phone number.
|
|
124
|
+
* @property {string|null} e164 - The E.164 formatted version of the phone number.
|
|
125
|
+
* @property {string|null} href - A formatted phone number link.
|
|
126
|
+
* @property {string|null} localNumber - The local part of the phone number.
|
|
127
|
+
* @property {string} rawNumber - The original raw phone number. Unsanitized.
|
|
128
|
+
* @property {string|null} regionCode - The region code of the phone number.
|
|
129
|
+
*/
|
|
130
|
+
export const getPhoneParts = (phoneNumber) => {
|
|
131
|
+
const regionCodeLengths = [1, 2, 3];
|
|
132
|
+
let phoneParts = {
|
|
133
|
+
areaCode: null,
|
|
134
|
+
e164: null,
|
|
135
|
+
format: null,
|
|
136
|
+
formattedNumber: null,
|
|
137
|
+
href: null,
|
|
138
|
+
localNumber: null,
|
|
139
|
+
rawNumber: phoneNumber,
|
|
140
|
+
regionCode: null,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
if (!phoneNumber) {
|
|
144
|
+
return phoneParts;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Remove all non-digit characters except the leading '+'
|
|
148
|
+
let strippedPhoneNumber = sanitizeRawNumber(phoneNumber);
|
|
149
|
+
|
|
150
|
+
// The shortest length for a phone number (that we care about) is 7 digits.
|
|
151
|
+
// The longest phone number is 15 digits.
|
|
152
|
+
if (
|
|
153
|
+
strippedPhoneNumber.replace(/\D/g, '').length >= 7 &&
|
|
154
|
+
strippedPhoneNumber.replace(/\D/g, '').length <= 15
|
|
155
|
+
) {
|
|
156
|
+
// Extract the region code if not explicitly provided and it is part of the
|
|
157
|
+
// phone number
|
|
158
|
+
if (strippedPhoneNumber.startsWith('+')) {
|
|
159
|
+
// US number formatted with +12065551234
|
|
160
|
+
if (
|
|
161
|
+
strippedPhoneNumber.length === 12 &&
|
|
162
|
+
strippedPhoneNumber.startsWith('+1')
|
|
163
|
+
) {
|
|
164
|
+
phoneParts.regionCode = '1';
|
|
165
|
+
phoneParts.localNumber = strippedPhoneNumber.slice(2); // Strip out the "+1"
|
|
166
|
+
phoneParts.areaCode = phoneParts.localNumber.slice(0, 3); // Grab the area code
|
|
167
|
+
}
|
|
168
|
+
// Otherwise, an intl number which may have 1, 2 or 3 digit region
|
|
169
|
+
else if (
|
|
170
|
+
strippedPhoneNumber.length >= 7 &&
|
|
171
|
+
strippedPhoneNumber.length <= 14
|
|
172
|
+
) {
|
|
173
|
+
// Try to match the phone number with each possible region code length
|
|
174
|
+
for (let length of regionCodeLengths) {
|
|
175
|
+
let match = strippedPhoneNumber.match(
|
|
176
|
+
new RegExp(`^\\+(\\d{${length}})(\\d+)`),
|
|
177
|
+
);
|
|
178
|
+
if (match && PHONE_FORMATS[match[1]]) {
|
|
179
|
+
phoneParts.regionCode = match[1];
|
|
180
|
+
phoneParts.localNumber = match[2];
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// If no region code is provided, assume US with the format 3109309000 after being stripped of non-numeric values.
|
|
187
|
+
// We'll try and derive the area code by looking it up against the known area codes.
|
|
188
|
+
else if (strippedPhoneNumber.length === 10) {
|
|
189
|
+
if (AREA_CODE_LIST.indexOf(strippedPhoneNumber.substring(0, 3)) !== -1) {
|
|
190
|
+
phoneParts.regionCode = '1';
|
|
191
|
+
phoneParts.areaCode = strippedPhoneNumber.substring(0, 3);
|
|
192
|
+
phoneParts.localNumber = strippedPhoneNumber.substring(3);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// If no region code is provided, assume US with the format 9309000 after being stripped of non-numeric values.
|
|
196
|
+
// This is not able to be validated or formatted since it lacks an area code.
|
|
197
|
+
else if (strippedPhoneNumber.length === 7) {
|
|
198
|
+
phoneParts.regionCode = '1';
|
|
199
|
+
phoneParts.localNumber = strippedPhoneNumber;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Default to region code 1 for US numbers if none is provided
|
|
203
|
+
if (
|
|
204
|
+
strippedPhoneNumber.length === 11 &&
|
|
205
|
+
strippedPhoneNumber.startsWith('1')
|
|
206
|
+
) {
|
|
207
|
+
phoneParts.regionCode = '1';
|
|
208
|
+
phoneParts.localNumber = strippedPhoneNumber.slice(1);
|
|
209
|
+
phoneParts.areaCode = phoneParts.localNumber.slice(0, 3);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// US likes a format that isn't as common
|
|
213
|
+
if (phoneParts.localNumber && phoneParts.regionCode === '1') {
|
|
214
|
+
// Specific format for US numbers with areaCode (206-930-9000).
|
|
215
|
+
if (phoneParts.localNumber.length === 10) {
|
|
216
|
+
phoneParts.areaCode = phoneParts.localNumber.slice(0, 3);
|
|
217
|
+
}
|
|
218
|
+
} else if (phoneParts.localNumber) {
|
|
219
|
+
// General format for shorter numbers
|
|
220
|
+
phoneParts.localNumber = phoneParts.localNumber.replace(/\D/g, '');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Unset any known invalid area codes. We only care about region 1 (USA).
|
|
225
|
+
if (
|
|
226
|
+
AREA_CODE_LIST.indexOf(phoneParts.areaCode) === -1 ||
|
|
227
|
+
phoneParts.regionCode !== '1'
|
|
228
|
+
) {
|
|
229
|
+
phoneParts.areaCode = null;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (phoneParts.localNumber && phoneParts.regionCode) {
|
|
233
|
+
phoneParts.href = formatPhoneNumberLink(phoneParts);
|
|
234
|
+
phoneParts.e164 = formatPhoneNumberForE164(phoneParts);
|
|
235
|
+
phoneParts.format = findPhoneFormat(phoneParts);
|
|
236
|
+
phoneParts.formattedNumber = formatPhoneNumber(phoneParts);
|
|
237
|
+
|
|
238
|
+
// If there are left over x's, the formatting ran into something unexpected.
|
|
239
|
+
// This may be ok depending on the region and their phone number formats.
|
|
240
|
+
// But it does mean we don't want to display this number.
|
|
241
|
+
if (
|
|
242
|
+
phoneParts.formattedNumber &&
|
|
243
|
+
phoneParts.formattedNumber.indexOf('x') !== -1
|
|
244
|
+
) {
|
|
245
|
+
// Since `rawNumber` isn't sanitized, we'll use a simple format that we
|
|
246
|
+
// are assured to be safe.
|
|
247
|
+
phoneParts.formattedNumber = strippedPhoneNumber;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return phoneParts;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Sanitizes a phone number by removing all non-numeric characters
|
|
256
|
+
* except for the leading plus sign (+) if it exists.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} phoneNumber - The raw phone number input.
|
|
259
|
+
* @returns {string} - The sanitized phone number containing only digits and an optional leading plus sign.
|
|
260
|
+
*/
|
|
261
|
+
export const sanitizeRawNumber = (phoneNumber) => {
|
|
262
|
+
return phoneNumber.replace(/(?!^\+)\D/g, '');
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Finds valid phone numbers in a given text string.
|
|
267
|
+
*
|
|
268
|
+
* This function uses a regular expression to locate potential phone numbers in the text.
|
|
269
|
+
* Valid matches are then processed to extract relevant information.
|
|
270
|
+
*
|
|
271
|
+
* @param {string} text - The text string to search for phone numbers.
|
|
272
|
+
* @returns {Array<Object>} An array of objects, each containing the index, lastIndex, and parts of the valid phone numbers found.
|
|
273
|
+
* @property {number} index - The starting index of the phone number in the text.
|
|
274
|
+
* @property {number} lastIndex - The ending index of the phone number in the text.
|
|
275
|
+
* @property {Object} phoneParts - The parts of the phone number, as returned by the getPhoneParts function.
|
|
276
|
+
*/
|
|
277
|
+
export const findNumbersInString = (text) => {
|
|
278
|
+
const regex = new RegExp(VALID_PHONE_NUMBER, 'g');
|
|
279
|
+
let matches = [];
|
|
280
|
+
let match;
|
|
281
|
+
|
|
282
|
+
// Regex finds possible matches. Go through each of them to further validate and extract relevant info.
|
|
283
|
+
while ((match = regex.exec(text)) !== null) {
|
|
284
|
+
let number = match[0].trim(); // Access the captured group
|
|
285
|
+
|
|
286
|
+
// Ensure number is not just a partial match by checking it contains at least 6 digits.
|
|
287
|
+
if (
|
|
288
|
+
number.replace(new RegExp(`[${VALID_PUNCTUATION}]`, 'g'), '').length >= 6
|
|
289
|
+
) {
|
|
290
|
+
const index = text.indexOf(number);
|
|
291
|
+
const lastIndex = index + number.length;
|
|
292
|
+
const phoneParts = getPhoneParts(number);
|
|
293
|
+
|
|
294
|
+
// Presumed phone numbers may be invalidated by omission of formattedNumber from getPhoneParts.
|
|
295
|
+
// This will prevent short-numbers that ommit area code from being fetched from a larger string since it may be unreliable.
|
|
296
|
+
if (phoneParts.formattedNumber) {
|
|
297
|
+
matches.push({
|
|
298
|
+
index,
|
|
299
|
+
lastIndex,
|
|
300
|
+
...phoneParts,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return matches;
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Finds the phone number format for a given region code.
|
|
311
|
+
*
|
|
312
|
+
* This function retrieves the phone number format corresponding to the provided
|
|
313
|
+
* region code from the PHONE_FORMATS object. If the region code is not found,
|
|
314
|
+
* it defaults to the format for region code '1' (US).
|
|
315
|
+
*
|
|
316
|
+
* @param {Object} params - The parameters for formatting the phone number.
|
|
317
|
+
* @param {string} regionCode - The region code to look up the phone number format.
|
|
318
|
+
* @param {string} params.e164 - The E.164 formatted phone number to format. Example: `+12065551234`.
|
|
319
|
+
* @returns {string} The phone number format for the given region code in the format of "(xxx) xxx-xxxx".
|
|
320
|
+
*/
|
|
321
|
+
export const findPhoneFormat = ({ regionCode, e164 }) => {
|
|
322
|
+
const formatRaw = PHONE_FORMATS[regionCode];
|
|
323
|
+
const numberLength = e164 && e164.replace(/\D/g, '').length;
|
|
324
|
+
// If the region isn't defined or no matching length is found in the PHONE_FORMATS, we'll fall back to the US format.
|
|
325
|
+
let format = PHONE_FORMATS[1];
|
|
326
|
+
|
|
327
|
+
if (formatRaw && numberLength) {
|
|
328
|
+
// The PHONE_FORMATS will have arrays for regions with inconsistent number lengths / formats.
|
|
329
|
+
if (Array.isArray(formatRaw)) {
|
|
330
|
+
formatRaw.forEach((value) => {
|
|
331
|
+
const templateLength = value.split('x').length - 1;
|
|
332
|
+
if (numberLength === templateLength) {
|
|
333
|
+
format = value;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
// Some region (such as the US) will have a consistent format, so we expect a string.
|
|
338
|
+
else if (formatRaw) {
|
|
339
|
+
format = formatRaw;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return format;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Formats a phone number according to a specified format.
|
|
348
|
+
*
|
|
349
|
+
* This function takes a desired format string and an E.164 formatted phone number,
|
|
350
|
+
* then formats the phone number according to the provided format. The format string
|
|
351
|
+
* uses 'x' characters to represent digits from the phone number.
|
|
352
|
+
*
|
|
353
|
+
* @param {Object} params - The parameters for formatting the phone number.
|
|
354
|
+
* @param {string} params.format - The desired format for the phone number. Example: `(xxx) xxx-xxxx`.
|
|
355
|
+
* @param {string} params.e164 - The E.164 formatted phone number to format. Example: `+12065551234`.
|
|
356
|
+
* @returns {string|null} The formatted phone number, or null if the E.164 number or format is not provided.
|
|
357
|
+
*/
|
|
358
|
+
export const formatPhoneNumber = ({ format, e164 }) => {
|
|
359
|
+
let formattedNumber = '';
|
|
360
|
+
|
|
361
|
+
if (e164 && format) {
|
|
362
|
+
// Remove the leading '+' and let the format handle it.
|
|
363
|
+
const strippedPhone = e164.replace(/\D/g, '');
|
|
364
|
+
let phoneIndex = strippedPhone.length - 1;
|
|
365
|
+
|
|
366
|
+
// Traverse backward so we can omit country code in some formats (like US).
|
|
367
|
+
for (let i = format.length; i >= 0; i--) {
|
|
368
|
+
if (format[i]) {
|
|
369
|
+
if (format[i].toLowerCase() === 'x' && strippedPhone[phoneIndex]) {
|
|
370
|
+
formattedNumber = strippedPhone[phoneIndex] + formattedNumber;
|
|
371
|
+
phoneIndex -= 1;
|
|
372
|
+
} else {
|
|
373
|
+
formattedNumber = format[i] + formattedNumber;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return formattedNumber || null;
|
|
380
|
+
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
export const PHONE_FORMATS = {
|
|
2
|
+
1: '(xxx) xxx-xxxx', // United States
|
|
3
|
+
7: '+x xxx xxx-xx-xx', // Russia
|
|
4
|
+
20: '+xx x xxxxxxxx', // Egypt
|
|
5
|
+
27: '+xx xx xxx xxxx', // South Africa
|
|
6
|
+
30: '+xx xxx xxx xxxx', // Greece
|
|
7
|
+
31: '+xx xx xxx xxxx', // Netherlands
|
|
8
|
+
32: '+xx xxx xx xx xx', // Belgium
|
|
9
|
+
33: '+xx x xx xx xx xx', // France
|
|
10
|
+
34: '+xx xxx xx xx xx', // Spain
|
|
11
|
+
36: '+xx xx xxx xxxx', // Hungary
|
|
12
|
+
39: '+xx xxx xxx xxxx', // Italy
|
|
13
|
+
40: '+xx xxx xxx xxxx', // Romania
|
|
14
|
+
41: '+xx xx xxx xx xx', // Switzerland
|
|
15
|
+
43: '+xx xxx xxx xxxx', // Austria
|
|
16
|
+
44: '+xx xxxx xxxxxx', // United Kingdom
|
|
17
|
+
45: '+xx xx xx xx xx', // Denmark
|
|
18
|
+
46: '+xx xx xxx xx xx', // Sweden
|
|
19
|
+
47: '+xx xxx xx xxx', // Norway
|
|
20
|
+
48: '+xx xxx xxx xxx', // Poland
|
|
21
|
+
49: [
|
|
22
|
+
'+xx xx xxxxxx',
|
|
23
|
+
'+xx xx xxxxxxx',
|
|
24
|
+
'+xx xx xxxxxxxx',
|
|
25
|
+
'+xx xxx xxxxxxxx',
|
|
26
|
+
], // Germany
|
|
27
|
+
51: '+xx xxx xxx xxx', // Peru
|
|
28
|
+
52: '+xx x xxxx xxxx', // Mexico
|
|
29
|
+
53: '+x xxx xxxx', // Cuba
|
|
30
|
+
54: '+xx xx xxxx xxxx', // Argentina
|
|
31
|
+
55: '+xx xx xxxx xxxx', // Brazil
|
|
32
|
+
56: '+xx x xxxx xxxx', // Chile
|
|
33
|
+
57: '+xx xxx xxx xxxx', // Colombia
|
|
34
|
+
58: '+xx xxx xxx xxxx', // Venezuela
|
|
35
|
+
60: '+xx xx xxx xxxx', // Malaysia
|
|
36
|
+
61: '+xx xxxx xxxx', // Australia
|
|
37
|
+
62: '+xx xxx xxx xxx', // Indonesia
|
|
38
|
+
63: '+xx xxx xxx xxxx', // Philippines
|
|
39
|
+
64: '+xx xxx xxx xxxx', // New Zealand
|
|
40
|
+
65: '+xx xxxx xxxx', // Singapore
|
|
41
|
+
66: '+xx xx xxx xxxx', // Thailand
|
|
42
|
+
81: '+xx xx xxxx xxxx', // Japan
|
|
43
|
+
82: '+xx xx xxx xxxx', // South Korea
|
|
44
|
+
84: '+xx xxx xxxx xxxx', // Vietnam
|
|
45
|
+
86: '+xx xxx xxxx xxxx', // China
|
|
46
|
+
90: '+xx xxx xxx xxxx', // Turkey
|
|
47
|
+
91: '+xx xx xxxx xxxx', // India
|
|
48
|
+
92: '+xx xxx xxx xxxx', // Pakistan
|
|
49
|
+
93: '+xx xx xxx xxxx', // Afghanistan
|
|
50
|
+
94: '+xx xx xxx xxxx', // Sri Lanka
|
|
51
|
+
95: '+xx xxx xxx xxxx', // Myanmar
|
|
52
|
+
98: '+xx xxx xxx xxxx', // Iran
|
|
53
|
+
211: '+xxx xxx xxxx', // South Sudan
|
|
54
|
+
212: '+xxx xx xx xx xx', // Morocco
|
|
55
|
+
213: '+xxx xx xx xx', // Algeria
|
|
56
|
+
216: '+xxx xx xxx', // Tunisia
|
|
57
|
+
218: '+xxx xx xxx xxx', // Libya
|
|
58
|
+
220: '+xxx xxx xxxx', // Gambia
|
|
59
|
+
221: '+xxx xxx xxx xxx', // Senegal
|
|
60
|
+
222: '+xxx xxx xxxx', // Mauritania
|
|
61
|
+
223: '+xxx xxx xxxx', // Mali
|
|
62
|
+
224: '+xxx xxx xxx xxx', // Guinea
|
|
63
|
+
225: '+xxx xx xx xx xx', // Ivory Coast
|
|
64
|
+
226: '+xxx xx xx xx xx', // Burkina Faso
|
|
65
|
+
227: '+xxx xx xx xx xx', // Niger
|
|
66
|
+
228: '+xxx xxx xxx xxx', // Togo
|
|
67
|
+
229: '+xxx xx xx xx xx', // Benin
|
|
68
|
+
230: '+xxx xxxx xxxx', // Mauritius
|
|
69
|
+
231: '+xxx xx xx xx xx', // Liberia
|
|
70
|
+
232: '+xxx xxx xxxx', // Sierra Leone
|
|
71
|
+
233: '+xxx xxx xxxx', // Ghana
|
|
72
|
+
234: '+xxx xxx xxxx xxxx', // Nigeria
|
|
73
|
+
235: '+xxx xx xx xx xx', // Chad
|
|
74
|
+
236: '+xxx xx xx xx xx', // Central African Republic
|
|
75
|
+
237: '+xxx xxxx xxxx', // Cameroon
|
|
76
|
+
238: '+xxx xxxx xxxx', // Cape Verde
|
|
77
|
+
239: '+xxx xxxx xxxx', // Sao Tome and Principe
|
|
78
|
+
240: '+xxx xxx xxxx xxxx', // Equatorial Guinea
|
|
79
|
+
241: '+xxx xxx xxxx xxxx', // Gabon
|
|
80
|
+
242: '+xxx xxx xxxx xxxx', // Republic of the Congo
|
|
81
|
+
243: '+xxx xxx xxxx xxxx', // Democratic Republic of the Congo
|
|
82
|
+
244: '+xxx xxx xxxx xxxx', // Angola
|
|
83
|
+
245: '+xxx xxx xxxx xxxx', // Guinea-Bissau
|
|
84
|
+
246: '+xxx xxx xxxx', // British Indian Ocean Territory
|
|
85
|
+
248: '+xxx xxxx xxxx', // Seychelles
|
|
86
|
+
249: '+xxx xxx xxxx xxxx', // Sudan
|
|
87
|
+
250: '+xxx xxx xxxx xxxx', // Rwanda
|
|
88
|
+
251: '+xxx xxx xxxx xxxx', // Ethiopia
|
|
89
|
+
252: '+xxx xxx xxxx xxxx', // Somalia
|
|
90
|
+
253: '+xxx xxx xxxx xxxx', // Djibouti
|
|
91
|
+
254: '+xxx xxx xxxx xxxx', // Kenya
|
|
92
|
+
255: '+xxx xxx xxxx xxxx', // Tanzania
|
|
93
|
+
256: '+xxx xxx xxxx xxxx', // Uganda
|
|
94
|
+
257: '+xxx xx xx xx xx', // Burundi
|
|
95
|
+
258: '+xxx xxx xxxx xxxx', // Mozambique
|
|
96
|
+
260: '+xxx xxx xxxx xxxx', // Zambia
|
|
97
|
+
261: '+xxx xx xx xx xx', // Madagascar
|
|
98
|
+
263: '+xxx xxx xxxx xxxx', // Zimbabwe
|
|
99
|
+
264: '+xxx xxx xxxx xxxx', // Namibia
|
|
100
|
+
265: '+xxx xxx xxxx xxxx', // Malawi
|
|
101
|
+
266: '+xxx xx xx xx xx', // Lesotho
|
|
102
|
+
267: '+xxx xxx xxxx xxxx', // Botswana
|
|
103
|
+
268: '+xxx xx xx xx xx', // Eswatini
|
|
104
|
+
269: '+xxx xx xx xx xx', // Comoros
|
|
105
|
+
290: '+xxx xxxx xxxx', // Saint Helena
|
|
106
|
+
291: '+xxx xxx xxxx xxxx', // Eritrea
|
|
107
|
+
297: '+xxx xxxx xxxx', // Aruba
|
|
108
|
+
298: '+xxx xxx xxx', // Faroe Islands
|
|
109
|
+
299: '+xxx xxx xxx xxx', // Greenland
|
|
110
|
+
350: '+xxx xxx xxxx xxxx', // Gibraltar
|
|
111
|
+
351: '+xxx xxx xxxx xxxx', // Portugal
|
|
112
|
+
352: '+xxx xxx xxxx xxxx', // Luxembourg
|
|
113
|
+
353: '+xxx xxx xxxx xxxx', // Ireland
|
|
114
|
+
354: '+xxx xxx xxxx xxxx', // Iceland
|
|
115
|
+
355: '+xxx xxx xxxx xxxx', // Albania
|
|
116
|
+
356: '+xxx xx xx xx xx', // Malta
|
|
117
|
+
357: '+xxx xxx xxxx xxxx', // Cyprus
|
|
118
|
+
358: '+xxx xxx xxxx xxxx', // Finland
|
|
119
|
+
359: '+xxx xxx xxxx xxxx', // Bulgaria
|
|
120
|
+
370: '+xxx xxx xxxx xxxx', // Lithuania
|
|
121
|
+
371: '+xxx xxx xxxx xxxx', // Latvia
|
|
122
|
+
372: '+xxx xxx xxxx xxxx', // Estonia
|
|
123
|
+
373: '+xxx xxx xxxx xxxx', // Moldova
|
|
124
|
+
374: '+xxx xxx xxxx xxxx', // Armenia
|
|
125
|
+
375: '+xxx xxx xxxx xxxx', // Belarus
|
|
126
|
+
376: '+xxx xxx xxxx xxxx', // Andorra
|
|
127
|
+
377: '+xxx xxx xxxx xxxx', // Monaco
|
|
128
|
+
378: '+xxx xxx xxxx xxxx', // San Marino
|
|
129
|
+
379: '+xxx xxx xxxx xxxx', // Vatican
|
|
130
|
+
380: '+xxx xxx xxxx xxxx', // Ukraine
|
|
131
|
+
381: '+xxx xxx xxxx xxxx', // Serbia
|
|
132
|
+
382: '+xxx xxx xxxx xxxx', // Montenegro
|
|
133
|
+
383: '+xxx xxx xxxx xxxx', // Kosovo
|
|
134
|
+
385: '+xxx xxx xxxx xxxx', // Croatia
|
|
135
|
+
386: '+xxx xxx xxxx xxxx', // Slovenia
|
|
136
|
+
387: '+xxx xxx xxxx xxxx', // Bosnia and Herzegovina
|
|
137
|
+
389: '+xxx xxx xxxx xxxx', // North Macedonia
|
|
138
|
+
420: '+xxx xxx xxxx xxxx', // Czech Republic
|
|
139
|
+
421: '+xxx xxx xxxx xxxx', // Slovakia
|
|
140
|
+
423: '+xxx xxxx xxxx xxxx', // Liechtenstein
|
|
141
|
+
500: '+xxx xxxx xxxx', // Falkland Islands
|
|
142
|
+
501: '+xxx xxxx xxxx', // Belize
|
|
143
|
+
502: '+xxx xxxx xxxx', // Guatemala
|
|
144
|
+
503: '+xxx xxxx xxxx', // El Salvador
|
|
145
|
+
504: '+xxx xxxx xxxx', // Honduras
|
|
146
|
+
505: '+xxx xxxx xxxx', // Nicaragua
|
|
147
|
+
506: '+xxx xxxx xxxx', // Costa Rica
|
|
148
|
+
507: '+xxx xxxx xxxx', // Panama
|
|
149
|
+
508: '+xxx xxxx xxxx', // Saint Pierre and Miquelon
|
|
150
|
+
509: '+xxx xxxx xxxx', // Haiti
|
|
151
|
+
590: '+xxx xxxx xxxx', // Saint Martin
|
|
152
|
+
591: '+xxx xxx xxxx xxxx', // Bolivia
|
|
153
|
+
592: '+xxx xxxx xxxx', // Guyana
|
|
154
|
+
593: '+xxx xxx xxxx xxxx', // Ecuador
|
|
155
|
+
594: '+xxx xxxx xxxx', // French Guiana
|
|
156
|
+
595: '+xxx xxx xxxx xxxx', // Paraguay
|
|
157
|
+
596: '+xxx xxxx xxxx', // Martinique
|
|
158
|
+
597: '+xxx xxxx xxxx', // Suriname
|
|
159
|
+
598: '+xxx xxx xxxx xxxx', // Uruguay
|
|
160
|
+
599: '+xxx xxxx xxxx xxxx', // Curaçao
|
|
161
|
+
670: '+xxx xxxx xxxx', // East Timor
|
|
162
|
+
672: '+xxx xxxx xxxx', // Antarctica
|
|
163
|
+
673: '+xxx xxxx xxxx', // Brunei
|
|
164
|
+
674: '+xxx xxxx xxxx', // Nauru
|
|
165
|
+
675: '+xxx xxxx xxxx xxxx', // Papua New Guinea
|
|
166
|
+
676: '+xxx xxxx xxxx xxxx', // Tonga
|
|
167
|
+
677: '+xxx xxxx xxxx xxxx', // Solomon Islands
|
|
168
|
+
678: '+xxx xxxx xxxx xxxx', // Vanuatu
|
|
169
|
+
679: '+xxx xxxx xxxx xxxx', // Fiji
|
|
170
|
+
680: '+xxx xxxx xxxx xxxx', // Palau
|
|
171
|
+
681: '+xxx xxxx xxxx xxxx', // Wallis and Futuna
|
|
172
|
+
682: '+xxx xxxx xxxx xxxx', // Cook Islands
|
|
173
|
+
683: '+xxx xxxx xxxx xxxx', // Niue
|
|
174
|
+
685: '+xxx xxxx xxxx xxxx', // Samoa
|
|
175
|
+
686: '+xxx xxxx xxxx xxxx', // Kiribati
|
|
176
|
+
687: '+xxx xxxx xxxx xxxx', // New Caledonia
|
|
177
|
+
688: '+xxx xxxx xxxx xxxx', // Tuvalu
|
|
178
|
+
689: '+xxx xxxx xxxx xxxx', // French Polynesia
|
|
179
|
+
690: '+xxx xxxx xxxx xxxx', // Tokelau
|
|
180
|
+
691: '+xxx xxxx xxxx xxxx', // Micronesia
|
|
181
|
+
692: '+xxx xxxx xxxx xxxx', // Marshall Islands
|
|
182
|
+
850: '+xxx xxxx xxxx xxxx', // North Korea
|
|
183
|
+
852: '+xxx xxxx xxxx xxxx', // Hong Kong
|
|
184
|
+
853: '+xxx xxxx xxxx xxxx', // Macau
|
|
185
|
+
855: '+xxx xxx xxxx xxxx', // Cambodia
|
|
186
|
+
856: '+xxx xxxx xxxx xxxx', // Laos
|
|
187
|
+
880: '+xxx xxx xxxx xxxx', // Bangladesh
|
|
188
|
+
886: '+xxx xxxx xxxx xxxx', // Taiwan
|
|
189
|
+
960: '+xxx xxx xxxx xxxx', // Maldives
|
|
190
|
+
961: '+xxx xxx xxxx xxxx', // Lebanon
|
|
191
|
+
962: '+xxx xxxx xxxx xxxx', // Jordan
|
|
192
|
+
963: '+xxx xxxx xxxx xxxx', // Syria
|
|
193
|
+
964: '+xxx xxxx xxxx xxxx', // Iraq
|
|
194
|
+
965: '+xxx xxxx xxxx xxxx', // Kuwait
|
|
195
|
+
966: '+xxx xxxx xxxx xxxx', // Saudi Arabia
|
|
196
|
+
967: '+xxx xxxx xxxx xxxx', // Yemen
|
|
197
|
+
968: '+xxx xxxx xxxx xxxx', // Oman
|
|
198
|
+
970: '+xxx xxx xxxx xxxx', // Palestine
|
|
199
|
+
971: '+xxx xxx xxxx xxxx', // United Arab Emirates
|
|
200
|
+
972: '+xxx xxxx xxxx xxxx', // Israel
|
|
201
|
+
973: '+xxx xxxx xxxx xxxx', // Bahrain
|
|
202
|
+
974: '+xxx xxxx xxxx xxxx', // Qatar
|
|
203
|
+
975: '+xxx xxxx xxxx xxxx', // Bhutan
|
|
204
|
+
976: '+xxx xxx xxxx xxxx', // Mongolia
|
|
205
|
+
977: '+xxx xxxx xxxx xxxx', // Nepal
|
|
206
|
+
992: '+xxx xxxx xxxx xxxx', // Tajikistan
|
|
207
|
+
993: '+xxx xxx xxxx xxxx', // Turkmenistan
|
|
208
|
+
994: '+xxx xxx xxxx xxxx', // Azerbaijan
|
|
209
|
+
995: '+xxx xxxx xxxx xxxx', // Georgia
|
|
210
|
+
996: '+xxx xxxx xxxx xxxx', // Kyrgyzstan
|
|
211
|
+
998: '+xxx xxxx xxxx xxxx', // Uzbekistan
|
|
212
|
+
};
|