/** * The i18n module provides some simple internationalization support * in a way that is compatible with handlebars rendering */ use log::*; pub fn parse_languages(header: &str) -> Vec { trace!("Parsing languages from: {}", header); let mut results = vec![]; for part in header.split(",") { if let Ok(language) = Language::from(part) { results.push(language); } } results } #[derive(Clone, Debug)] pub struct Language { pub code: String, region: Option, quality: f64, } lazy_static! { static ref LANG_REGEX: regex::Regex = regex::Regex::new(r"(?P\w+)-?(?P\w+)?(;q=(?P([0-9]*[.])?[0-9]+)?)?").unwrap(); } impl Language { fn from(segment: &str) -> Result { if let Some(captures) = LANG_REGEX.captures(segment) { println!("caps: {:?}", captures); Ok(Language { code: captures.name("code").map_or("unknown".to_string(), |c| c.as_str().to_string()), region: captures.name("region").map_or(None, |c| Some(c.as_str().to_string())), quality: captures.name("quality").map_or(1.0, |c| c.as_str().parse().unwrap_or(0.0)), }) } else { Err(Error::Generic) } } } #[derive(Clone, Debug)] enum Error { Generic, } #[cfg(test)] mod tests { use super::*; #[test] fn language_from_segment() { let lang = Language::from("en-US"); assert!(lang.is_ok()); let lang = lang.unwrap(); assert_eq!("en", lang.code); assert_eq!(Some("US".to_string()), lang.region); assert_eq!(1.0, lang.quality); } #[test] fn parse_langs_simple() { let header = "en-US,en;q=0.5"; let langs = parse_languages(&header); assert_eq!(langs.len(), 2); } #[test] fn parse_langs_multi() { let header = "en-US,en;q=0.7,de-DE;q=0.3"; let langs = parse_languages(&header); assert_eq!(langs.len(), 3); let de = langs.get(2).unwrap(); assert_eq!("de", de.code); assert_eq!(0.3, de.quality); } }