use std::collections::HashMap;
use super::key::Key;
use super::opts::Opts;
#[derive(Debug)]
pub struct Dictionary {
pub(crate) inner: HashMap<String, serde_json::Value>,
pub default_locale: String,
}
impl Default for Dictionary {
fn default() -> Self {
Self {
inner: HashMap::new(),
default_locale: "en".into(),
}
}
}
impl Dictionary {
pub fn translate<'a, K: Into<Key<'a>>, I: Into<Opts<'a>>>(
&self,
key: K,
opts: I,
) -> super::err::Result<String> {
let opts = opts.into();
let mut key = key.into();
let alt_key;
match opts.count {
Some(0) => {
alt_key = key.chain(["zero"].as_ref());
key = alt_key;
}
Some(1) => {
alt_key = key.chain(["one"].as_ref());
key = alt_key;
}
Some(_) => {
alt_key = key.chain(["other"].as_ref());
key = alt_key;
}
_ => {}
}
let locale = opts.locale.unwrap_or_else(|| &self.default_locale);
let localized = self.inner.get(locale).ok_or_else(|| {
crate::err::Error::UnknownLocale(String::from(locale).into_boxed_str())
})?;
let entry = |key: Key| {
key.find(localized)
.and_then(|val| val.as_str())
.map(String::from)
.ok_or_else(|| crate::err::Error::UnknownKey(key.to_string().into_boxed_str()))
};
let value = match entry(key) {
Ok(value) => value,
Err(e) => match opts.default_key {
Some(default_key) => {
return entry(default_key);
}
_ => {
return Err(e);
}
},
};
match opts.vars {
Some(vars) => Ok(strfmt::strfmt(&value, &vars)?),
None => Ok(value),
}
}
pub fn t<'a, K: Into<Key<'a>>, I: Into<Opts<'a>>>(
&self,
key: K,
opts: I,
) -> crate::err::Result<String> {
self.translate(key, opts)
}
}
#[cfg(test)]
mod tests {
use crate::opts::{Count, DefaultKey, Opts, Var};
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "examples/locales/"]
struct Asset;
#[test]
fn it_works() {
let mut dict = crate::Config::default()
.with_embed::<Asset>()
.finish()
.unwrap();
assert_eq!(
dict.t(&["greeting"], None).unwrap(),
String::from("Hello, World!")
);
assert_eq!(
dict.t("missed", DefaultKey("missing.default")).unwrap(),
String::from("Sorry, that translation doesn't exist.")
);
assert_eq!(
dict.t(&["custom", "greeting"], Var("name", "Jacob"))
.unwrap(),
String::from("Hello, Jacob!!!")
);
assert_eq!(
dict.t("messages", Opts::default().count(1)).unwrap(),
String::from("You have one message.")
);
assert_eq!(
dict.t("messages", Opts::default().count(0)).unwrap(),
String::from("You have no messages.")
);
assert_eq!(
dict.t("messages", Count(200)).unwrap(),
String::from("You have 200 messages.")
);
assert!(dict.t("message.x", ()).is_err());
assert_eq!(
dict.t(
"a.very.nested.message",
(
Var("name", "you"),
Var("message", "\"a very nested message\"")
)
)
.unwrap(),
String::from("Hello, you. Your message is: \"a very nested message\"")
);
dict.default_locale = String::from("de");
assert_eq!(
dict.t("greeting", None).unwrap(),
String::from("Hallo Welt!")
);
}
}