use phf::Map;
use super::arabic::ARABIC_SYNONYMS;
use super::english::CURATED_SYNONYMS;
use super::french::FRENCH_SYNONYMS;
use super::german::GERMAN_SYNONYMS;
use super::spanish::SPANISH_SYNONYMS;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum LanguageHint {
#[default]
English,
Spanish,
Arabic,
French,
German,
Auto,
}
impl LanguageHint {
pub fn as_bcp47(self) -> &'static str {
match self {
LanguageHint::English => "en",
LanguageHint::Spanish => "es",
LanguageHint::Arabic => "ar",
LanguageHint::French => "fr",
LanguageHint::German => "de",
LanguageHint::Auto => "auto",
}
}
}
pub fn detect_language(text: &str) -> LanguageHint {
let sample: String = text.chars().take(512).collect();
let arabic_count = sample
.chars()
.filter(|&c| ('\u{0600}'..='\u{06FF}').contains(&c))
.count();
if arabic_count > 5 {
return LanguageHint::Arabic;
}
let lower = sample.to_lowercase();
let spanish_score: usize = [
"ción", "que ", " de ", " en ", " la ", " el ", "ñ", "¿", "¡",
]
.iter()
.filter(|&&s| lower.contains(s))
.count();
let french_score: usize = [
"tion", " de ", " le ", " la ", " un ", " des ", "œ", "ê", "â",
]
.iter()
.filter(|&&s| lower.contains(s))
.count();
let german_score: usize = [
"sch ", " die ", " der ", " und ", " ist ", "ä", "ö", "ü", "ß",
]
.iter()
.filter(|&&s| lower.contains(s))
.count();
let max = spanish_score.max(french_score).max(german_score);
if max < 2 {
return LanguageHint::English;
}
if spanish_score == max {
return LanguageHint::Spanish;
}
if french_score == max {
return LanguageHint::French;
}
if german_score == max {
return LanguageHint::German;
}
LanguageHint::English
}
pub fn synonyms_for(lang: LanguageHint) -> &'static Map<&'static str, &'static [&'static str]> {
match lang {
LanguageHint::Spanish => &SPANISH_SYNONYMS,
LanguageHint::French => &FRENCH_SYNONYMS,
LanguageHint::German => &GERMAN_SYNONYMS,
LanguageHint::Arabic => &ARABIC_SYNONYMS,
_ => &CURATED_SYNONYMS,
}
}