167 lines
4.6 KiB
Rust
167 lines
4.6 KiB
Rust
//! Selectable transcription languages (T8.7, FR-TRX-4, M4.2) — the Settings
|
|
//! language dropdown shown when a multilingual model is active.
|
|
//!
|
|
//! ponytail: a fixed table, not a runtime query against whisper.cpp's
|
|
//! `whisper_lang_str`/`whisper_lang_max_id` — the ~100-language set whisper.cpp
|
|
//! ships is effectively static (OpenAI's Whisper `tokenizer.py` LANGUAGES
|
|
//! table), and hardcoding it here means the list is available to the UI even
|
|
//! before any model is loaded (no `cpu-transcription` feature dependency).
|
|
|
|
use crate::models::LanguageOption;
|
|
|
|
/// `(ISO-639-1 code, display label)`, exactly the codes whisper.cpp accepts
|
|
/// via `whisper_full_params.language`.
|
|
const LANGUAGES: &[(&str, &str)] = &[
|
|
("en", "English"),
|
|
("zh", "Chinese"),
|
|
("de", "German"),
|
|
("es", "Spanish"),
|
|
("ru", "Russian"),
|
|
("ko", "Korean"),
|
|
("fr", "French"),
|
|
("ja", "Japanese"),
|
|
("pt", "Portuguese"),
|
|
("tr", "Turkish"),
|
|
("pl", "Polish"),
|
|
("ca", "Catalan"),
|
|
("nl", "Dutch"),
|
|
("ar", "Arabic"),
|
|
("sv", "Swedish"),
|
|
("it", "Italian"),
|
|
("id", "Indonesian"),
|
|
("hi", "Hindi"),
|
|
("fi", "Finnish"),
|
|
("vi", "Vietnamese"),
|
|
("he", "Hebrew"),
|
|
("uk", "Ukrainian"),
|
|
("el", "Greek"),
|
|
("ms", "Malay"),
|
|
("cs", "Czech"),
|
|
("ro", "Romanian"),
|
|
("da", "Danish"),
|
|
("hu", "Hungarian"),
|
|
("ta", "Tamil"),
|
|
("no", "Norwegian"),
|
|
("th", "Thai"),
|
|
("ur", "Urdu"),
|
|
("hr", "Croatian"),
|
|
("bg", "Bulgarian"),
|
|
("lt", "Lithuanian"),
|
|
("la", "Latin"),
|
|
("mi", "Maori"),
|
|
("ml", "Malayalam"),
|
|
("cy", "Welsh"),
|
|
("sk", "Slovak"),
|
|
("te", "Telugu"),
|
|
("fa", "Persian"),
|
|
("lv", "Latvian"),
|
|
("bn", "Bengali"),
|
|
("sr", "Serbian"),
|
|
("az", "Azerbaijani"),
|
|
("sl", "Slovenian"),
|
|
("kn", "Kannada"),
|
|
("et", "Estonian"),
|
|
("mk", "Macedonian"),
|
|
("br", "Breton"),
|
|
("eu", "Basque"),
|
|
("is", "Icelandic"),
|
|
("hy", "Armenian"),
|
|
("ne", "Nepali"),
|
|
("mn", "Mongolian"),
|
|
("bs", "Bosnian"),
|
|
("kk", "Kazakh"),
|
|
("sq", "Albanian"),
|
|
("sw", "Swahili"),
|
|
("gl", "Galician"),
|
|
("mr", "Marathi"),
|
|
("pa", "Punjabi"),
|
|
("si", "Sinhala"),
|
|
("km", "Khmer"),
|
|
("sn", "Shona"),
|
|
("yo", "Yoruba"),
|
|
("so", "Somali"),
|
|
("af", "Afrikaans"),
|
|
("oc", "Occitan"),
|
|
("ka", "Georgian"),
|
|
("be", "Belarusian"),
|
|
("tg", "Tajik"),
|
|
("sd", "Sindhi"),
|
|
("gu", "Gujarati"),
|
|
("am", "Amharic"),
|
|
("yi", "Yiddish"),
|
|
("lo", "Lao"),
|
|
("uz", "Uzbek"),
|
|
("fo", "Faroese"),
|
|
("ht", "Haitian Creole"),
|
|
("ps", "Pashto"),
|
|
("tk", "Turkmen"),
|
|
("nn", "Nynorsk"),
|
|
("mt", "Maltese"),
|
|
("sa", "Sanskrit"),
|
|
("lb", "Luxembourgish"),
|
|
("my", "Myanmar"),
|
|
("bo", "Tibetan"),
|
|
("tl", "Tagalog"),
|
|
("mg", "Malagasy"),
|
|
("as", "Assamese"),
|
|
("tt", "Tatar"),
|
|
("haw", "Hawaiian"),
|
|
("ln", "Lingala"),
|
|
("ha", "Hausa"),
|
|
("ba", "Bashkir"),
|
|
("jw", "Javanese"),
|
|
("su", "Sundanese"),
|
|
("yue", "Cantonese"),
|
|
];
|
|
|
|
/// The dropdown's contents (`list_whisper_languages` command) — "Auto-detect"
|
|
/// itself is not in this list; the frontend prepends it (maps to `None`/no
|
|
/// `language` argument).
|
|
pub fn list() -> Vec<LanguageOption> {
|
|
LANGUAGES
|
|
.iter()
|
|
.map(|(code, label)| LanguageOption {
|
|
code: code.to_string(),
|
|
label: label.to_string(),
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
/// Whether `code` is a known whisper.cpp language code (case-insensitive).
|
|
/// Used to validate an explicit selection before it's forced into
|
|
/// `FullParams::set_language` — an unrecognized code is still passed through
|
|
/// to whisper.cpp (it may support codes we haven't listed), but callers use
|
|
/// this to warn rather than silently accept a typo.
|
|
pub fn is_known(code: &str) -> bool {
|
|
LANGUAGES.iter().any(|(c, _)| c.eq_ignore_ascii_case(code))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn list_includes_english_and_common_languages() {
|
|
let langs = list();
|
|
assert!(langs.iter().any(|l| l.code == "en" && l.label == "English"));
|
|
assert!(langs.iter().any(|l| l.code == "es"));
|
|
assert!(langs.iter().any(|l| l.code == "fr"));
|
|
}
|
|
|
|
#[test]
|
|
fn codes_are_unique() {
|
|
let mut codes: Vec<&str> = LANGUAGES.iter().map(|(c, _)| *c).collect();
|
|
let before = codes.len();
|
|
codes.sort_unstable();
|
|
codes.dedup();
|
|
assert_eq!(before, codes.len(), "duplicate language code in catalog");
|
|
}
|
|
|
|
#[test]
|
|
fn is_known_is_case_insensitive() {
|
|
assert!(is_known("en"));
|
|
assert!(is_known("ES"));
|
|
assert!(!is_known("xx-not-a-real-code"));
|
|
}
|
|
}
|