#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Localized<'a> {
pub key: &'a str,
pub fallback: &'a str,
}
impl<'a> Localized<'a> {
pub const fn new(key: &'a str, fallback: &'a str) -> Self {
Self { key, fallback }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Translation<'a> {
pub key: &'a str,
pub value: &'a str,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct LocaleTable<'a> {
pub id: &'a str,
pub entries: &'a [Translation<'a>],
}
#[derive(Clone, Copy, Debug)]
pub struct I18n<'a> {
locale: &'a str,
fallback_locale: &'a str,
locales: &'a [LocaleTable<'a>],
}
impl<'a> I18n<'a> {
pub const fn new(
locale: &'a str,
fallback_locale: &'a str,
locales: &'a [LocaleTable<'a>],
) -> Self {
Self {
locale,
fallback_locale,
locales,
}
}
pub const fn locale(&self) -> &'a str {
self.locale
}
pub fn set_locale(&mut self, locale: &'a str) {
self.locale = locale;
}
pub fn text(&self, label: Localized<'a>) -> &'a str {
self.lookup(self.locale, label.key)
.or_else(|| self.lookup(self.fallback_locale, label.key))
.unwrap_or(label.fallback)
}
fn lookup(&self, locale: &str, key: &str) -> Option<&'a str> {
let table = self.locales.iter().find(|table| table.id == locale)?;
table
.entries
.iter()
.find(|entry| entry.key == key)
.map(|entry| entry.value)
}
}