use crate::reactor::Reactor;
use crate::translator::errors::*;
use crate::PerseusNodeType;
use std::collections::HashMap;
use sycamore::prelude::{use_context, Scope, Signal};
pub const LIGHTWEIGHT_TRANSLATOR_FILE_EXT: &str = "json";
#[derive(Clone)]
pub struct LightweightTranslator {
locale: String,
translations: HashMap<String, String>,
}
impl std::fmt::Debug for LightweightTranslator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LightweightTranslator")
.field("locale", &self.locale)
.finish()
}
}
impl LightweightTranslator {
pub fn new(locale: String, json_string: String) -> Result<Self, TranslatorError> {
let translations =
serde_json::from_str::<HashMap<String, String>>(&json_string).map_err(|err| {
TranslatorError::TranslationsStrSerFailed {
locale: locale.to_string(),
source: err.into(),
}
})?;
Ok(Self {
translations,
locale,
})
}
pub fn url(&self, url: &str) -> String {
let url = url.strip_prefix('/').unwrap_or(url);
format!("{}/{}", self.locale, url)
}
pub fn get_locale(&self) -> String {
self.locale.clone()
}
pub fn translate(&self, id: &str, args: Option<TranslationArgs>) -> String {
let translation_res = self.translate_checked(id, args);
match translation_res {
Ok(translation) => translation,
Err(_) => panic!("translation id '{}' not found for locale '{}' (if you're not hardcoding the id, use `.translate_checked()` instead)", id, self.locale)
}
}
pub fn translate_checked(
&self,
id: &str,
args: Option<TranslationArgs>,
) -> Result<String, TranslatorError> {
match self.translations.get(id) {
Some(translation) => {
let mut translation = translation.to_string();
if let Some(args) = args {
for (k, v) in args.0.iter() {
translation = translation.replace(&format!("{{ ${} }}", k), v);
}
}
Ok(translation)
}
None => Err(TranslatorError::TranslationIdNotFound {
locale: self.locale.to_string(),
id: id.to_string(),
}),
}
}
pub fn get_bundle(&self) -> &HashMap<String, String> {
&self.translations
}
}
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct TranslationArgs(pub HashMap<String, String>);
impl TranslationArgs {
pub fn set(&mut self, k: &str, v: &str) -> Option<String> {
self.0.insert(k.to_string(), v.to_string())
}
pub fn get(&self, k: &str) -> Option<&String> {
self.0.get(k)
}
pub fn new() -> Self {
Self(HashMap::new())
}
}
#[doc(hidden)]
pub fn t_macro_backend(id: &str, cx: Scope) -> String {
let translator = use_context::<Reactor<PerseusNodeType>>(cx).get_translator();
translator.translate(id, None)
}
#[doc(hidden)]
pub fn t_macro_backend_with_args(id: &str, args: TranslationArgs, cx: Scope) -> String {
let translator = use_context::<Reactor<PerseusNodeType>>(cx).get_translator();
translator.translate(id, Some(args))
}
#[doc(hidden)]
pub fn link_macro_backend(url: &str, cx: Scope) -> String {
let translator = use_context::<Reactor<PerseusNodeType>>(cx).get_translator();
translator.url(url)
}