Extension to return old Twitter layout from 2015.
at master 17 kB view raw
1// Tests locale files 2 3const languageCodes = [ 4 {"code":"ab","name":"Abkhaz","nativeName":"аҧсуа"}, 5 {"code":"aa","name":"Afar","nativeName":"Afaraf"}, 6 {"code":"af","name":"Afrikaans","nativeName":"Afrikaans"}, 7 {"code":"ak","name":"Akan","nativeName":"Akan"}, 8 {"code":"sq","name":"Albanian","nativeName":"Shqip"}, 9 {"code":"am","name":"Amharic","nativeName":"አማርኛ"}, 10 {"code":"ar","name":"Arabic","nativeName":"العربية"}, 11 {"code":"an","name":"Aragonese","nativeName":"Aragonés"}, 12 {"code":"hy","name":"Armenian","nativeName":"Հայերեն"}, 13 {"code":"as","name":"Assamese","nativeName":"অসমীয়া"}, 14 {"code":"av","name":"Avaric","nativeName":"авар мацӀ, магӀарул мацӀ"}, 15 {"code":"ae","name":"Avestan","nativeName":"avesta"}, 16 {"code":"ay","name":"Aymara","nativeName":"aymar aru"}, 17 {"code":"az","name":"Azerbaijani","nativeName":"azərbaycan dili"}, 18 {"code":"bm","name":"Bambara","nativeName":"bamanankan"}, 19 {"code":"ba","name":"Bashkir","nativeName":"башҡорт теле"}, 20 {"code":"eu","name":"Basque","nativeName":"euskara, euskera"}, 21 {"code":"be","name":"Belarusian","nativeName":"Беларуская"}, 22 {"code":"bn","name":"Bengali","nativeName":"বাংলা"}, 23 {"code":"bh","name":"Bihari","nativeName":"भोजपुरी"}, 24 {"code":"bi","name":"Bislama","nativeName":"Bislama"}, 25 {"code":"bs","name":"Bosnian","nativeName":"bosanski jezik"}, 26 {"code":"br","name":"Breton","nativeName":"brezhoneg"}, 27 {"code":"bg","name":"Bulgarian","nativeName":"български език"}, 28 {"code":"my","name":"Burmese","nativeName":"ဗမာစာ"}, 29 {"code":"ca","name":"Catalan; Valencian","nativeName":"Català"}, 30 {"code":"ch","name":"Chamorro","nativeName":"Chamoru"}, 31 {"code":"ce","name":"Chechen","nativeName":"нохчийн мотт"}, 32 {"code":"ny","name":"Chichewa; Chewa; Nyanja","nativeName":"chiCheŵa, chinyanja"}, 33 {"code":"zh","name":"Chinese","nativeName":"中文 (Zhōngwén), 汉语, 漢語"}, 34 {"code":"zh_CN","name":"Chinese","nativeName":"中文 (Zhōngwén), 汉语, 漢語"}, 35 {"code":"cv","name":"Chuvash","nativeName":"чӑваш чӗлхи"}, 36 {"code":"kw","name":"Cornish","nativeName":"Kernewek"}, 37 {"code":"co","name":"Corsican","nativeName":"corsu, lingua corsa"}, 38 {"code":"cr","name":"Cree","nativeName":"ᓀᐦᐃᔭᐍᐏᐣ"}, 39 {"code":"hr","name":"Croatian","nativeName":"hrvatski"}, 40 {"code":"cs","name":"Czech","nativeName":"česky, čeština"}, 41 {"code":"da","name":"Danish","nativeName":"dansk"}, 42 {"code":"dv","name":"Divehi; Dhivehi; Maldivian;","nativeName":"ދިވެހި"}, 43 {"code":"nl","name":"Dutch","nativeName":"Nederlands, Vlaams"}, 44 {"code":"en","name":"English","nativeName":"English"}, 45 {"code":"eo","name":"Esperanto","nativeName":"Esperanto"}, 46 {"code":"et","name":"Estonian","nativeName":"eesti, eesti keel"}, 47 {"code":"ee","name":"Ewe","nativeName":"Eʋegbe"}, 48 {"code":"fo","name":"Faroese","nativeName":"føroyskt"}, 49 {"code":"fj","name":"Fijian","nativeName":"vosa Vakaviti"}, 50 {"code":"fi","name":"Finnish","nativeName":"suomi, suomen kieli"}, 51 {"code":"fr","name":"French","nativeName":"français, langue française"}, 52 {"code":"ff","name":"Fula; Fulah; Pulaar; Pular","nativeName":"Fulfulde, Pulaar, Pular"}, 53 {"code":"gl","name":"Galician","nativeName":"Galego"}, 54 {"code":"ka","name":"Georgian","nativeName":"ქართული"}, 55 {"code":"de","name":"German","nativeName":"Deutsch"}, 56 {"code":"el","name":"Greek, Modern","nativeName":"Ελληνικά"}, 57 {"code":"gn","name":"Guaraní","nativeName":"Avañeẽ"}, 58 {"code":"gu","name":"Gujarati","nativeName":"ગુજરાતી"}, 59 {"code":"ht","name":"Haitian; Haitian Creole","nativeName":"Kreyòl ayisyen"}, 60 {"code":"ha","name":"Hausa","nativeName":"Hausa, هَوُسَ"}, 61 {"code":"he","name":"Hebrew (modern)","nativeName":"עברית"}, 62 {"code":"hz","name":"Herero","nativeName":"Otjiherero"}, 63 {"code":"hi","name":"Hindi","nativeName":"हिन्दी, हिंदी"}, 64 {"code":"ho","name":"Hiri Motu","nativeName":"Hiri Motu"}, 65 {"code":"hu","name":"Hungarian","nativeName":"Magyar"}, 66 {"code":"ia","name":"Interlingua","nativeName":"Interlingua"}, 67 {"code":"id","name":"Indonesian","nativeName":"Bahasa Indonesia"}, 68 {"code":"ie","name":"Interlingue","nativeName":"Originally called Occidental; then Interlingue after WWII"}, 69 {"code":"ga","name":"Irish","nativeName":"Gaeilge"}, 70 {"code":"ig","name":"Igbo","nativeName":"Asụsụ Igbo"}, 71 {"code":"ik","name":"Inupiaq","nativeName":"Iñupiaq, Iñupiatun"}, 72 {"code":"io","name":"Ido","nativeName":"Ido"}, 73 {"code":"is","name":"Icelandic","nativeName":"Íslenska"}, 74 {"code":"it","name":"Italian","nativeName":"Italiano"}, 75 {"code":"iu","name":"Inuktitut","nativeName":"ᐃᓄᒃᑎᑐᑦ"}, 76 {"code":"ja","name":"Japanese","nativeName":"日本語 (にほんご/にっぽんご)"}, 77 {"code":"jv","name":"Javanese","nativeName":"basa Jawa"}, 78 {"code":"kl","name":"Kalaallisut, Greenlandic","nativeName":"kalaallisut, kalaallit oqaasii"}, 79 {"code":"kn","name":"Kannada","nativeName":"ಕನ್ನಡ"}, 80 {"code":"kr","name":"Kanuri","nativeName":"Kanuri"}, 81 {"code":"ks","name":"Kashmiri","nativeName":"कश्मीरी, كشميري‎"}, 82 {"code":"kk","name":"Kazakh","nativeName":"Қазақ тілі"}, 83 {"code":"km","name":"Khmer","nativeName":"ភាសាខ្មែរ"}, 84 {"code":"ki","name":"Kikuyu, Gikuyu","nativeName":"Gĩkũyũ"}, 85 {"code":"rw","name":"Kinyarwanda","nativeName":"Ikinyarwanda"}, 86 {"code":"ky","name":"Kirghiz, Kyrgyz","nativeName":"кыргыз тили"}, 87 {"code":"kv","name":"Komi","nativeName":"коми кыв"}, 88 {"code":"kg","name":"Kongo","nativeName":"KiKongo"}, 89 {"code":"ko","name":"Korean","nativeName":"한국어 (韓國語), 조선말 (朝鮮語)"}, 90 {"code":"ku","name":"Kurdish","nativeName":"Kurdî, كوردی‎"}, 91 {"code":"kj","name":"Kwanyama, Kuanyama","nativeName":"Kuanyama"}, 92 {"code":"la","name":"Latin","nativeName":"latine, lingua latina"}, 93 {"code":"lb","name":"Luxembourgish, Letzeburgesch","nativeName":"Lëtzebuergesch"}, 94 {"code":"lg","name":"Luganda","nativeName":"Luganda"}, 95 {"code":"li","name":"Limburgish, Limburgan, Limburger","nativeName":"Limburgs"}, 96 {"code":"ln","name":"Lingala","nativeName":"Lingála"}, 97 {"code":"lo","name":"Lao","nativeName":"ພາສາລາວ"}, 98 {"code":"lt","name":"Lithuanian","nativeName":"lietuvių kalba"}, 99 {"code":"lu","name":"Luba-Katanga","nativeName":""}, 100 {"code":"lv","name":"Latvian","nativeName":"latviešu valoda"}, 101 {"code":"gv","name":"Manx","nativeName":"Gaelg, Gailck"}, 102 {"code":"mk","name":"Macedonian","nativeName":"македонски јазик"}, 103 {"code":"mg","name":"Malagasy","nativeName":"Malagasy fiteny"}, 104 {"code":"ms","name":"Malay","nativeName":"bahasa Melayu, بهاس ملايو‎"}, 105 {"code":"ml","name":"Malayalam","nativeName":"മലയാളം"}, 106 {"code":"mt","name":"Maltese","nativeName":"Malti"}, 107 {"code":"mi","name":"Māori","nativeName":"te reo Māori"}, 108 {"code":"mr","name":"Marathi (Marāṭhī)","nativeName":"मराठी"}, 109 {"code":"mh","name":"Marshallese","nativeName":"Kajin M̧ajeļ"}, 110 {"code":"mn","name":"Mongolian","nativeName":"монгол"}, 111 {"code":"na","name":"Nauru","nativeName":"Ekakairũ Naoero"}, 112 {"code":"nv","name":"Navajo, Navaho","nativeName":"Diné bizaad, Dinékʼehǰí"}, 113 {"code":"nb","name":"Norwegian Bokmål","nativeName":"Norsk bokmål"}, 114 {"code":"nd","name":"North Ndebele","nativeName":"isiNdebele"}, 115 {"code":"ne","name":"Nepali","nativeName":"नेपाली"}, 116 {"code":"ng","name":"Ndonga","nativeName":"Owambo"}, 117 {"code":"nn","name":"Norwegian Nynorsk","nativeName":"Norsk nynorsk"}, 118 {"code":"no","name":"Norwegian","nativeName":"Norsk"}, 119 {"code":"ii","name":"Nuosu","nativeName":"ꆈꌠ꒿ Nuosuhxop"}, 120 {"code":"nr","name":"South Ndebele","nativeName":"isiNdebele"}, 121 {"code":"oc","name":"Occitan","nativeName":"Occitan"}, 122 {"code":"oj","name":"Ojibwe, Ojibwa","nativeName":"ᐊᓂᔑᓈᐯᒧᐎᓐ"}, 123 {"code":"cu","name":"Old Church Slavonic, Church Slavic, Church Slavonic, Old Bulgarian, Old Slavonic","nativeName":"ѩзыкъ словѣньскъ"}, 124 {"code":"om","name":"Oromo","nativeName":"Afaan Oromoo"}, 125 {"code":"or","name":"Oriya","nativeName":"ଓଡ଼ିଆ"}, 126 {"code":"os","name":"Ossetian, Ossetic","nativeName":"ирон æвзаг"}, 127 {"code":"pa","name":"Panjabi, Punjabi","nativeName":"ਪੰਜਾਬੀ, پنجابی‎"}, 128 {"code":"pi","name":"Pāli","nativeName":"पाऴि"}, 129 {"code":"fa","name":"Persian","nativeName":"فارسی"}, 130 {"code":"pl","name":"Polish","nativeName":"polski"}, 131 {"code":"ps","name":"Pashto, Pushto","nativeName":"پښتو"}, 132 {"code":"pt","name":"Portuguese","nativeName":"Português"}, 133 {"code":"pt_BR","name":"Portuguese (Brazil)","nativeName":"Português do Brasil"}, 134 {"code":"qu","name":"Quechua","nativeName":"Runa Simi, Kichwa"}, 135 {"code":"rm","name":"Romansh","nativeName":"rumantsch grischun"}, 136 {"code":"rn","name":"Kirundi","nativeName":"kiRundi"}, 137 {"code":"ro","name":"Romanian, Moldavian, Moldovan","nativeName":"română"}, 138 {"code":"ru","name":"Russian","nativeName":"русский язык"}, 139 {"code":"sa","name":"Sanskrit (Saṁskṛta)","nativeName":"संस्कृतम्"}, 140 {"code":"sc","name":"Sardinian","nativeName":"sardu"}, 141 {"code":"sd","name":"Sindhi","nativeName":"सिन्धी, سنڌي، سندھی‎"}, 142 {"code":"se","name":"Northern Sami","nativeName":"Davvisámegiella"}, 143 {"code":"sm","name":"Samoan","nativeName":"gagana faa Samoa"}, 144 {"code":"sg","name":"Sango","nativeName":"yângâ tî sängö"}, 145 {"code":"sr","name":"Serbian","nativeName":"српски језик"}, 146 {"code":"gd","name":"Scottish Gaelic; Gaelic","nativeName":"Gàidhlig"}, 147 {"code":"sn","name":"Shona","nativeName":"chiShona"}, 148 {"code":"si","name":"Sinhala, Sinhalese","nativeName":"සිංහල"}, 149 {"code":"sk","name":"Slovak","nativeName":"slovenčina"}, 150 {"code":"sl","name":"Slovene","nativeName":"slovenščina"}, 151 {"code":"so","name":"Somali","nativeName":"Soomaaliga, af Soomaali"}, 152 {"code":"st","name":"Southern Sotho","nativeName":"Sesotho"}, 153 {"code":"es","name":"Spanish; Castilian","nativeName":"español, castellano"}, 154 {"code":"su","name":"Sundanese","nativeName":"Basa Sunda"}, 155 {"code":"sw","name":"Swahili","nativeName":"Kiswahili"}, 156 {"code":"ss","name":"Swati","nativeName":"SiSwati"}, 157 {"code":"sv","name":"Swedish","nativeName":"svenska"}, 158 {"code":"ta","name":"Tamil","nativeName":"தமிழ்"}, 159 {"code":"te","name":"Telugu","nativeName":"తెలుగు"}, 160 {"code":"tg","name":"Tajik","nativeName":"тоҷикӣ, toğikī, تاجیکی‎"}, 161 {"code":"th","name":"Thai","nativeName":"ไทย"}, 162 {"code":"ti","name":"Tigrinya","nativeName":"ትግርኛ"}, 163 {"code":"bo","name":"Tibetan Standard, Tibetan, Central","nativeName":"བོད་ཡིག"}, 164 {"code":"tk","name":"Turkmen","nativeName":"Türkmen, Түркмен"}, 165 {"code":"tl","name":"Tagalog","nativeName":"Wikang Tagalog, ᜏᜒᜃᜅ᜔ ᜆᜄᜎᜓᜄ᜔"}, 166 {"code":"tn","name":"Tswana","nativeName":"Setswana"}, 167 {"code":"to","name":"Tonga (Tonga Islands)","nativeName":"faka Tonga"}, 168 {"code":"tr","name":"Turkish","nativeName":"Türkçe"}, 169 {"code":"ts","name":"Tsonga","nativeName":"Xitsonga"}, 170 {"code":"tt","name":"Tatar","nativeName":"татарча, tatarça, تاتارچا‎"}, 171 {"code":"tw","name":"Twi","nativeName":"Twi"}, 172 {"code":"ty","name":"Tahitian","nativeName":"Reo Tahiti"}, 173 {"code":"ug","name":"Uighur, Uyghur","nativeName":"Uyƣurqə, ئۇيغۇرچە‎"}, 174 {"code":"uk","name":"Ukrainian","nativeName":"українська"}, 175 {"code":"ur","name":"Urdu","nativeName":"اردو"}, 176 {"code":"uz","name":"Uzbek","nativeName":"zbek, Ўзбек, أۇزبېك‎"}, 177 {"code":"ve","name":"Venda","nativeName":"Tshivenḓa"}, 178 {"code":"vi","name":"Vietnamese","nativeName":"Tiếng Việt"}, 179 {"code":"vo","name":"Volapük","nativeName":"Volapük"}, 180 {"code":"wa","name":"Walloon","nativeName":"Walon"}, 181 {"code":"cy","name":"Welsh","nativeName":"Cymraeg"}, 182 {"code":"wo","name":"Wolof","nativeName":"Wollof"}, 183 {"code":"fy","name":"Western Frisian","nativeName":"Frysk"}, 184 {"code":"xh","name":"Xhosa","nativeName":"isiXhosa"}, 185 {"code":"yi","name":"Yiddish","nativeName":"ייִדיש"}, 186 {"code":"yo","name":"Yoruba","nativeName":"Yorùbá"}, 187 {"code":"za","name":"Zhuang, Chuang","nativeName":"Saɯ cueŋƅ, Saw cuengh"} 188]; 189 190const fs = require('fs'); 191const path = require('path'); 192 193const validKey = /^[a-zA-Z0-9_@]+$/; 194const placeholdersRegex = /\$[a-zA-Z0-9_@]+\$/g; 195const validFieldKeys = ['name', 'message', 'description', 'example', 'note', 'placeholders']; 196 197const locales = 198 fs.readdirSync(path.join(__dirname, '_locales'), { withFileTypes: true }) 199 .filter(dirent => dirent.isDirectory()) 200 .map(dirent => dirent.name); 201 202const englishLocale = JSON.parse(fs.readFileSync(path.join(__dirname, '_locales', 'en', 'messages.json'))); 203const englishLocaleArray = Object.keys(englishLocale); 204 205let errors = false; 206 207for(let localeName of locales) { 208 let locale; 209 210 try { 211 locale = JSON.parse(fs.readFileSync(path.join(__dirname, '_locales', localeName, 'messages.json'))); 212 } catch(e) { 213 console.error(`❌ (Critical) Error parsing _locales/${localeName}/messages.json`, e); 214 errors = true; 215 continue; 216 } 217 218 if(localeName !== 'en') { 219 let array = Object.keys(locale); 220 let diff = englishLocaleArray.length - array.length; 221 if(diff !== 0) { 222 if(diff < 10) { 223 let missing = englishLocaleArray.filter(key => !array.includes(key)); 224 console.log(`❌ Missing ${diff} keys in _locales/${localeName}/messages.json (${languageCodes.find(l => l.code === localeName)?.name}): ${missing.join(', ')}`); 225 } else { 226 console.log(`❌ Missing ${diff} keys in _locales/${localeName}/messages.json (${languageCodes.find(l => l.code === localeName)?.name})`); 227 } 228 } else { 229 console.log(`✅ All keys present in _locales/${localeName}/messages.json (${languageCodes.find(l => l.code === localeName)?.name})`); 230 } 231 } 232 233 let keys = Object.keys(locale); 234 for(let key of keys) { 235 if(!englishLocale[key]) { 236 console.error(`❌ Key "${key}" is not present in English for _locales/${localeName}/messages.json`); 237 errors = true; 238 } 239 if(!validKey.test(key)) { 240 console.error(`❌ Invalid key "${key}" in _locales/${localeName}/messages.json`); 241 errors = true; 242 } 243 if(key.length > 80) { 244 console.error(`❌ Key "${key}" is too long in _locales/${localeName}/messages.json`); 245 errors = true; 246 } 247 } 248 249 if(!locale.ext_description) { 250 console.error(`❌ Missing "ext_description" in _locales/${localeName}/messages.json`); 251 errors = true; 252 } 253 254 if(locale.ext_description.length > 132) { 255 console.error(`❌ "ext_description" is too long in _locales/${localeName}/messages.json`); 256 errors = true; 257 } 258 259 for(let fieldName in locale) { 260 let field = locale[fieldName]; 261 let keys = Object.keys(field); 262 263 for(let key of keys) { 264 if(!validFieldKeys.includes(key)) { 265 console.error(`❌ Invalid key "${key}" on "${fieldName}" in _locales/${localeName}/messages.json`); 266 errors = true; 267 } 268 } 269 270 if(typeof field.message !== 'string') { 271 console.error(`❌ Missing "message" on "${fieldName}" in _locales/${localeName}/messages.json`); 272 errors = true; 273 } 274 275 let placeholders = field.message.match(placeholdersRegex); 276 if(placeholders) { 277 if(!field.placeholders) { 278 console.error(`❌ Missing "placeholders" on "${fieldName}" in _locales/${localeName}/messages.json`); 279 errors = true; 280 } else { 281 placeholders = placeholders.map(placeholder => placeholder.slice(1, -1).toLowerCase()); 282 for(let placeholder of placeholders) { 283 if(!field.placeholders[placeholder]) { 284 console.error(`❌ Missing placeholder "${placeholder}" on "${fieldName}" in _locales/${localeName}/messages.json`); 285 errors = true; 286 } 287 if(!field.placeholders[placeholder].content) { 288 console.error(`❌ Missing placeholder content "${placeholder}" on "${fieldName}" in _locales/${localeName}/messages.json`); 289 errors = true; 290 } 291 } 292 } 293 } 294 } 295} 296 297if(errors) { 298 process.exit(1); 299} else { 300 console.log('\n✅ All locale files are valid.'); 301}