use crate::html::{Markup, PreEscaped};
use crate::{include_locales, AutoDefault, CowStr};
use super::{LangId, Locale};
use fluent_templates::Loader;
use fluent_templates::StaticLoader as Locales;
use std::collections::HashMap;
use std::fmt;
include_locales!(LOCALES_PAGETOP);
#[derive(AutoDefault, Clone, Debug)]
enum L10nOp {
#[default]
None,
Text(CowStr),
Translate(CowStr),
}
#[derive(AutoDefault, Clone)]
pub struct L10n {
op: L10nOp,
#[default(&LOCALES_PAGETOP)]
locales: &'static Locales,
args: Vec<(CowStr, CowStr)>,
}
impl fmt::Debug for L10n {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("L10n")
.field("op", &self.op)
.field("args", &self.args)
.field("locales", &"<StaticLoader>")
.finish()
}
}
impl L10n {
pub fn n(text: impl Into<CowStr>) -> Self {
Self {
op: L10nOp::Text(text.into()),
..Default::default()
}
}
pub fn l(key: impl Into<CowStr>) -> Self {
Self {
op: L10nOp::Translate(key.into()),
..Default::default()
}
}
pub fn t(key: impl Into<CowStr>, locales: &'static Locales) -> Self {
Self {
op: L10nOp::Translate(key.into()),
locales,
..Default::default()
}
}
pub fn with_arg(mut self, arg: impl Into<CowStr>, value: impl Into<CowStr>) -> Self {
self.args.push((arg.into(), value.into()));
self
}
pub fn with_args<I, K, V>(mut self, args: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
K: Into<CowStr>,
V: Into<CowStr>,
{
self.args
.extend(args.into_iter().map(|(k, v)| (k.into(), v.into())));
self
}
pub fn get(&self) -> Option<String> {
self.lookup(&Locale::default())
}
pub fn lookup(&self, language: &impl LangId) -> Option<String> {
match &self.op {
L10nOp::None => None,
L10nOp::Text(text) => Some(text.clone().into_owned()),
L10nOp::Translate(key) => {
if self.args.is_empty() {
self.locales.try_lookup(language.langid(), key.as_ref())
} else {
let mut args = HashMap::with_capacity(self.args.len());
for (k, v) in self.args.iter() {
args.insert(k.clone(), v.as_ref().into());
}
self.locales
.try_lookup_with_args(language.langid(), key.as_ref(), &args)
}
}
}
}
pub fn using(&self, language: &impl LangId) -> Markup {
PreEscaped(self.lookup(language).unwrap_or_default())
}
}