bc-countries
Version:
A convenient Javascript countries utilities (e.g: dial codes, country codes, names)
1,430 lines (1,398 loc) • 20.6 kB
JavaScript
'use strict';
var allCountries = [
[
'Afghanistan (افغانستان)',
'af',
'93'
],
[
'Albania (Shqipëri)',
'al',
'355'
],
[
'Algeria (الجزائر)',
'dz',
'213'
],
[
'American Samoa',
'as',
'1684'
],
[
'Andorra',
'ad',
'376'
],
[
'Angola',
'ao',
'244'
],
[
'Anguilla',
'ai',
'1264'
],
[
'Antigua and Barbuda',
'ag',
'1268'
],
[
'Argentina',
'ar',
'54'
],
[
'Armenia (Հայաստան)',
'am',
'374'
],
[
'Aruba',
'aw',
'297'
],
[
'Australia',
'au',
'61',
0
],
[
'Austria (Österreich)',
'at',
'43'
],
[
'Azerbaijan (Azərbaycan)',
'az',
'994'
],
[
'Bahamas',
'bs',
'1242'
],
[
'Bahrain (البحرين)',
'bh',
'973'
],
[
'Bangladesh (বাংলাদেশ)',
'bd',
'880'
],
[
'Barbados',
'bb',
'1246'
],
[
'Belarus (Беларусь)',
'by',
'375'
],
[
'Belgium (België)',
'be',
'32'
],
[
'Belize',
'bz',
'501'
],
[
'Benin (Bénin)',
'bj',
'229'
],
[
'Bermuda',
'bm',
'1441'
],
[
'Bhutan (འབྲུག)',
'bt',
'975'
],
[
'Bolivia',
'bo',
'591'
],
[
'Bosnia and Herzegovina (Босна и Херцеговина)',
'ba',
'387'
],
[
'Botswana',
'bw',
'267'
],
[
'Brazil (Brasil)',
'br',
'55'
],
[
'British Indian Ocean Territory',
'io',
'246'
],
[
'British Virgin Islands',
'vg',
'1284'
],
[
'Brunei',
'bn',
'673'
],
[
'Bulgaria (България)',
'bg',
'359'
],
[
'Burkina Faso',
'bf',
'226'
],
[
'Burundi (Uburundi)',
'bi',
'257'
],
[
'Cambodia (កម្ពុជា)',
'kh',
'855'
],
[
'Cameroon (Cameroun)',
'cm',
'237'
],
[
'Canada',
'ca',
'1',
1,
['204', '226', '236', '249', '250', '289', '306', '343', '365', '387', '403', '416', '418', '431', '437', '438', '450', '506', '514', '519', '548', '579', '581', '587', '604', '613', '639', '647', '672', '705', '709', '742', '778', '780', '782', '807', '819', '825', '867', '873', '902', '905']
],
[
'Cape Verde (Kabu Verdi)',
'cv',
'238'
],
[
'Caribbean Netherlands',
'bq',
'599',
1
],
[
'Cayman Islands',
'ky',
'1345'
],
[
'Central African Republic (République centrafricaine)',
'cf',
'236'
],
[
'Chad (Tchad)',
'td',
'235'
],
[
'Chile',
'cl',
'56'
],
[
'China (中国)',
'cn',
'86'
],
[
'Christmas Island',
'cx',
'61',
2
],
[
'Cocos (Keeling) Islands',
'cc',
'61',
1
],
[
'Colombia',
'co',
'57'
],
[
'Comoros (جزر القمر)',
'km',
'269'
],
[
'Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)',
'cd',
'243'
],
[
'Congo (Republic) (Congo-Brazzaville)',
'cg',
'242'
],
[
'Cook Islands',
'ck',
'682'
],
[
'Costa Rica',
'cr',
'506'
],
[
'Côte d’Ivoire',
'ci',
'225'
],
[
'Croatia (Hrvatska)',
'hr',
'385'
],
[
'Cuba',
'cu',
'53'
],
[
'Curaçao',
'cw',
'599',
0
],
[
'Cyprus (Κύπρος)',
'cy',
'357'
],
[
'Czech Republic (Česká republika)',
'cz',
'420'
],
[
'Denmark (Danmark)',
'dk',
'45'
],
[
'Djibouti',
'dj',
'253'
],
[
'Dominica',
'dm',
'1767'
],
[
'Dominican Republic (República Dominicana)',
'do',
'1',
2,
['809', '829', '849']
],
[
'Ecuador',
'ec',
'593'
],
[
'Egypt (مصر)',
'eg',
'20'
],
[
'El Salvador',
'sv',
'503'
],
[
'Equatorial Guinea (Guinea Ecuatorial)',
'gq',
'240'
],
[
'Eritrea',
'er',
'291'
],
[
'Estonia (Eesti)',
'ee',
'372'
],
[
'Ethiopia',
'et',
'251'
],
[
'Falkland Islands (Islas Malvinas)',
'fk',
'500'
],
[
'Faroe Islands (Føroyar)',
'fo',
'298'
],
[
'Fiji',
'fj',
'679'
],
[
'Finland (Suomi)',
'fi',
'358',
0
],
[
'France',
'fr',
'33'
],
[
'French Guiana (Guyane française)',
'gf',
'594'
],
[
'French Polynesia (Polynésie française)',
'pf',
'689'
],
[
'Gabon',
'ga',
'241'
],
[
'Gambia',
'gm',
'220'
],
[
'Georgia (საქართველო)',
'ge',
'995'
],
[
'Germany (Deutschland)',
'de',
'49'
],
[
'Ghana (Gaana)',
'gh',
'233'
],
[
'Gibraltar',
'gi',
'350'
],
[
'Greece (Ελλάδα)',
'gr',
'30'
],
[
'Greenland (Kalaallit Nunaat)',
'gl',
'299'
],
[
'Grenada',
'gd',
'1473'
],
[
'Guadeloupe',
'gp',
'590',
0
],
[
'Guam',
'gu',
'1671'
],
[
'Guatemala',
'gt',
'502'
],
[
'Guernsey',
'gg',
'44',
1
],
[
'Guinea (Guinée)',
'gn',
'224'
],
[
'Guinea-Bissau (Guiné Bissau)',
'gw',
'245'
],
[
'Guyana',
'gy',
'592'
],
[
'Haiti',
'ht',
'509'
],
[
'Honduras',
'hn',
'504'
],
[
'Hong Kong (香港)',
'hk',
'852'
],
[
'Hungary (Magyarország)',
'hu',
'36'
],
[
'Iceland (Ísland)',
'is',
'354'
],
[
'India (भारत)',
'in',
'91'
],
[
'Indonesia',
'id',
'62'
],
[
'Iran (ایران)',
'ir',
'98'
],
[
'Iraq (العراق)',
'iq',
'964'
],
[
'Ireland',
'ie',
'353'
],
[
'Isle of Man',
'im',
'44',
2
],
[
'Israel (ישראל)',
'il',
'972'
],
[
'Italy (Italia)',
'it',
'39',
0
],
[
'Jamaica',
'jm',
'1876'
],
[
'Japan (日本)',
'jp',
'81'
],
[
'Jersey',
'je',
'44',
3
],
[
'Jordan (الأردن)',
'jo',
'962'
],
[
'Kazakhstan (Казахстан)',
'kz',
'7',
1
],
[
'Kenya',
'ke',
'254'
],
[
'Kiribati',
'ki',
'686'
],
[
'Kuwait (الكويت)',
'kw',
'965'
],
[
'Kyrgyzstan (Кыргызстан)',
'kg',
'996'
],
[
'Laos (ລາວ)',
'la',
'856'
],
[
'Latvia (Latvija)',
'lv',
'371'
],
[
'Lebanon (لبنان)',
'lb',
'961'
],
[
'Lesotho',
'ls',
'266'
],
[
'Liberia',
'lr',
'231'
],
[
'Libya (ليبيا)',
'ly',
'218'
],
[
'Liechtenstein',
'li',
'423'
],
[
'Lithuania (Lietuva)',
'lt',
'370'
],
[
'Luxembourg',
'lu',
'352'
],
[
'Macau (澳門)',
'mo',
'853'
],
[
'Macedonia (FYROM) (Македонија)',
'mk',
'389'
],
[
'Madagascar (Madagasikara)',
'mg',
'261'
],
[
'Malawi',
'mw',
'265'
],
[
'Malaysia',
'my',
'60'
],
[
'Maldives',
'mv',
'960'
],
[
'Mali',
'ml',
'223'
],
[
'Malta',
'mt',
'356'
],
[
'Marshall Islands',
'mh',
'692'
],
[
'Martinique',
'mq',
'596'
],
[
'Mauritania (موريتانيا)',
'mr',
'222'
],
[
'Mauritius (Moris)',
'mu',
'230'
],
[
'Mayotte',
'yt',
'262',
1
],
[
'Mexico (México)',
'mx',
'52'
],
[
'Micronesia',
'fm',
'691'
],
[
'Moldova (Republica Moldova)',
'md',
'373'
],
[
'Monaco',
'mc',
'377'
],
[
'Mongolia (Монгол)',
'mn',
'976'
],
[
'Montenegro (Crna Gora)',
'me',
'382'
],
[
'Montserrat',
'ms',
'1664'
],
[
'Morocco (المغرب)',
'ma',
'212',
0
],
[
'Mozambique (Moçambique)',
'mz',
'258'
],
[
'Myanmar (Burma) (မြန်မာ)',
'mm',
'95'
],
[
'Namibia (Namibië)',
'na',
'264'
],
[
'Nauru',
'nr',
'674'
],
[
'Nepal (नेपाल)',
'np',
'977'
],
[
'Netherlands (Nederland)',
'nl',
'31'
],
[
'New Caledonia (Nouvelle-Calédonie)',
'nc',
'687'
],
[
'New Zealand',
'nz',
'64'
],
[
'Nicaragua',
'ni',
'505'
],
[
'Niger (Nijar)',
'ne',
'227'
],
[
'Nigeria',
'ng',
'234'
],
[
'Niue',
'nu',
'683'
],
[
'Norfolk Island',
'nf',
'672'
],
[
'North Korea (조선 민주주의 인민 공화국)',
'kp',
'850'
],
[
'Northern Mariana Islands',
'mp',
'1670'
],
[
'Norway (Norge)',
'no',
'47',
0
],
[
'Oman (عُمان)',
'om',
'968'
],
[
'Pakistan (پاکستان)',
'pk',
'92'
],
[
'Palau',
'pw',
'680'
],
[
'Palestine (فلسطين)',
'ps',
'970'
],
[
'Panama (Panamá)',
'pa',
'507'
],
[
'Papua New Guinea',
'pg',
'675'
],
[
'Paraguay',
'py',
'595'
],
[
'Peru (Perú)',
'pe',
'51'
],
[
'Philippines',
'ph',
'63'
],
[
'Poland (Polska)',
'pl',
'48'
],
[
'Portugal',
'pt',
'351'
],
[
'Puerto Rico',
'pr',
'1',
3,
['787', '939']
],
[
'Qatar (قطر)',
'qa',
'974'
],
[
'Réunion (La Réunion)',
're',
'262',
0
],
[
'Romania (România)',
'ro',
'40'
],
[
'Russia (Россия)',
'ru',
'7',
0
],
[
'Rwanda',
'rw',
'250'
],
[
'Saint Barthélemy (Saint-Barthélemy)',
'bl',
'590',
1
],
[
'Saint Helena',
'sh',
'290'
],
[
'Saint Kitts and Nevis',
'kn',
'1869'
],
[
'Saint Lucia',
'lc',
'1758'
],
[
'Saint Martin (Saint-Martin (partie française))',
'mf',
'590',
2
],
[
'Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)',
'pm',
'508'
],
[
'Saint Vincent and the Grenadines',
'vc',
'1784'
],
[
'Samoa',
'ws',
'685'
],
[
'San Marino',
'sm',
'378'
],
[
'São Tomé and Príncipe (São Tomé e Príncipe)',
'st',
'239'
],
[
'Saudi Arabia (المملكة العربية السعودية)',
'sa',
'966'
],
[
'Senegal (Sénégal)',
'sn',
'221'
],
[
'Serbia (Србија)',
'rs',
'381'
],
[
'Seychelles',
'sc',
'248'
],
[
'Sierra Leone',
'sl',
'232'
],
[
'Singapore',
'sg',
'65'
],
[
'Sint Maarten',
'sx',
'1721'
],
[
'Slovakia (Slovensko)',
'sk',
'421'
],
[
'Slovenia (Slovenija)',
'si',
'386'
],
[
'Solomon Islands',
'sb',
'677'
],
[
'Somalia (Soomaaliya)',
'so',
'252'
],
[
'South Africa',
'za',
'27'
],
[
'South Korea (대한민국)',
'kr',
'82'
],
[
'South Sudan (جنوب السودان)',
'ss',
'211'
],
[
'Spain (España)',
'es',
'34'
],
[
'Sri Lanka (ශ්රී ලංකාව)',
'lk',
'94'
],
[
'Sudan (السودان)',
'sd',
'249'
],
[
'Suriname',
'sr',
'597'
],
[
'Svalbard and Jan Mayen',
'sj',
'47',
1
],
[
'Swaziland',
'sz',
'268'
],
[
'Sweden (Sverige)',
'se',
'46'
],
[
'Switzerland (Schweiz)',
'ch',
'41'
],
[
'Syria (سوريا)',
'sy',
'963'
],
[
'Taiwan (台灣)',
'tw',
'886'
],
[
'Tajikistan',
'tj',
'992'
],
[
'Tanzania',
'tz',
'255'
],
[
'Thailand (ไทย)',
'th',
'66'
],
[
'Timor-Leste',
'tl',
'670'
],
[
'Togo',
'tg',
'228'
],
[
'Tokelau',
'tk',
'690'
],
[
'Tonga',
'to',
'676'
],
[
'Trinidad and Tobago',
'tt',
'1868'
],
[
'Tunisia (تونس)',
'tn',
'216'
],
[
'Turkey (Türkiye)',
'tr',
'90'
],
[
'Turkmenistan',
'tm',
'993'
],
[
'Turks and Caicos Islands',
'tc',
'1649'
],
[
'Tuvalu',
'tv',
'688'
],
[
'U.S. Virgin Islands',
'vi',
'1340'
],
[
'Uganda',
'ug',
'256'
],
[
'Ukraine (Україна)',
'ua',
'380'
],
[
'United Arab Emirates (الإمارات العربية المتحدة)',
'ae',
'971'
],
[
'United Kingdom',
'gb',
'44',
0
],
[
'United States',
'us',
'1',
0
],
[
'Uruguay',
'uy',
'598'
],
[
'Uzbekistan (Oʻzbekiston)',
'uz',
'998'
],
[
'Vanuatu',
'vu',
'678'
],
[
'Vatican City (Città del Vaticano)',
'va',
'39',
1
],
[
'Venezuela',
've',
'58'
],
[
'Vietnam (Việt Nam)',
'vn',
'84'
],
[
'Wallis and Futuna',
'wf',
'681'
],
[
'Western Sahara (الصحراء الغربية)',
'eh',
'212',
1
],
[
'Yemen (اليمن)',
'ye',
'967'
],
[
'Zambia',
'zm',
'260'
],
[
'Zimbabwe',
'zw',
'263'
],
[
'Åland Islands',
'ax',
'358',
1
]
];
var libphonenumber = require('google-libphonenumber'),
Trie = require('digits-trie');
// check if given number is valid
function isValidNumberHelper(number, countryCode) {
try {
var phoneUtil = libphonenumber.PhoneNumberUtil.getInstance();
var numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode);
return phoneUtil.isValidNumber(numberObj);
} catch (e) {
return false;
}
}
// format the given number (optionally add any formatting suffix e.g. a hyphen)
function formatNumberHelper(val, countryCode, addSuffix, allowExtension, isAllowedKey) {
try {
var clean = val.replace(/\D/g, ""),
// NOTE: we use AsYouTypeFormatter because the default format function can't handle incomplete numbers e.g. "+17024" formats to "+1 7024" as opposed to "+1 702-4"
formatter = new libphonenumber.AsYouTypeFormatter(countryCode),
// if clean is empty, we still need this to be a string otherwise we get errors later
result = "",
next,
extSuffix = " ext. ";
if (val.substr(0, 1) == "+") {
clean = "+" + clean;
}
for (var i = 0; i < clean.length; i++) {
// TODO: improve this so don't just pump in every digit every time - we should just cache this formatter object, and just call inputDigit once each time the user enters a new digit
next = formatter.inputDigit(clean.charAt(i));
// if adding this char didn't change the length, or made it smaller (and there's no longer any spaces): that means that formatting failed which means the number was no longer a potentially valid number, so if we're allowing extensions: assume the rest is the ext
if (allowExtension && result && next.length <= result.length && next.indexOf(" ") == -1) {
// set flag for extension
next = -1;
break;
}
result = next;
}
// for some reason libphonenumber formats "+44" to "+44 ", but doesn't do the same with "+1"
if (result.charAt(result.length - 1) == " ") {
result = result.substr(0, result.length - 1);
}
// check if there's a suffix to add (unless there's an ext)
if (addSuffix && !val.split(extSuffix)[1]) {
// hack to get formatting suffix
var test = formatter.inputDigit('5');
// again the "+44 " problem... (also affects "+45" apparently)
if (test.charAt(test.length - 1) == " ") {
test = test.substr(0, test.length - 1);
}
// if adding a '5' introduces a formatting char - check if the penultimate char is not-a-number
var penultimate = test.substr(test.length - 2, 1);
// Note: never use isNaN without parseFloat
if (isNaN(parseFloat(penultimate))) {
// return the new value (minus that last '5' we just added)
return test.substr(0, test.length - 1);
} else if (allowExtension && result && test.length <= result.length && test.indexOf(" ") == -1 && !isAllowedKey) {
// else if the next digit would break the formating, and we're allowing extensions, AND this is not an allowed key: add the suffix
// NOTE: we must check this is not an allowed key because if it was that means it was the last digit in a valid number and we dont want to add the "ext" suffix in that case. This whole condition is just here to catch the case that: after typing a valid number, they try to type "ext" - this will not automatically add it for them.
return result + extSuffix;
}
}
// if the clean number contains an extension we need to add it
if (next == -1) {
result += extSuffix + clean.substring(i, clean.length);
}
return result;
} catch (e) {
return val;
}
}
var iso2Countries = {};
var dialCodes = new Trie();
for (var i = 0; i < allCountries.length; i++) {
var country = allCountries[i];
var dialCode = country[2];
var iso2 = country[1];
dialCodes.set(dialCode, iso2);
iso2Countries[iso2] = country;
}
function makeCountry (country) {
return {
dialCode: country[2],
iso2Code: country[1],
name: country[0]
};
}
function getDialCodeByDigits (digits) {
if (!digits) { return ''; }
else { return dialCodes.longestMatchingPrefix(digits).key; }
}
function getIso2CodeByDigits (digits) {
if (!digits) { return ''; }
else { return dialCodes.longestMatchingPrefix(digits).value; }
}
function getCountryByIso2Code (iso2) {
var country = iso2Countries[iso2];
if (country) { return makeCountry(iso2Countries[iso2]); }
else { return null; }
}
function getAllCountries () {
var countries = new Array(allCountries.length);
for (var i = 0; i < allCountries.length; i++) { countries[i] = makeCountry(allCountries[i]); }
return countries;
}
function hasPrefix (number) {
return (number[0] === '+');
}
function getDigits (number) {
if (!number) { return ''; }
else { return number.replace(/\D/g, ''); }
}
function prefixNumber (number) {
if (number && !hasPrefix(number)) { return ('+' + number); }
else { return number; }
}
function formatNumber (number) {
if (!number) { return ''; }
else {
var dialCode = getDialCodeByDigits(getDigits(number));
if (dialCode) { return formatNumberHelper(prefixNumber(number)); }
else { return number; }
}
}
function changeDialCode (number, newDialCode) {
if (!number) { return ('+' + newDialCode); }
else {
var digits = getDigits(number);
var oldDialCode = getDialCodeByDigits(digits);
if (oldDialCode) {
var numberWithNewDialCode = digits.replace(oldDialCode, newDialCode);
var formattedNumber = formatNumber(numberWithNewDialCode);
return formattedNumber;
}
else { return formatNumber('+' + newDialCode + digits); }
}
}
function isValidNumber (number) {
if (!number || !hasPrefix(number)) { return false; }
else {
var digits = getDigits(number);
var iso2Code = getIso2CodeByDigits(digits);
if (iso2Code) { return isValidNumberHelper(number, iso2Code); }
else { return false; }
}
}
module.exports = {
getCountryByIso2Code: getCountryByIso2Code,
getDialCodeByDigits: getDialCodeByDigits,
getIso2CodeByDigits: getIso2CodeByDigits,
getAllCountries: getAllCountries,
changeDialCode: changeDialCode,
isValidNumber: isValidNumber,
formatNumber: formatNumber,
getDigits: getDigits
};