use deserr::Deserr; use milli::{tokenizer::Language, LocalizedAttributesRule}; use serde::{Deserialize, Serialize}; use serde_json::json; use strum::{EnumIter, IntoEnumIterator}; #[derive( Debug, Copy, Clone, PartialEq, Eq, Deserr, Serialize, Deserialize, Ord, PartialOrd, EnumIter, )] #[deserr(rename_all = camelCase)] #[serde(rename_all = "camelCase")] pub enum Locale { // ISO 639-3 Afr, Aka, Amh, Ara, Aze, Bel, Ben, Bul, Cat, Ces, Cmn, Dan, Deu, Ell, Eng, Epo, Est, Fas, Fin, Fra, Guj, Heb, Hin, Hrv, Hun, Hye, Ind, Ita, Jav, Jpn, Kan, Kat, Khm, Kor, Lat, Lav, Lit, Mal, Mar, Mkd, Mya, Nep, Nld, Nob, Ori, Pan, Pes, Pol, Por, Ron, Rus, Sin, Slk, Slv, Sna, Spa, Srp, Swe, Tam, Tel, Tgl, Tha, Tuk, Tur, Ukr, Urd, Uzb, Vie, Yid, Zho, Zul, // ISO 639-1 Af, Ak, Am, Ar, Az, Be, Bn, Bg, Ca, Cs, Zh, Da, De, El, En, Eo, Et, Fi, Fr, Gu, He, Hi, Hr, Hu, Hy, Id, It, Jv, Ja, Kn, Ka, Km, Ko, La, Lv, Lt, Ml, Mr, Mk, My, Ne, Nl, Nb, Or, Pa, Fa, Pl, Pt, Ro, Ru, Si, Sk, Sl, Sn, Es, Sr, Sv, Ta, Te, Tl, Th, Tk, Tr, Uk, Ur, Uz, Vi, Yi, Zu, } impl From for Language { fn from(other: Locale) -> Language { match other { // ISO 639-3 Locale::Afr => Language::Afr, Locale::Aka => Language::Aka, Locale::Amh => Language::Amh, Locale::Ara => Language::Ara, Locale::Aze => Language::Aze, Locale::Bel => Language::Bel, Locale::Ben => Language::Ben, Locale::Bul => Language::Bul, Locale::Cat => Language::Cat, Locale::Ces => Language::Ces, Locale::Cmn => Language::Cmn, Locale::Dan => Language::Dan, Locale::Deu => Language::Deu, Locale::Ell => Language::Ell, Locale::Eng => Language::Eng, Locale::Epo => Language::Epo, Locale::Est => Language::Est, Locale::Fas => Language::Pes, Locale::Fin => Language::Fin, Locale::Fra => Language::Fra, Locale::Guj => Language::Guj, Locale::Heb => Language::Heb, Locale::Hin => Language::Hin, Locale::Hrv => Language::Hrv, Locale::Hun => Language::Hun, Locale::Hye => Language::Hye, Locale::Ind => Language::Ind, Locale::Ita => Language::Ita, Locale::Jav => Language::Jav, Locale::Jpn => Language::Jpn, Locale::Kan => Language::Kan, Locale::Kat => Language::Kat, Locale::Khm => Language::Khm, Locale::Kor => Language::Kor, Locale::Lat => Language::Lat, Locale::Lav => Language::Lav, Locale::Lit => Language::Lit, Locale::Mal => Language::Mal, Locale::Mar => Language::Mar, Locale::Mkd => Language::Mkd, Locale::Mya => Language::Mya, Locale::Nep => Language::Nep, Locale::Nld => Language::Nld, Locale::Nob => Language::Nob, Locale::Ori => Language::Ori, Locale::Pan => Language::Pan, Locale::Pes => Language::Pes, Locale::Pol => Language::Pol, Locale::Por => Language::Por, Locale::Ron => Language::Ron, Locale::Rus => Language::Rus, Locale::Sin => Language::Sin, Locale::Slk => Language::Slk, Locale::Slv => Language::Slv, Locale::Sna => Language::Sna, Locale::Spa => Language::Spa, Locale::Srp => Language::Srp, Locale::Swe => Language::Swe, Locale::Tam => Language::Tam, Locale::Tel => Language::Tel, Locale::Tgl => Language::Tgl, Locale::Tha => Language::Tha, Locale::Tuk => Language::Tuk, Locale::Tur => Language::Tur, Locale::Ukr => Language::Ukr, Locale::Urd => Language::Urd, Locale::Uzb => Language::Uzb, Locale::Vie => Language::Vie, Locale::Yid => Language::Yid, Locale::Zho => Language::Cmn, Locale::Zul => Language::Zul, // ISO 639-1 Locale::Af => Language::Afr, Locale::Ak => Language::Aka, Locale::Am => Language::Amh, Locale::Ar => Language::Ara, Locale::Az => Language::Aze, Locale::Be => Language::Bel, Locale::Bn => Language::Ben, Locale::Bg => Language::Bul, Locale::Ca => Language::Cat, Locale::Cs => Language::Ces, Locale::Zh => Language::Cmn, Locale::Da => Language::Dan, Locale::De => Language::Deu, Locale::El => Language::Ell, Locale::En => Language::Eng, Locale::Eo => Language::Epo, Locale::Et => Language::Est, Locale::Fi => Language::Fin, Locale::Fr => Language::Fra, Locale::Gu => Language::Guj, Locale::He => Language::Heb, Locale::Hi => Language::Hin, Locale::Hr => Language::Hrv, Locale::Hu => Language::Hun, Locale::Hy => Language::Hye, Locale::Id => Language::Ind, Locale::It => Language::Ita, Locale::Jv => Language::Jav, Locale::Ja => Language::Jpn, Locale::Kn => Language::Kan, Locale::Ka => Language::Kat, Locale::Km => Language::Khm, Locale::Ko => Language::Kor, Locale::La => Language::Lat, Locale::Lv => Language::Lav, Locale::Lt => Language::Lit, Locale::Ml => Language::Mal, Locale::Mr => Language::Mar, Locale::Mk => Language::Mkd, Locale::My => Language::Mya, Locale::Ne => Language::Nep, Locale::Nl => Language::Nld, Locale::Nb => Language::Nob, Locale::Or => Language::Ori, Locale::Pa => Language::Pan, Locale::Fa => Language::Pes, Locale::Pl => Language::Pol, Locale::Pt => Language::Por, Locale::Ro => Language::Ron, Locale::Ru => Language::Rus, Locale::Si => Language::Sin, Locale::Sk => Language::Slk, Locale::Sl => Language::Slv, Locale::Sn => Language::Sna, Locale::Es => Language::Spa, Locale::Sr => Language::Srp, Locale::Sv => Language::Swe, Locale::Ta => Language::Tam, Locale::Te => Language::Tel, Locale::Tl => Language::Tgl, Locale::Th => Language::Tha, Locale::Tk => Language::Tuk, Locale::Tr => Language::Tur, Locale::Uk => Language::Ukr, Locale::Ur => Language::Urd, Locale::Uz => Language::Uzb, Locale::Vi => Language::Vie, Locale::Yi => Language::Yid, Locale::Zu => Language::Zul, } } } impl From for Locale { fn from(other: Language) -> Locale { match other { Language::Afr => Locale::Afr, Language::Aka => Locale::Aka, Language::Amh => Locale::Amh, Language::Ara => Locale::Ara, Language::Aze => Locale::Aze, Language::Bel => Locale::Bel, Language::Ben => Locale::Ben, Language::Bul => Locale::Bul, Language::Cat => Locale::Cat, Language::Ces => Locale::Ces, Language::Cmn => Locale::Zho, Language::Dan => Locale::Dan, Language::Deu => Locale::Deu, Language::Ell => Locale::Ell, Language::Eng => Locale::Eng, Language::Epo => Locale::Epo, Language::Est => Locale::Est, Language::Fin => Locale::Fin, Language::Fra => Locale::Fra, Language::Guj => Locale::Guj, Language::Heb => Locale::Heb, Language::Hin => Locale::Hin, Language::Hrv => Locale::Hrv, Language::Hun => Locale::Hun, Language::Hye => Locale::Hye, Language::Ind => Locale::Ind, Language::Ita => Locale::Ita, Language::Jav => Locale::Jav, Language::Jpn => Locale::Jpn, Language::Kan => Locale::Kan, Language::Kat => Locale::Kat, Language::Khm => Locale::Khm, Language::Kor => Locale::Kor, Language::Lat => Locale::Lat, Language::Lav => Locale::Lav, Language::Lit => Locale::Lit, Language::Mal => Locale::Mal, Language::Mar => Locale::Mar, Language::Mkd => Locale::Mkd, Language::Mya => Locale::Mya, Language::Nep => Locale::Nep, Language::Nld => Locale::Nld, Language::Nob => Locale::Nob, Language::Ori => Locale::Ori, Language::Pan => Locale::Pan, Language::Pes => Locale::Fas, Language::Pol => Locale::Pol, Language::Por => Locale::Por, Language::Ron => Locale::Ron, Language::Rus => Locale::Rus, Language::Sin => Locale::Sin, Language::Slk => Locale::Slk, Language::Slv => Locale::Slv, Language::Sna => Locale::Sna, Language::Spa => Locale::Spa, Language::Srp => Locale::Srp, Language::Swe => Locale::Swe, Language::Tam => Locale::Tam, Language::Tel => Locale::Tel, Language::Tgl => Locale::Tgl, Language::Tha => Locale::Tha, Language::Tuk => Locale::Tuk, Language::Tur => Locale::Tur, Language::Ukr => Locale::Ukr, Language::Urd => Locale::Urd, Language::Uzb => Locale::Uzb, Language::Vie => Locale::Vie, Language::Yid => Locale::Yid, Language::Zul => Locale::Zul, } } } #[derive(Debug)] pub struct LocaleFormatError { pub invalid_locale: String, } impl std::fmt::Display for LocaleFormatError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let valid_locales = Locale::iter() .map(|l| format!("`{}`", json!(l).as_str().unwrap())) .collect::>() .join(", "); write!(f, "Unsupported locale `{}`, expected one of {}", self.invalid_locale, valid_locales) } } impl std::error::Error for LocaleFormatError {} impl std::str::FromStr for Locale { type Err = LocaleFormatError; fn from_str(s: &str) -> Result { let locale = match s { // ISO 639-3 "afr" => Locale::Afr, "aka" => Locale::Aka, "amh" => Locale::Amh, "ara" => Locale::Ara, "aze" => Locale::Aze, "bel" => Locale::Bel, "ben" => Locale::Ben, "bul" => Locale::Bul, "cat" => Locale::Cat, "ces" => Locale::Ces, "cmn" => Locale::Cmn, "dan" => Locale::Dan, "deu" => Locale::Deu, "ell" => Locale::Ell, "eng" => Locale::Eng, "epo" => Locale::Epo, "est" => Locale::Est, "fas" => Locale::Fas, "fin" => Locale::Fin, "fra" => Locale::Fra, "guj" => Locale::Guj, "heb" => Locale::Heb, "hin" => Locale::Hin, "hrv" => Locale::Hrv, "hun" => Locale::Hun, "hye" => Locale::Hye, "ind" => Locale::Ind, "ita" => Locale::Ita, "jav" => Locale::Jav, "jpn" => Locale::Jpn, "kan" => Locale::Kan, "kat" => Locale::Kat, "khm" => Locale::Khm, "kor" => Locale::Kor, "lat" => Locale::Lat, "lav" => Locale::Lav, "lit" => Locale::Lit, "mal" => Locale::Mal, "mar" => Locale::Mar, "mkd" => Locale::Mkd, "mya" => Locale::Mya, "nep" => Locale::Nep, "nld" => Locale::Nld, "nob" => Locale::Nob, "ori" => Locale::Ori, "pan" => Locale::Pan, "pes" => Locale::Pes, "pol" => Locale::Pol, "por" => Locale::Por, "ron" => Locale::Ron, "rus" => Locale::Rus, "sin" => Locale::Sin, "slk" => Locale::Slk, "slv" => Locale::Slv, "sna" => Locale::Sna, "spa" => Locale::Spa, "srp" => Locale::Srp, "swe" => Locale::Swe, "tam" => Locale::Tam, "tel" => Locale::Tel, "tgl" => Locale::Tgl, "tha" => Locale::Tha, "tuk" => Locale::Tuk, "tur" => Locale::Tur, "ukr" => Locale::Ukr, "urd" => Locale::Urd, "uzb" => Locale::Uzb, "vie" => Locale::Vie, "yid" => Locale::Yid, "zho" => Locale::Zho, "zul" => Locale::Zul, // ISO 639-1 "af" => Locale::Af, "ak" => Locale::Ak, "am" => Locale::Am, "ar" => Locale::Ar, "az" => Locale::Az, "be" => Locale::Be, "bn" => Locale::Bn, "bg" => Locale::Bg, "ca" => Locale::Ca, "cs" => Locale::Cs, "zh" => Locale::Zh, "da" => Locale::Da, "de" => Locale::De, "el" => Locale::El, "en" => Locale::En, "eo" => Locale::Eo, "et" => Locale::Et, "fi" => Locale::Fi, "fr" => Locale::Fr, "gu" => Locale::Gu, "he" => Locale::He, "hi" => Locale::Hi, "hr" => Locale::Hr, "hu" => Locale::Hu, "hy" => Locale::Hy, "id" => Locale::Id, "it" => Locale::It, "jv" => Locale::Jv, "ja" => Locale::Ja, "kn" => Locale::Kn, "ka" => Locale::Ka, "km" => Locale::Km, "ko" => Locale::Ko, "la" => Locale::La, "lv" => Locale::Lv, "lt" => Locale::Lt, "ml" => Locale::Ml, "mr" => Locale::Mr, "mk" => Locale::Mk, "my" => Locale::My, "ne" => Locale::Ne, "nl" => Locale::Nl, "nb" => Locale::Nb, "or" => Locale::Or, "pa" => Locale::Pa, "fa" => Locale::Fa, "pl" => Locale::Pl, "pt" => Locale::Pt, "ro" => Locale::Ro, "ru" => Locale::Ru, "si" => Locale::Si, "sk" => Locale::Sk, "sl" => Locale::Sl, "sn" => Locale::Sn, "es" => Locale::Es, "sr" => Locale::Sr, "sv" => Locale::Sv, "ta" => Locale::Ta, "te" => Locale::Te, "tl" => Locale::Tl, "th" => Locale::Th, "tk" => Locale::Tk, "tr" => Locale::Tr, "uk" => Locale::Uk, "ur" => Locale::Ur, "uz" => Locale::Uz, "vi" => Locale::Vi, "yi" => Locale::Yi, "zu" => Locale::Zu, // otherwise _ => return Err(LocaleFormatError { invalid_locale: s.to_string() }), }; Ok(locale) } } #[derive(Debug, Clone, PartialEq, Eq, Deserr, Serialize, Deserialize)] #[deserr(rename_all = camelCase)] #[serde(rename_all = "camelCase")] pub struct LocalizedAttributesRuleView { pub attribute_patterns: Vec, pub locales: Vec, } impl From for LocalizedAttributesRuleView { fn from(rule: LocalizedAttributesRule) -> Self { Self { attribute_patterns: rule.attribute_patterns, locales: rule.locales.into_iter().map(|l| l.into()).collect(), } } } impl From for LocalizedAttributesRule { fn from(view: LocalizedAttributesRuleView) -> Self { Self { attribute_patterns: view.attribute_patterns, locales: view.locales.into_iter().map(|l| l.into()).collect(), } } }