mod iso_codes {
include!("iso_codes.rs");
}
pub use iso_codes::{Lang, LanguageTag, Market};
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Locale {
pub market: Market,
pub language: Lang,
pub include_neutral: bool,
}
impl Locale {
pub fn new(market: Market, language: Lang, include_neutral: bool) -> Self {
Locale {
market,
language,
include_neutral,
}
}
pub fn production() -> Self {
Locale::new(Market::Us, Lang::En, false)
}
pub fn dcat_trail(&self) -> String {
let market = self.market.as_str();
let lang = self.language.as_str();
if self.include_neutral && lang != "en" {
format!("market={market}&languages={lang},en&catalogsource=apps")
} else {
format!("market={market}&languages={lang}&catalogsource=apps")
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn production_locale_trail() {
let trail = Locale::production().dcat_trail();
assert_eq!(trail, "market=US&languages=en&catalogsource=apps");
}
#[test]
fn locale_with_neutral_fallback() {
let locale = Locale::new(Market::De, Lang::De, true);
assert_eq!(
locale.dcat_trail(),
"market=DE&languages=de,en&catalogsource=apps",
);
}
#[test]
fn locale_neutral_skipped_when_lang_is_en() {
let locale = Locale::new(Market::Us, Lang::En, true);
assert_eq!(
locale.dcat_trail(),
"market=US&languages=en&catalogsource=apps",
);
}
#[test]
fn market_roundtrip() {
assert_eq!(Market::Us.as_str(), "US");
assert_eq!(Market::Jp.as_str(), "JP");
assert_eq!(Market::Zw.as_str(), "ZW");
assert_eq!(Market::from_str("us").unwrap(), Market::Us);
assert_eq!(Market::from_str("ZW").unwrap(), Market::Zw);
assert!(Market::from_str("XX").is_err());
}
#[test]
fn lang_roundtrip() {
assert_eq!(Lang::En.as_str(), "en");
assert_eq!(Lang::Zh.as_str(), "zh");
assert_eq!(Lang::from_str("EN").unwrap(), Lang::En);
assert!(Lang::from_str("xx").is_err());
}
#[test]
fn language_tag_roundtrip() {
assert_eq!(LanguageTag::EnUs.as_str(), "en-US");
assert_eq!(LanguageTag::ZhHant.as_str(), "zh-Hant");
assert_eq!(LanguageTag::SrCyrlRs.as_str(), "sr-Cyrl-RS");
assert_eq!(LanguageTag::CaEsValencia.as_str(), "ca-ES-valencia");
assert_eq!(LanguageTag::from_str("en-us").unwrap(), LanguageTag::EnUs);
assert_eq!(
LanguageTag::from_str("ZH-HANT").unwrap(),
LanguageTag::ZhHant,
);
assert!(LanguageTag::from_str("xx-YY").is_err());
}
#[test]
fn english_names() {
assert_eq!(Market::Us.english_name(), "United States");
assert_eq!(Lang::En.english_name(), "English");
assert_eq!(LanguageTag::EnUs.english_name(), "English");
assert_eq!(LanguageTag::ZhHant.english_name(), "Chinese (Traditional)",);
}
#[test]
fn serde_uses_canonical_code() {
assert_eq!(serde_json::to_string(&Market::Us).unwrap(), "\"US\"",);
assert_eq!(
serde_json::from_str::<Market>("\"GB\"").unwrap(),
Market::Gb,
);
assert_eq!(serde_json::to_string(&Lang::En).unwrap(), "\"en\"",);
}
}