2020-11-05 18:58:23 +02:00
const { sprintf } = require ( 'sprintf-js' ) ;
interface StringToStringMap {
2020-11-12 21:29:22 +02:00
[ key : string ] : string ;
2020-11-05 18:58:23 +02:00
}
interface CodeToCountryMap {
2020-11-12 21:29:22 +02:00
[ key : string ] : string [ ] ;
2020-11-05 18:58:23 +02:00
}
2023-10-11 11:17:46 +02:00
type ParsePluralFormFunction = ( n : number ) = > number ;
2020-11-05 18:58:23 +02:00
2024-03-18 14:16:17 +02:00
interface Iso639Item {
alpha3 : string ;
alpha2 : string ;
nameEnglish : string ;
nameNative : string ;
}
type Iso639Line = [ string , string , string , string ? ] ;
// cSpell:disable
// Source: https://www.loc.gov/standards/iso639-2/php/code_list.php
// ISO 639-2 Code, ISO 639-1 Code, English name of Language
const iso639_ : Iso639Line [ ] = [
[ 'aar' , 'aa' , 'Afar' ] ,
[ 'abk' , 'ab' , 'Abkhazian' ] ,
[ 'ave' , 'ae' , 'Avestan' ] ,
[ 'afr' , 'af' , 'Afrikaans' ] ,
[ 'aka' , 'ak' , 'Akan' ] ,
[ 'amh' , 'am' , 'Amharic' ] ,
[ 'arg' , 'an' , 'Aragonese' , 'Aragonés' ] ,
[ 'ara' , 'ar' , 'Arabic' ] ,
[ 'asm' , 'as' , 'Assamese' ] ,
[ 'ava' , 'av' , 'Avaric' ] ,
[ 'aym' , 'ay' , 'Aymara' ] ,
[ 'aze' , 'az' , 'Azerbaijani' ] ,
[ 'bak' , 'ba' , 'Bashkir' ] ,
[ 'bel' , 'be' , 'Belarusian' ] ,
[ 'bul' , 'bg' , 'Bulgarian' ] ,
[ 'bih' , 'bh' , 'Bihari languages' ] ,
[ 'bis' , 'bi' , 'Bislama' ] ,
[ 'bam' , 'bm' , 'Bambara' ] ,
[ 'ben' , 'bn' , 'Bengali' ] ,
[ 'bod' , 'bo' , 'Tibetan' ] ,
[ 'bre' , 'br' , 'Breton' ] ,
[ 'bos' , 'bs' , 'Bosnian' ] ,
[ 'cat' , 'ca' , 'Catalan; Valencian' ] ,
[ 'che' , 'ce' , 'Chechen' ] ,
[ 'cha' , 'ch' , 'Chamorro' ] ,
[ 'cos' , 'co' , 'Corsican' ] ,
[ 'cre' , 'cr' , 'Cree' ] ,
[ 'ces' , 'cs' , 'Czech' ] ,
[ 'chu' , 'cu' , 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic' ] ,
[ 'chv' , 'cv' , 'Chuvash' ] ,
[ 'cym' , 'cy' , 'Welsh' ] ,
[ 'dan' , 'da' , 'Danish' , 'Dansk' ] ,
[ 'deu' , 'de' , 'German' , 'Deutsch' ] ,
[ 'div' , 'dv' , 'Divehi; Dhivehi; Maldivian' ] ,
[ 'dzo' , 'dz' , 'Dzongkha' ] ,
[ 'ewe' , 'ee' , 'Ewe' ] ,
[ 'ell' , 'el' , 'Greek, Modern (1453-)' , 'Ελληνικά' ] ,
[ 'eng' , 'en' , 'English' , 'English' ] ,
[ 'epo' , 'eo' , 'Esperanto' ] ,
[ 'spa' , 'es' , 'Spanish; Castilian' , 'Español' ] ,
[ 'est' , 'et' , 'Estonian' , 'Eesti Keel' ] ,
[ 'eus' , 'eu' , 'Basque' ] ,
[ 'fas' , 'fa' , 'Persian' ] ,
[ 'ful' , 'ff' , 'Fulah' ] ,
[ 'fin' , 'fi' , 'Finnish' ] ,
[ 'fij' , 'fj' , 'Fijian' ] ,
[ 'fao' , 'fo' , 'Faroese' ] ,
[ 'fra' , 'fr' , 'French' , 'Français' ] ,
[ 'fry' , 'fy' , 'Western Frisian' ] ,
[ 'gle' , 'ga' , 'Irish' ] ,
[ 'gla' , 'gd' , 'Gaelic; Scottish Gaelic' ] ,
[ 'glg' , 'gl' , 'Galician' ] ,
[ 'grn' , 'gn' , 'Guarani' ] ,
[ 'guj' , 'gu' , 'Gujarati' ] ,
[ 'glv' , 'gv' , 'Manx' ] ,
[ 'hau' , 'ha' , 'Hausa' ] ,
[ 'heb' , 'he' , 'Hebrew' , 'עיברית' ] ,
[ 'hin' , 'hi' , 'Hindi' ] ,
[ 'hmo' , 'ho' , 'Hiri Motu' ] ,
[ 'hrv' , 'hr' , 'Croatian' ] ,
[ 'hat' , 'ht' , 'Haitian; Haitian Creole' ] ,
[ 'hun' , 'hu' , 'Hungarian' , 'Magyar' ] ,
[ 'hye' , 'hy' , 'Armenian' ] ,
[ 'her' , 'hz' , 'Herero' ] ,
[ 'ina' , 'ia' , 'Interlingua (International Auxiliary Language Association)' ] ,
[ 'ind' , 'id' , 'Indonesian' ] ,
[ 'ile' , 'ie' , 'Interlingue; Occidental' ] ,
[ 'ibo' , 'ig' , 'Igbo' ] ,
[ 'iii' , 'ii' , 'Sichuan Yi; Nuosu' ] ,
[ 'ipk' , 'ik' , 'Inupiaq' ] ,
[ 'ido' , 'io' , 'Ido' ] ,
[ 'isl' , 'is' , 'Icelandic' ] ,
[ 'ita' , 'it' , 'Italian' , 'Italiano' ] ,
[ 'iku' , 'iu' , 'Inuktitut' ] ,
[ 'jpn' , 'ja' , 'Japanese' , '日本語' ] ,
[ 'jav' , 'jv' , 'Javanese' ] ,
[ 'kat' , 'ka' , 'Georgian' ] ,
[ 'kon' , 'kg' , 'Kongo' ] ,
[ 'kik' , 'ki' , 'Kikuyu; Gikuyu' ] ,
[ 'kua' , 'kj' , 'Kuanyama; Kwanyama' ] ,
[ 'kaz' , 'kk' , 'Kazakh' ] ,
[ 'kal' , 'kl' , 'Kalaallisut; Greenlandic' ] ,
[ 'khm' , 'km' , 'Central Khmer' ] ,
[ 'kan' , 'kn' , 'Kannada' ] ,
[ 'kor' , 'ko' , 'Korean' , '한국어' ] ,
[ 'kau' , 'kr' , 'Kanuri' ] ,
[ 'kas' , 'ks' , 'Kashmiri' ] ,
[ 'kur' , 'ku' , 'Kurdish' ] ,
[ 'kom' , 'kv' , 'Komi' ] ,
[ 'cor' , 'kw' , 'Cornish' ] ,
[ 'kir' , 'ky' , 'Kirghiz; Kyrgyz' ] ,
[ 'lat' , 'la' , 'Latin' ] ,
[ 'ltz' , 'lb' , 'Luxembourgish; Letzeburgesch' ] ,
[ 'lug' , 'lg' , 'Ganda' ] ,
[ 'lim' , 'li' , 'Limburgan; Limburger; Limburgish' ] ,
[ 'lin' , 'ln' , 'Lingala' ] ,
[ 'lao' , 'lo' , 'Lao' ] ,
[ 'lit' , 'lt' , 'Lithuanian' , 'Lietuvių kalba' ] ,
[ 'lub' , 'lu' , 'Luba-Katanga' ] ,
[ 'lav' , 'lv' , 'Latvian' , 'Latviešu' ] ,
[ 'mlg' , 'mg' , 'Malagasy' ] ,
[ 'mah' , 'mh' , 'Marshallese' ] ,
[ 'mri' , 'mi' , 'Maori' ] ,
[ 'mkd' , 'mk' , 'Macedonian' ] ,
[ 'mal' , 'ml' , 'Malayalam' ] ,
[ 'mon' , 'mn' , 'Mongolian' ] ,
[ 'mar' , 'mr' , 'Marathi' ] ,
[ 'msa' , 'ms' , 'Malay' ] ,
[ 'mlt' , 'mt' , 'Maltese' ] ,
[ 'mya' , 'my' , 'Burmese' ] ,
[ 'nau' , 'na' , 'Nauru' ] ,
[ 'nob' , 'nb' , 'Bokmål, Norwegian; Norwegian Bokmål' ] ,
[ 'nde' , 'nd' , 'Ndebele, North; North Ndebele' ] ,
[ 'nep' , 'ne' , 'Nepali' ] ,
[ 'ndo' , 'ng' , 'Ndonga' ] ,
[ 'nld' , 'nl' , 'Dutch; Flemish' , 'Nederlands' ] ,
[ 'nno' , 'nn' , 'Norwegian Nynorsk; Nynorsk, Norwegian' ] ,
[ 'nor' , 'no' , 'Norwegian' ] ,
[ 'nbl' , 'nr' , 'Ndebele, South; South Ndebele' ] ,
[ 'nav' , 'nv' , 'Navajo; Navaho' ] ,
[ 'nya' , 'ny' , 'Chichewa; Chewa; Nyanja' ] ,
[ 'oci' , 'oc' , 'Occitan (post 1500)' ] ,
[ 'oji' , 'oj' , 'Ojibwa' ] ,
[ 'orm' , 'om' , 'Oromo' ] ,
[ 'ori' , 'or' , 'Oriya' ] ,
[ 'oss' , 'os' , 'Ossetian; Ossetic' ] ,
[ 'pan' , 'pa' , 'Panjabi; Punjabi' ] ,
[ 'pli' , 'pi' , 'Pali' ] ,
[ 'pol' , 'pl' , 'Polish' , 'Polski' ] ,
[ 'pus' , 'ps' , 'Pushto; Pashto' ] ,
[ 'por' , 'pt' , 'Portuguese' , 'Português' ] ,
[ 'que' , 'qu' , 'Quechua' ] ,
[ 'roh' , 'rm' , 'Romansh' ] ,
[ 'run' , 'rn' , 'Rundi' ] ,
[ 'ron' , 'ro' , 'Romanian; Moldavian; Moldovan' , 'Română' ] ,
[ 'rus' , 'ru' , 'Russian' , 'Русский' ] ,
[ 'kin' , 'rw' , 'Kinyarwanda' ] ,
[ 'san' , 'sa' , 'Sanskrit' ] ,
[ 'srd' , 'sc' , 'Sardinian' ] ,
[ 'snd' , 'sd' , 'Sindhi' ] ,
[ 'sme' , 'se' , 'Northern Sami' ] ,
[ 'sag' , 'sg' , 'Sango' ] ,
[ 'sin' , 'si' , 'Sinhala; Sinhalese' ] ,
[ 'slk' , 'sk' , 'Slovak' , 'Slovenčina' ] ,
[ 'slv' , 'sl' , 'Slovenian' ] ,
[ 'smo' , 'sm' , 'Samoan' ] ,
[ 'sna' , 'sn' , 'Shona' ] ,
[ 'som' , 'so' , 'Somali' ] ,
[ 'sqi' , 'sq' , 'Albanian' , 'Shqip' ] ,
[ 'srp' , 'sr' , 'Serbian' , 'српски језик' ] ,
[ 'ssw' , 'ss' , 'Swati' ] ,
[ 'sot' , 'st' , 'Sotho, Southern' ] ,
[ 'sun' , 'su' , 'Sundanese' ] ,
[ 'swe' , 'sv' , 'Swedish' , 'Svenska' ] ,
[ 'swa' , 'sw' , 'Swahili' ] ,
[ 'tam' , 'ta' , 'Tamil' ] ,
[ 'tel' , 'te' , 'Telugu' ] ,
[ 'tgk' , 'tg' , 'Tajik' ] ,
[ 'tha' , 'th' , 'Thai' ] ,
[ 'tir' , 'ti' , 'Tigrinya' ] ,
[ 'tuk' , 'tk' , 'Turkmen' ] ,
[ 'tgl' , 'tl' , 'Tagalog' ] ,
[ 'tsn' , 'tn' , 'Tswana' ] ,
[ 'ton' , 'to' , 'Tonga (Tonga Islands)' ] ,
[ 'tur' , 'tr' , 'Turkish' , 'Türkçe' ] ,
[ 'tso' , 'ts' , 'Tsonga' ] ,
[ 'tat' , 'tt' , 'Tatar' ] ,
[ 'twi' , 'tw' , 'Twi' ] ,
[ 'tah' , 'ty' , 'Tahitian' ] ,
[ 'uig' , 'ug' , 'Uighur; Uyghur' ] ,
[ 'ukr' , 'uk' , 'Ukrainian' ] ,
[ 'urd' , 'ur' , 'Urdu' ] ,
[ 'uzb' , 'uz' , 'Uzbek' ] ,
[ 'ven' , 've' , 'Venda' ] ,
[ 'vie' , 'vi' , 'Vietnamese' , 'Tiếng Việt' ] ,
[ 'vol' , 'vo' , 'Volapük' ] ,
[ 'wln' , 'wa' , 'Walloon' ] ,
[ 'wol' , 'wo' , 'Wolof' ] ,
[ 'xho' , 'xh' , 'Xhosa' ] ,
[ 'yid' , 'yi' , 'Yiddish' ] ,
[ 'yor' , 'yo' , 'Yoruba' ] ,
[ 'zha' , 'za' , 'Zhuang; Chuang' ] ,
[ 'zho' , 'zh' , 'Chinese' , '中文' ] ,
[ 'zul' , 'zu' , 'Zulu' ] ,
2023-12-13 21:24:58 +02:00
] ;
2024-03-18 14:16:17 +02:00
// cSpell:enable
2023-12-13 21:24:58 +02:00
2020-11-12 21:13:28 +02:00
const codeToCountry_ : CodeToCountryMap = {
2020-11-05 18:58:23 +02:00
AD : [ 'Andorra' , 'Andorra' ] ,
AE : [ 'United Arab Emirates' , 'دولة الإمارات العربيّة المتّحدة' ] ,
AF : [ 'Afghanistan' , 'د افغانستان اسلامي دولتدولت اسلامی افغانستان, جمهوری اسلامی افغانستان' ] ,
AG : [ 'Antigua and Barbuda' , 'Antigua and Barbuda' ] ,
AI : [ 'Anguilla' , 'Anguilla' ] ,
AL : [ 'Albania' , 'Shqipëria' ] ,
AM : [ 'Armenia' , 'Հայաստան' ] ,
AO : [ 'Angola' , 'Angola' ] ,
AQ : [ 'Antarctica' , 'Antarctica, Antártico, Antarctique, Антарктике' ] ,
AR : [ 'Argentina' , 'Argentina' ] ,
AS : [ 'American Samoa' , 'American Samoa' ] ,
AT : [ 'Austria' , 'Österreich' ] ,
AU : [ 'Australia' , 'Australia' ] ,
AW : [ 'Aruba' , 'Aruba' ] ,
AX : [ 'Aland Islands' , 'Åland' ] ,
AZ : [ 'Azerbaijan' , 'Azərbaycan' ] ,
BA : [ 'Bosnia and Herzegovina' , 'Bosna i Hercegovina' ] ,
BB : [ 'Barbados' , 'Barbados' ] ,
BD : [ 'Bangladesh' , 'গণপ্রজাতন্ত্রী বাংলাদেশ' ] ,
BE : [ 'Belgium' , 'België, Belgique, Belgien' ] ,
BF : [ 'Burkina Faso' , 'Burkina Faso' ] ,
BG : [ 'Bulgaria' , 'България' ] ,
BH : [ 'Bahrain' , 'البحرين' ] ,
BI : [ 'Burundi' , 'Burundi' ] ,
BJ : [ 'Benin' , 'Bénin' ] ,
BL : [ 'Saint-Barthélemy' , 'Saint-Barthélemy' ] ,
BM : [ 'Bermuda' , 'Bermuda' ] ,
BN : [ 'Brunei Darussalam' , 'Brunei Darussalam' ] ,
BO : [ 'Bolivia' , 'Bolivia, Bulibiya, Volívia, Wuliwya' ] ,
BQ : [ 'Caribbean Netherlands' , 'Caribisch Nederland' ] ,
BR : [ 'Brazil' , 'Brasil' ] ,
BS : [ 'Bahamas' , 'Bahamas' ] ,
BT : [ 'Bhutan' , 'འབྲུག་ཡུལ' ] ,
BV : [ 'Bouvet Island' , 'Bouvetøya' ] ,
BW : [ 'Botswana' , 'Botswana' ] ,
BY : [ 'Belarus' , 'Беларусь' ] ,
BZ : [ 'Belize' , 'Belize' ] ,
CA : [ 'Canada' , 'Canada' ] ,
CC : [ 'Cocos (Keeling) Islands' , 'Cocos (Keeling) Islands' ] ,
CD : [ 'Democratic Republic of the Congo (Congo-Kinshasa, former Zaire)' , 'République Démocratique du Congo' ] ,
CF : [ 'Centrafrican Republic' , 'République centrafricaine, Ködörösêse tî Bêafrîka' ] ,
CG : [ 'Republic of the Congo (Congo-Brazzaville)' , 'République du Congo' ] ,
CH : [ 'Switzerland' , 'Schweiz, Suisse, Svizzera, Svizra' ] ,
CI : [ 'Côte d\'Ivoire' , 'Côte d\'Ivoire' ] ,
CK : [ 'Cook Islands' , 'Cook Islands, Kūki ʻĀirani' ] ,
CL : [ 'Chile' , 'Chile' ] ,
CM : [ 'Cameroon' , 'Cameroun, Cameroon' ] ,
CN : [ 'China' , '中国' ] ,
CO : [ 'Colombia' , 'Colombia' ] ,
CR : [ 'Costa Rica' , 'Costa Rica' ] ,
CU : [ 'Cuba' , 'Cuba' ] ,
CV : [ 'Cabo Verde' , 'Cabo Verde' ] ,
CW : [ 'Curaçao' , 'Curaçao' ] ,
CX : [ 'Christmas Island' , 'Christmas Island' ] ,
CY : [ 'Cyprus' , 'Κύπρος, Kibris' ] ,
CZ : [ 'Czech Republic' , 'Česká republika' ] ,
DE : [ 'Germany' , 'Deutschland' ] ,
DJ : [ 'Djibouti' , 'Djibouti, جيبوتي, Jabuuti, Gabuutih' ] ,
DK : [ 'Denmark' , 'Danmark' ] ,
DM : [ 'Dominica' , 'Dominica' ] ,
DO : [ 'Dominican Republic' , 'República Dominicana' ] ,
DZ : [ 'Algeria' , 'الجزائر' ] ,
EC : [ 'Ecuador' , 'Ecuador' ] ,
EE : [ 'Estonia' , 'Eesti' ] ,
EG : [ 'Egypt' , 'مصر' ] ,
EH : [ 'Western Sahara' , 'Sahara Occidental' ] ,
ER : [ 'Eritrea' , 'ኤርትራ, إرتريا, Eritrea' ] ,
ES : [ 'Spain' , 'España' ] ,
ET : [ 'Ethiopia' , 'ኢትዮጵያ, Itoophiyaa' ] ,
FI : [ 'Finland' , 'Suomi' ] ,
FJ : [ 'Fiji' , 'Fiji' ] ,
FK : [ 'Falkland Islands' , 'Falkland Islands' ] ,
FM : [ 'Micronesia (Federated States of)' , 'Micronesia' ] ,
FO : [ 'Faroe Islands' , 'Føroyar, Færøerne' ] ,
FR : [ 'France' , 'France' ] ,
GA : [ 'Gabon' , 'Gabon' ] ,
GB : [ 'United Kingdom' , 'United Kingdom' ] ,
GD : [ 'Grenada' , 'Grenada' ] ,
GE : [ 'Georgia' , 'საქართველო' ] ,
GF : [ 'French Guiana' , 'Guyane française' ] ,
GG : [ 'Guernsey' , 'Guernsey' ] ,
GH : [ 'Ghana' , 'Ghana' ] ,
GI : [ 'Gibraltar' , 'Gibraltar' ] ,
GL : [ 'Greenland' , 'Kalaallit Nunaat, Grønland' ] ,
GM : [ 'The Gambia' , 'The Gambia' ] ,
GN : [ 'Guinea' , 'Guinée' ] ,
GP : [ 'Guadeloupe' , 'Guadeloupe' ] ,
GQ : [ 'Equatorial Guinea' , 'Guiena ecuatorial, Guinée équatoriale, Guiné Equatorial' ] ,
GR : [ 'Greece' , 'Ελλάδα' ] ,
GS : [ 'South Georgia and the South Sandwich Islands' , 'South Georgia and the South Sandwich Islands' ] ,
GT : [ 'Guatemala' , 'Guatemala' ] ,
GU : [ 'Guam' , 'Guam, Guåhån' ] ,
GW : [ 'Guinea Bissau' , 'Guiné-Bissau' ] ,
GY : [ 'Guyana' , 'Guyana' ] ,
HK : [ 'Hong Kong (SAR of China)' , '香港, Hong Kong' ] ,
HM : [ 'Heard Island and McDonald Islands' , 'Heard Island and McDonald Islands' ] ,
HN : [ 'Honduras' , 'Honduras' ] ,
HR : [ 'Croatia' , 'Hrvatska' ] ,
HT : [ 'Haiti' , 'Haïti, Ayiti' ] ,
HU : [ 'Hungary' , 'Magyarország' ] ,
ID : [ 'Indonesia' , 'Indonesia' ] ,
IE : [ 'Ireland' , 'Ireland, Éire' ] ,
IL : [ 'Israel' , 'ישראל' ] ,
IM : [ 'Isle of Man' , 'Isle of Man' ] ,
IN : [ 'India' , 'भारत, India' ] ,
IO : [ 'British Indian Ocean Territory' , 'British Indian Ocean Territory' ] ,
IQ : [ 'Iraq' , 'العراق, Iraq' ] ,
IR : [ 'Iran' , 'ایران' ] ,
IS : [ 'Iceland' , 'Ísland' ] ,
IT : [ 'Italy' , 'Italia' ] ,
JE : [ 'Jersey' , 'Jersey' ] ,
JM : [ 'Jamaica' , 'Jamaica' ] ,
JO : [ 'Jordan' , 'الأُرْدُن' ] ,
JP : [ 'Japan' , '日本' ] ,
KE : [ 'Kenya' , 'Kenya' ] ,
KG : [ 'Kyrgyzstan' , 'Кыргызстан, Киргизия' ] ,
KH : [ 'Cambodia' , 'កម្ពុជា' ] ,
KI : [ 'Kiribati' , 'Kiribati' ] ,
KM : [ 'Comores' , 'ﺍﻟﻘﻤﺮي, Comores, Komori' ] ,
KN : [ 'Saint Kitts and Nevis' , 'Saint Kitts and Nevis' ] ,
KP : [ 'North Korea' , '북조선' ] ,
KR : [ 'South Korea' , '대한민국' ] ,
KW : [ 'Kuwait' , 'الكويت' ] ,
KY : [ 'Cayman Islands' , 'Cayman Islands' ] ,
KZ : [ 'Kazakhstan' , 'Қазақстан, Казахстан' ] ,
LA : [ 'Laos' , 'ປະຊາຊົນລາວ' ] ,
LB : [ 'Lebanon' , 'لبنان, Liban' ] ,
LC : [ 'Saint Lucia' , 'Saint Lucia' ] ,
LI : [ 'Liechtenstein' , 'Liechtenstein' ] ,
LK : [ 'Sri Lanka' , 'ශ්රී ලංකා, இலங்கை' ] ,
LR : [ 'Liberia' , 'Liberia' ] ,
LS : [ 'Lesotho' , 'Lesotho' ] ,
LT : [ 'Lithuania' , 'Lietuva' ] ,
LU : [ 'Luxembourg' , 'Lëtzebuerg, Luxembourg, Luxemburg' ] ,
LV : [ 'Latvia' , 'Latvija' ] ,
LY : [ 'Libya' , 'ليبيا' ] ,
MA : [ 'Morocco' , 'Maroc, ⵍⵎⵖⵔⵉⴱ, المغرب' ] ,
MC : [ 'Monaco' , 'Monaco' ] ,
MD : [ 'Moldova' , 'Moldova, Молдавия' ] ,
ME : [ 'Montenegro' , 'Crna Gora, Црна Гора' ] ,
MF : [ 'Saint Martin (French part)' , 'Saint-Martin' ] ,
MG : [ 'Madagascar' , 'Madagasikara, Madagascar' ] ,
MH : [ 'Marshall Islands' , 'Marshall Islands' ] ,
MK : [ 'North Macedonia' , 'Северна Македонија' ] ,
ML : [ 'Mali' , 'Mali' ] ,
MM : [ 'Myanmar' , 'မြန်မာ' ] ,
MN : [ 'Mongolia' , 'Монгол Улс' ] ,
MO : [ 'Macao (SAR of China)' , '澳門, Macau' ] ,
MP : [ 'Northern Mariana Islands' , 'Northern Mariana Islands' ] ,
MQ : [ 'Martinique' , 'Martinique' ] ,
MR : [ 'Mauritania' , 'موريتانيا, Mauritanie' ] ,
MS : [ 'Montserrat' , 'Montserrat' ] ,
MT : [ 'Malta' , 'Malta' ] ,
MU : [ 'Mauritius' , 'Maurice, Mauritius' ] ,
MV : [ 'Maldives' , '' ] ,
MW : [ 'Malawi' , 'Malawi' ] ,
MX : [ 'Mexico' , 'México' ] ,
MY : [ 'Malaysia' , '' ] ,
MZ : [ 'Mozambique' , 'Mozambique' ] ,
NA : [ 'Namibia' , 'Namibia' ] ,
NC : [ 'New Caledonia' , 'Nouvelle-Calédonie' ] ,
NE : [ 'Niger' , 'Niger' ] ,
NF : [ 'Norfolk Island' , 'Norfolk Island' ] ,
NG : [ 'Nigeria' , 'Nigeria' ] ,
NI : [ 'Nicaragua' , 'Nicaragua' ] ,
NL : [ 'The Netherlands' , 'Nederland' ] ,
NO : [ 'Norway' , 'Norge, Noreg' ] ,
NP : [ 'Nepal' , '' ] ,
NR : [ 'Nauru' , 'Nauru' ] ,
NU : [ 'Niue' , 'Niue' ] ,
NZ : [ 'New Zealand' , 'New Zealand' ] ,
OM : [ 'Oman' , 'سلطنة عُمان' ] ,
PA : [ 'Panama' , 'Panama' ] ,
PE : [ 'Peru' , 'Perú' ] ,
PF : [ 'French Polynesia' , 'Polynésie française' ] ,
PG : [ 'Papua New Guinea' , 'Papua New Guinea' ] ,
PH : [ 'Philippines' , 'Philippines' ] ,
PK : [ 'Pakistan' , 'پاکستان' ] ,
PL : [ 'Poland' , 'Polska' ] ,
PM : [ 'Saint Pierre and Miquelon' , 'Saint-Pierre-et-Miquelon' ] ,
PN : [ 'Pitcairn' , 'Pitcairn' ] ,
PR : [ 'Puerto Rico' , 'Puerto Rico' ] ,
PS : [ 'Palestinian Territory' , 'Palestinian Territory' ] ,
PT : [ 'Portugal' , 'Portugal' ] ,
PW : [ 'Palau' , 'Palau' ] ,
PY : [ 'Paraguay' , 'Paraguay' ] ,
QA : [ 'Qatar' , 'قطر' ] ,
RE : [ 'Reunion' , 'La Réunion' ] ,
RO : [ 'Romania' , 'România' ] ,
RS : [ 'Serbia' , 'Србија' ] ,
RU : [ 'Russia' , 'Россия' ] ,
RW : [ 'Rwanda' , 'Rwanda' ] ,
SA : [ 'Saudi Arabia' , 'السعودية' ] ,
SB : [ 'Solomon Islands' , 'Solomon Islands' ] ,
SC : [ 'Seychelles' , 'Seychelles' ] ,
SD : [ 'Sudan' , 'السودان' ] ,
SE : [ 'Sweden' , 'Sverige' ] ,
SG : [ 'Singapore' , 'Singapore' ] ,
SH : [ 'Saint Helena' , 'Saint Helena' ] ,
SI : [ 'Slovenia' , 'Slovenija' ] ,
SJ : [ 'Svalbard and Jan Mayen' , 'Svalbard and Jan Mayen' ] ,
SK : [ 'Slovakia' , 'Slovensko' ] ,
SL : [ 'Sierra Leone' , 'Sierra Leone' ] ,
SM : [ 'San Marino' , 'San Marino' ] ,
SN : [ 'Sénégal' , 'Sénégal' ] ,
SO : [ 'Somalia' , 'Somalia, الصومال' ] ,
SR : [ 'Suriname' , 'Suriname' ] ,
ST : [ 'São Tomé and Príncipe' , 'São Tomé e Príncipe' ] ,
SS : [ 'South Sudan' , 'South Sudan' ] ,
SV : [ 'El Salvador' , 'El Salvador' ] ,
SX : [ 'Saint Martin (Dutch part)' , 'Sint Maarten' ] ,
SY : [ 'Syria' , 'سوريا, Sūriyya' ] ,
SZ : [ 'eSwatini' , 'eSwatini' ] ,
TC : [ 'Turks and Caicos Islands' , 'Turks and Caicos Islands' ] ,
TD : [ 'Chad' , 'Tchad, تشاد' ] ,
TF : [ 'French Southern and Antarctic Lands' , 'Terres australes et antarctiques françaises' ] ,
TG : [ 'Togo' , 'Togo' ] ,
TH : [ 'Thailand' , 'ประเทศไทย' ] ,
TJ : [ 'Tajikistan' , ',' ] ,
TK : [ 'Tokelau' , 'Tokelau' ] ,
TL : [ 'Timor-Leste' , 'Timor-Leste' ] ,
TM : [ 'Turkmenistan' , 'Türkmenistan' ] ,
TN : [ 'Tunisia' , 'تونس, Tunisie' ] ,
TO : [ 'Tonga' , 'Tonga' ] ,
TR : [ 'Turkey' , 'Türkiye' ] ,
TT : [ 'Trinidad and Tobago' , 'Trinidad and Tobago' ] ,
TV : [ 'Tuvalu' , 'Tuvalu' ] ,
TW : [ 'Taiwan' , 'Taiwan' ] ,
TZ : [ 'Tanzania' , 'Tanzania' ] ,
UA : [ 'Ukraine' , 'Україна' ] ,
UG : [ 'Uganda' , 'Uganda' ] ,
UM : [ 'United States Minor Outlying Islands' , 'United States Minor Outlying Islands' ] ,
US : [ 'United States of America' , 'United States of America' ] ,
UY : [ 'Uruguay' , 'Uruguay' ] ,
UZ : [ 'Uzbekistan' , '' ] ,
VA : [ 'City of the Vatican' , 'Città del Vaticano' ] ,
VC : [ 'Saint Vincent and the Grenadines' , 'Saint Vincent and the Grenadines' ] ,
VE : [ 'Venezuela' , 'Venezuela' ] ,
VG : [ 'British Virgin Islands' , 'British Virgin Islands' ] ,
VI : [ 'United States Virgin Islands' , 'United States Virgin Islands' ] ,
VN : [ 'Vietnam' , 'Việt Nam' ] ,
VU : [ 'Vanuatu' , 'Vanuatu' ] ,
WF : [ 'Wallis and Futuna' , 'Wallis-et-Futuna' ] ,
WS : [ 'Samoa' , 'Samoa' ] ,
YE : [ 'Yemen' , 'اليَمَن' ] ,
YT : [ 'Mayotte' , 'Mayotte' ] ,
ZA : [ 'South Africa' , 'South Africa' ] ,
ZM : [ 'Zambia' , 'Zambia' ] ,
ZW : [ 'Zimbabwe' , 'Zimbabwe' ] ,
} ;
2024-04-05 13:16:49 +02:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
2020-11-12 21:13:28 +02:00
let supportedLocales_ : any = null ;
2024-04-05 13:16:49 +02:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
2020-11-12 21:13:28 +02:00
let localeStats_ : any = null ;
2020-11-05 18:58:23 +02:00
2023-10-11 11:17:46 +02:00
const loadedLocales_ : Record < string , Record < string , string [ ] > > = { } ;
const pluralFunctions_ : Record < string , ParsePluralFormFunction > = { } ;
2020-11-05 18:58:23 +02:00
const defaultLocale_ = 'en_GB' ;
let currentLocale_ = defaultLocale_ ;
2023-10-11 11:17:46 +02:00
// Copied from https://github.com/eugeny-dementev/parse-gettext-plural-form
// along with the tests
export const parsePluralForm = ( form : string ) : ParsePluralFormFunction = > {
const pluralFormRegex = /^(\s*nplurals\s*=\s*[0-9]+\s*;\s*plural\s*=\s*(?:\s|[-?|&=!<>+*/%:;a-zA-Z0-9_()])+)$/m ;
if ( ! pluralFormRegex . test ( form ) ) throw new Error ( ` Plural-Forms is invalid: ${ form } ` ) ;
if ( ! /;\s*$/ . test ( form ) ) {
form += ';' ;
}
const code = [
'var plural;' ,
'var nplurals;' ,
form ,
'return (plural === true ? 1 : plural ? plural : 0);' ,
] . join ( '\n' ) ;
2024-02-26 12:16:23 +02:00
// eslint-disable-next-line no-new-func -- There's a regex to check the form but it's still slightly unsafe, eventually we should automatically generate all the functions in advance in build-translations.ts
2023-10-11 11:17:46 +02:00
return ( new Function ( 'n' , code ) ) as ParsePluralFormFunction ;
} ;
2024-03-18 14:16:17 +02:00
const iso639LineToObject = ( line : Iso639Line ) = > {
// TODO: filter name in English (remove brackets, commas,)
const output : Iso639Item = {
alpha3 : line [ 0 ] ,
alpha2 : line [ 1 ] ,
nameEnglish : line [ 2 ] ,
nameNative : line [ 3 ] ? line [ 3 ] : '' ,
} ;
return output ;
} ;
const iso639InfoFromAlpha2 = ( alpha2 : string ) = > {
alpha2 = alpha2 . toLowerCase ( ) ;
const line = iso639_ . find ( e = > e [ 1 ] === alpha2 ) ;
if ( ! line ) return null ;
return iso639LineToObject ( line ) ;
} ;
2023-10-11 11:17:46 +02:00
const getPluralFunction = ( lang : string ) = > {
if ( ! ( lang in pluralFunctions_ ) ) {
const locale = closestSupportedLocale ( lang ) ;
const stats = localeStats ( ) [ locale ] ;
if ( ! stats . pluralForms ) {
pluralFunctions_ [ lang ] = null ;
} else {
pluralFunctions_ [ lang ] = parsePluralForm ( stats . pluralForms ) ;
}
}
return pluralFunctions_ [ lang ] ;
} ;
2020-11-05 18:58:23 +02:00
function defaultLocale() {
return defaultLocale_ ;
}
function localeStats() {
if ( ! localeStats_ ) localeStats_ = require ( './locales/index.js' ) . stats ;
return localeStats_ ;
}
2020-11-12 21:13:28 +02:00
function supportedLocales ( ) : string [ ] {
2020-11-05 18:58:23 +02:00
if ( ! supportedLocales_ ) supportedLocales_ = require ( './locales/index.js' ) . locales ;
const output = [ ] ;
for ( const n in supportedLocales_ ) {
if ( ! supportedLocales_ . hasOwnProperty ( n ) ) continue ;
output . push ( n ) ;
}
return output ;
}
interface SupportedLocalesToLanguagesOptions {
2020-11-12 21:29:22 +02:00
includeStats? : boolean ;
2020-11-05 18:58:23 +02:00
}
2020-11-12 21:13:28 +02:00
function supportedLocalesToLanguages ( options : SupportedLocalesToLanguagesOptions = null ) {
2020-11-05 18:58:23 +02:00
if ( ! options ) options = { } ;
const stats = localeStats ( ) ;
const locales = supportedLocales ( ) ;
2020-11-12 21:13:28 +02:00
const output : StringToStringMap = { } ;
2020-11-05 18:58:23 +02:00
for ( let i = 0 ; i < locales . length ; i ++ ) {
const locale = locales [ i ] ;
output [ locale ] = countryDisplayName ( locale ) ;
const stat = stats [ locale ] ;
if ( options . includeStats && stat ) {
output [ locale ] += ` ( ${ stat . percentDone } %) ` ;
}
}
return output ;
}
2023-06-30 10:11:26 +02:00
function closestSupportedLocale ( canonicalName : string , defaultToEnglish = true , locales : string [ ] = null ) {
2020-11-05 18:58:23 +02:00
locales = locales === null ? supportedLocales ( ) : locales ;
if ( locales . indexOf ( canonicalName ) >= 0 ) return canonicalName ;
const requiredLanguage = languageCodeOnly ( canonicalName ) . toLowerCase ( ) ;
for ( let i = 0 ; i < locales . length ; i ++ ) {
const locale = locales [ i ] ;
const language = locale . split ( '_' ) [ 0 ] ;
2022-07-23 09:31:32 +02:00
if ( requiredLanguage === language ) return locale ;
2020-11-05 18:58:23 +02:00
}
return defaultToEnglish ? 'en_GB' : null ;
}
2020-11-12 21:13:28 +02:00
function countryName ( countryCode : string ) {
2020-11-05 18:58:23 +02:00
const r = codeToCountry_ [ countryCode ] ? codeToCountry_ [ countryCode ] : null ;
if ( ! r ) return '' ;
return r . length > 1 && ! ! r [ 1 ] ? r [ 1 ] : r [ 0 ] ;
}
2023-06-30 10:11:26 +02:00
function languageName ( canonicalName : string , defaultToEnglish = true ) {
2023-06-13 19:06:54 +02:00
const languageCode = languageCodeOnly ( canonicalName ) ;
2024-03-18 14:16:17 +02:00
const info = iso639InfoFromAlpha2 ( languageCode ) ;
if ( ! info ) return '' ;
if ( info . nameNative ) return info . nameNative ;
if ( defaultToEnglish ) return info . nameEnglish ;
2020-11-05 18:58:23 +02:00
return '' ;
}
2020-11-12 21:13:28 +02:00
function languageCodeOnly ( canonicalName : string ) {
2020-11-05 18:58:23 +02:00
if ( canonicalName . length < 2 ) return canonicalName ;
return canonicalName . substr ( 0 , 2 ) ;
}
2020-11-12 21:13:28 +02:00
function countryCodeOnly ( canonicalName : string ) {
2020-11-05 18:58:23 +02:00
if ( canonicalName . length <= 2 ) return '' ;
return canonicalName . substr ( 3 ) ;
}
2020-11-12 21:13:28 +02:00
function countryDisplayName ( canonicalName : string ) {
2020-11-05 18:58:23 +02:00
const languageCode = languageCodeOnly ( canonicalName ) ;
const countryCode = countryCodeOnly ( canonicalName ) ;
let output = languageName ( languageCode ) ;
let extraString ;
if ( countryCode ) {
2022-07-23 09:31:32 +02:00
if ( languageCode === 'zh' && countryCode === 'CN' ) {
2020-11-05 18:58:23 +02:00
extraString = '简体' ; // "Simplified" in "Simplified Chinese"
} else {
extraString = countryName ( countryCode ) ;
}
}
2022-07-23 09:31:32 +02:00
if ( languageCode === 'zh' && ( countryCode === '' || countryCode === 'TW' ) ) extraString = '繁體' ; // "Traditional" in "Traditional Chinese"
2020-11-05 18:58:23 +02:00
if ( extraString ) {
output += ` ( ${ extraString } ) ` ;
} else if ( countryCode ) {
// If we have a country code but couldn't match it to a country name,
// just display the full canonical name (applies for example to es-419
// for Latin American Spanish).
output += ` ( ${ canonicalName } ) ` ;
}
return output ;
}
2020-11-12 21:13:28 +02:00
function localeStrings ( canonicalName : string ) {
2020-11-05 18:58:23 +02:00
const locale = closestSupportedLocale ( canonicalName ) ;
if ( loadedLocales_ [ locale ] ) return loadedLocales_ [ locale ] ;
2023-06-01 13:02:36 +02:00
loadedLocales_ [ locale ] = { . . . supportedLocales_ [ locale ] } ;
2020-11-05 18:58:23 +02:00
return loadedLocales_ [ locale ] ;
}
2022-11-28 18:16:32 +02:00
const currentLocale = ( ) = > {
return currentLocale_ ;
} ;
2020-11-12 21:13:28 +02:00
function setLocale ( canonicalName : string ) {
2022-07-23 09:31:32 +02:00
if ( currentLocale_ === canonicalName ) return ;
2020-11-05 18:58:23 +02:00
currentLocale_ = closestSupportedLocale ( canonicalName ) ;
}
function languageCode() {
return languageCodeOnly ( currentLocale_ ) ;
}
2020-11-27 13:12:28 +02:00
function localesFromLanguageCode ( languageCode : string , locales : string [ ] ) : string [ ] {
return locales . filter ( ( l : string ) = > {
return languageCodeOnly ( l ) === languageCode ;
} ) ;
}
2024-03-18 14:16:17 +02:00
export const toIso639Alpha3 = ( code : string ) = > {
2023-12-13 21:24:58 +02:00
if ( code . includes ( '_' ) ) {
const s = code . split ( '_' ) ;
code = s [ 0 ] ;
}
2024-03-18 14:16:17 +02:00
const info = iso639InfoFromAlpha2 ( code ) ;
if ( ! info ) throw new Error ( ` Cannot convert to ISO-639 code: ${ code } ` ) ;
return info . alpha3 ;
2023-12-13 21:24:58 +02:00
} ;
2024-04-05 13:16:49 +02:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
2021-05-15 20:56:49 +02:00
function _ ( s : string , . . . args : any [ ] ) : string {
2023-05-10 13:18:59 +02:00
return stringByLocale ( currentLocale_ , s , . . . args ) ;
}
2024-04-05 13:16:49 +02:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
2023-05-10 13:18:59 +02:00
function _n ( singular : string , plural : string , n : number , . . . args : any [ ] ) {
2023-10-11 11:17:46 +02:00
if ( [ 'en_GB' , 'en_US' ] . includes ( currentLocale_ ) ) {
if ( n > 1 ) return _ ( plural , . . . args ) ;
return _ ( singular , . . . args ) ;
} else {
const pluralFn = getPluralFunction ( currentLocale_ ) ;
const stringIndex = pluralFn ? pluralFn ( n ) : 0 ;
const strings = localeStrings ( currentLocale_ ) ;
const result = strings [ singular ] ;
let translatedString = '' ;
if ( result === undefined || ! result . join ( '' ) ) {
translatedString = singular ;
} else {
translatedString = stringIndex < result . length ? result [ stringIndex ] : result [ 0 ] ;
}
try {
return sprintf ( translatedString , . . . args ) ;
} catch ( error ) {
return ` ${ translatedString } ${ args . join ( ', ' ) } (Translation error: ${ error . message } ) ` ;
}
}
2023-05-10 13:18:59 +02:00
}
2024-04-05 13:16:49 +02:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
2023-05-10 13:18:59 +02:00
const stringByLocale = ( locale : string , s : string , . . . args : any [ ] ) : string = > {
const strings = localeStrings ( locale ) ;
2023-10-11 11:17:46 +02:00
const result = strings [ s ] ;
let translatedString = '' ;
if ( result === undefined || ! result . join ( '' ) ) {
translatedString = s ;
} else {
translatedString = result [ 0 ] ;
}
2020-11-05 18:58:23 +02:00
try {
2023-10-11 11:17:46 +02:00
return sprintf ( translatedString , . . . args ) ;
2020-11-05 18:58:23 +02:00
} catch ( error ) {
2023-10-11 11:17:46 +02:00
return ` ${ translatedString } ${ args . join ( ', ' ) } (Translation error: ${ error . message } ) ` ;
2020-11-05 18:58:23 +02:00
}
2023-05-10 13:18:59 +02:00
} ;
2020-11-05 18:58:23 +02:00
2023-06-13 19:06:54 +02:00
export { _ , _n , supportedLocales , languageName , currentLocale , localesFromLanguageCode , languageCodeOnly , countryDisplayName , localeStrings , setLocale , supportedLocalesToLanguages , defaultLocale , closestSupportedLocale , languageCode , countryCodeOnly } ;