187 lines
11 KiB
JavaScript
187 lines
11 KiB
JavaScript
/*
|
||||
|
|
* languages.js — the language catalog, shared by the NAS server, the listener
|
|||
|
|
* page, and the Mac engine.
|
|||
|
|
*
|
|||
|
|
* `code` is a FLORES-200 code, which is what NLLB-200 expects. `tts` is the
|
|||
|
|
* BCP-47 tag we hand to the phone's speechSynthesis; it is a best effort, and a
|
|||
|
|
* phone that has no matching voice simply shows captions without speaking.
|
|||
|
|
*
|
|||
|
|
* `native` is what the listener actually sees in the picker. Never show someone
|
|||
|
|
* the English name of their own language when you can help it.
|
|||
|
|
*/
|
|||
|
|
(function (root, factory) {
|
|||
|
|
if (typeof module === 'object' && module.exports) module.exports = factory();
|
|||
|
|
else root.Languages = factory();
|
|||
|
|
}(typeof self !== 'undefined' ? self : this, function () {
|
|||
|
|
|
|||
|
|
// [ FLORES code, English name, native name, BCP-47 for TTS, rtl ]
|
|||
|
|
var RAW = [
|
|||
|
|
['eng_Latn', 'English', 'English', 'en-US'],
|
|||
|
|
['spa_Latn', 'Spanish (Latin America)', 'Español (América Latina)', 'es-MX'],
|
|||
|
|
['zho_Hans', 'Chinese (Simplified)', '简体中文', 'zh-CN'],
|
|||
|
|
['zho_Hant', 'Chinese (Traditional)','繁體中文', 'zh-TW'],
|
|||
|
|
['yue_Hant', 'Cantonese', '廣東話', 'zh-HK'],
|
|||
|
|
['fra_Latn', 'French', 'Français', 'fr-FR'],
|
|||
|
|
/* One NLLB Portuguese, two voices: the Brazilian and European variants
|
|||
|
|
share their translation (por_PT is aliased to por_Latn at the MT
|
|||
|
|
boundary in engine.js) and differ in the voice that reads it. */
|
|||
|
|
['por_Latn', 'Portuguese (Brazil)', 'Português (Brasil)', 'pt-BR'],
|
|||
|
|
['por_PT', 'Portuguese (Portugal)', 'Português (Portugal)', 'pt-PT'],
|
|||
|
|
/* Same NLLB Spanish, read in a Castilian voice. There is no grammatical
|
|||
|
|
transform between them: converting ustedes->vosotros needs to know
|
|||
|
|
whether "you" was one person or a room, and neither the English nor
|
|||
|
|
the Spanish carries that — see spa-variants.js for the measurements. */
|
|||
|
|
['spa_ES', 'Spanish (Spain)', 'Español (España)', 'es-ES'],
|
|||
|
|
/* Mexico shares Latin America's grammar exactly (RAE: vosotros "carecen
|
|||
|
|
de uso en América", and Mexico is tuteo-exclusive), so the text is
|
|||
|
|
identical — this exists so a Mexican listener sees their own country
|
|||
|
|
named, and so the operator can give it its own voice. */
|
|||
|
|
['spa_MX', 'Spanish (Mexico)', 'Español (México)', 'es-MX'],
|
|||
|
|
['kor_Hang', 'Korean', '한국어', 'ko-KR'],
|
|||
|
|
['vie_Latn', 'Vietnamese', 'Tiếng Việt', 'vi-VN'],
|
|||
|
|
['hat_Latn', 'Haitian Creole', 'Kreyòl Ayisyen', 'ht-HT'],
|
|||
|
|
['arb_Arab', 'Arabic', 'العربية', 'ar-SA', true],
|
|||
|
|
['rus_Cyrl', 'Russian', 'Русский', 'ru-RU'],
|
|||
|
|
['ukr_Cyrl', 'Ukrainian', 'Українська', 'uk-UA'],
|
|||
|
|
['ron_Latn', 'Romanian', 'Română', 'ro-RO'],
|
|||
|
|
['pol_Latn', 'Polish', 'Polski', 'pl-PL'],
|
|||
|
|
['deu_Latn', 'German', 'Deutsch', 'de-DE'],
|
|||
|
|
['ita_Latn', 'Italian', 'Italiano', 'it-IT'],
|
|||
|
|
['nld_Latn', 'Dutch', 'Nederlands', 'nl-NL'],
|
|||
|
|
['tgl_Latn', 'Tagalog', 'Tagalog', 'fil-PH'],
|
|||
|
|
['ceb_Latn', 'Cebuano', 'Cebuano', 'fil-PH'],
|
|||
|
|
['ind_Latn', 'Indonesian', 'Bahasa Indonesia', 'id-ID'],
|
|||
|
|
['zsm_Latn', 'Malay', 'Bahasa Melayu', 'ms-MY'],
|
|||
|
|
['tha_Thai', 'Thai', 'ไทย', 'th-TH'],
|
|||
|
|
['khm_Khmr', 'Khmer', 'ភាសាខ្មែរ', 'km-KH'],
|
|||
|
|
['lao_Laoo', 'Lao', 'ລາວ', 'lo-LA'],
|
|||
|
|
['mya_Mymr', 'Burmese', 'မြန်မာ', 'my-MM'],
|
|||
|
|
['shn_Mymr', 'Shan', ' လိၵ်ႈတႆး', 'shn'],
|
|||
|
|
['kac_Latn', 'Kachin (Jingpho)', 'Jinghpaw', 'kac'],
|
|||
|
|
['npi_Deva', 'Nepali', 'नेपाली', 'ne-NP'],
|
|||
|
|
['hin_Deva', 'Hindi', 'हिन्दी', 'hi-IN'],
|
|||
|
|
['urd_Arab', 'Urdu', 'اردو', 'ur-PK', true],
|
|||
|
|
['ben_Beng', 'Bengali', 'বাংলা', 'bn-BD'],
|
|||
|
|
['pan_Guru', 'Punjabi', 'ਪੰਜਾਬੀ', 'pa-IN'],
|
|||
|
|
['guj_Gujr', 'Gujarati', 'ગુજરાતી', 'gu-IN'],
|
|||
|
|
['tam_Taml', 'Tamil', 'தமிழ்', 'ta-IN'],
|
|||
|
|
['tel_Telu', 'Telugu', 'తెలుగు', 'te-IN'],
|
|||
|
|
['mal_Mlym', 'Malayalam', 'മലയാളം', 'ml-IN'],
|
|||
|
|
['kan_Knda', 'Kannada', 'ಕನ್ನಡ', 'kn-IN'],
|
|||
|
|
['mar_Deva', 'Marathi', 'मराठी', 'mr-IN'],
|
|||
|
|
['sin_Sinh', 'Sinhala', 'සිංහල', 'si-LK'],
|
|||
|
|
['pes_Arab', 'Persian (Farsi)', 'فارسی', 'fa-IR', true],
|
|||
|
|
['prs_Arab', 'Dari', 'دری', 'fa-AF', true],
|
|||
|
|
['pbt_Arab', 'Pashto', 'پښتو', 'ps-AF', true],
|
|||
|
|
['ckb_Arab', 'Kurdish (Sorani)', 'کوردی', 'ckb', true],
|
|||
|
|
['kmr_Latn', 'Kurdish (Kurmanji)', 'Kurmancî', 'ku'],
|
|||
|
|
['heb_Hebr', 'Hebrew', 'עברית', 'he-IL', true],
|
|||
|
|
['tur_Latn', 'Turkish', 'Türkçe', 'tr-TR'],
|
|||
|
|
['amh_Ethi', 'Amharic', 'አማርኛ', 'am-ET'],
|
|||
|
|
['tir_Ethi', 'Tigrinya', 'ትግርኛ', 'ti-ET'],
|
|||
|
|
['som_Latn', 'Somali', 'Soomaali', 'so-SO'],
|
|||
|
|
['swh_Latn', 'Swahili', 'Kiswahili', 'sw-KE'],
|
|||
|
|
['yor_Latn', 'Yoruba', 'Yorùbá', 'yo-NG'],
|
|||
|
|
['ibo_Latn', 'Igbo', 'Igbo', 'ig-NG'],
|
|||
|
|
['hau_Latn', 'Hausa', 'Hausa', 'ha-NG'],
|
|||
|
|
['lin_Latn', 'Lingala', 'Lingála', 'ln'],
|
|||
|
|
['kin_Latn', 'Kinyarwanda', 'Ikinyarwanda', 'rw-RW'],
|
|||
|
|
['run_Latn', 'Kirundi', 'Ikirundi', 'rn'],
|
|||
|
|
['lug_Latn', 'Luganda', 'Luganda', 'lg'],
|
|||
|
|
['nya_Latn', 'Chichewa', 'Chichewa', 'ny'],
|
|||
|
|
['sna_Latn', 'Shona', 'chiShona', 'sn'],
|
|||
|
|
['zul_Latn', 'Zulu', 'isiZulu', 'zu-ZA'],
|
|||
|
|
['xho_Latn', 'Xhosa', 'isiXhosa', 'xh-ZA'],
|
|||
|
|
['afr_Latn', 'Afrikaans', 'Afrikaans', 'af-ZA'],
|
|||
|
|
['jpn_Jpan', 'Japanese', '日本語', 'ja-JP'],
|
|||
|
|
['ell_Grek', 'Greek', 'Ελληνικά', 'el-GR'],
|
|||
|
|
['hun_Latn', 'Hungarian', 'Magyar', 'hu-HU'],
|
|||
|
|
['ces_Latn', 'Czech', 'Čeština', 'cs-CZ'],
|
|||
|
|
['slk_Latn', 'Slovak', 'Slovenčina', 'sk-SK'],
|
|||
|
|
['bul_Cyrl', 'Bulgarian', 'Български', 'bg-BG'],
|
|||
|
|
['srp_Cyrl', 'Serbian', 'Српски', 'sr-RS'],
|
|||
|
|
['hrv_Latn', 'Croatian', 'Hrvatski', 'hr-HR'],
|
|||
|
|
['bos_Latn', 'Bosnian', 'Bosanski', 'bs-BA'],
|
|||
|
|
['slv_Latn', 'Slovenian', 'Slovenščina', 'sl-SI'],
|
|||
|
|
['als_Latn', 'Albanian', 'Shqip', 'sq-AL'],
|
|||
|
|
['lit_Latn', 'Lithuanian', 'Lietuvių', 'lt-LT'],
|
|||
|
|
['lvs_Latn', 'Latvian', 'Latviešu', 'lv-LV'],
|
|||
|
|
['est_Latn', 'Estonian', 'Eesti', 'et-EE'],
|
|||
|
|
['fin_Latn', 'Finnish', 'Suomi', 'fi-FI'],
|
|||
|
|
['swe_Latn', 'Swedish', 'Svenska', 'sv-SE'],
|
|||
|
|
['nob_Latn', 'Norwegian', 'Norsk', 'nb-NO'],
|
|||
|
|
['dan_Latn', 'Danish', 'Dansk', 'da-DK'],
|
|||
|
|
['isl_Latn', 'Icelandic', 'Íslenska', 'is-IS'],
|
|||
|
|
['kat_Geor', 'Georgian', 'ქართული', 'ka-GE'],
|
|||
|
|
['hye_Armn', 'Armenian', 'Հայերեն', 'hy-AM'],
|
|||
|
|
['azj_Latn', 'Azerbaijani', 'Azərbaycan', 'az-AZ'],
|
|||
|
|
['uzn_Latn', 'Uzbek', 'Oʻzbek', 'uz-UZ'],
|
|||
|
|
['kaz_Cyrl', 'Kazakh', 'Қазақша', 'kk-KZ'],
|
|||
|
|
['kir_Cyrl', 'Kyrgyz', 'Кыргызча', 'ky-KG'],
|
|||
|
|
['tgk_Cyrl', 'Tajik', 'Тоҷикӣ', 'tg-TJ'],
|
|||
|
|
['khk_Cyrl', 'Mongolian', 'Монгол', 'mn-MN'],
|
|||
|
|
['bod_Tibt', 'Tibetan', 'བོད་སྐད་', 'bo'],
|
|||
|
|
['gle_Latn', 'Irish', 'Gaeilge', 'ga-IE'],
|
|||
|
|
['cym_Latn', 'Welsh', 'Cymraeg', 'cy-GB'],
|
|||
|
|
['eus_Latn', 'Basque', 'Euskara', 'eu-ES'],
|
|||
|
|
['cat_Latn', 'Catalan', 'Català', 'ca-ES'],
|
|||
|
|
['glg_Latn', 'Galician', 'Galego', 'gl-ES'],
|
|||
|
|
['quy_Latn', 'Quechua', 'Runasimi', 'qu'],
|
|||
|
|
['ayr_Latn', 'Aymara', 'Aymar aru', 'ay'],
|
|||
|
|
['grn_Latn', 'Guarani', "Avañe'ẽ", 'gn'],
|
|||
|
|
['mri_Latn', 'Maori', 'Te Reo Māori', 'mi-NZ'],
|
|||
|
|
['smo_Latn', 'Samoan', 'Gagana Samoa', 'sm'],
|
|||
|
|
['fij_Latn', 'Fijian', 'Na Vosa Vakaviti', 'fj'],
|
|||
|
|
['tpi_Latn', 'Tok Pisin', 'Tok Pisin', 'tpi']
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
var LANGS = RAW.map(function (r) {
|
|||
|
|
return { code: r[0], name: r[1], native: r[2], tts: r[3], rtl: !!r[4] };
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
var BY_CODE = {};
|
|||
|
|
LANGS.forEach(function (l) { BY_CODE[l.code] = l; });
|
|||
|
|
|
|||
|
|
// A sane opening set for a US church. The operator can change this at any time.
|
|||
|
|
var DEFAULT_FEATURED = [
|
|||
|
|
'spa_Latn', 'zho_Hans', 'por_Latn', 'fra_Latn',
|
|||
|
|
'kor_Hang', 'vie_Latn', 'hat_Latn', 'arb_Arab'
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
function get(code) { return BY_CODE[code] || null; }
|
|||
|
|
|
|||
|
|
function label(code) {
|
|||
|
|
var l = BY_CODE[code];
|
|||
|
|
if (!l) return code;
|
|||
|
|
return l.native === l.name ? l.native : l.native + ' · ' + l.name;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Case- and accent-insensitive search across both names and the code, so
|
|||
|
|
"espanol", "Español", "spanish" and "spa" all find Spanish. */
|
|||
|
|
function normalize(s) {
|
|||
|
|
return String(s || '')
|
|||
|
|
.toLowerCase()
|
|||
|
|
.normalize('NFD')
|
|||
|
|
.replace(/[̀-ͯ]/g, '');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function search(query) {
|
|||
|
|
var q = normalize(query).trim();
|
|||
|
|
if (!q) return LANGS.slice();
|
|||
|
|
return LANGS.filter(function (l) {
|
|||
|
|
return normalize(l.name).indexOf(q) !== -1 ||
|
|||
|
|
normalize(l.native).indexOf(q) !== -1 ||
|
|||
|
|
normalize(l.code).indexOf(q) !== -1;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
LANGS: LANGS,
|
|||
|
|
DEFAULT_FEATURED: DEFAULT_FEATURED,
|
|||
|
|
get: get,
|
|||
|
|
label: label,
|
|||
|
|
search: search,
|
|||
|
|
codes: function () { return LANGS.map(function (l) { return l.code; }); }
|
|||
|
|
};
|
|||
|
|
}));
|