use super::Locales;
use crate::errors::*;
use crate::i18n::Translator;
use crate::utils::fetch;
use crate::utils::get_path_prefix_client;
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug, Clone)]
pub(crate) struct ClientTranslationsManager {
cached_translator: Rc<RefCell<Option<Translator>>>,
locales: Locales,
}
impl ClientTranslationsManager {
pub(crate) fn new(locales: &Locales) -> Self {
Self {
cached_translator: Rc::new(RefCell::new(None)),
locales: locales.clone(),
}
}
pub(crate) fn get_translator(&self) -> Option<Translator> {
self.cached_translator.borrow().as_ref().cloned()
}
fn preflight_check(&self, locale: &str) -> Result<bool, ClientError> {
let mut cached_translator = self.cached_translator.borrow_mut();
if cached_translator.is_some() && cached_translator.as_ref().unwrap().get_locale() == locale
{
Ok(false)
} else {
if self.locales.is_supported(locale) && self.locales.using_i18n {
Ok(true)
} else if !self.locales.using_i18n {
let translator = Translator::new("xx-XX".to_string(), "".to_string()).unwrap();
*cached_translator = Some(translator);
Ok(false)
} else {
panic!("locale not supported (this is a bug)");
}
}
}
fn cache_translator(&self, translator: Translator) {
*self.cached_translator.borrow_mut() = Some(translator);
}
pub(crate) fn set_translator_for_translations_str(
&self,
locale: &str,
translations_str: &str,
) -> Result<(), ClientError> {
if self.preflight_check(locale)? {
let translator = match Translator::new(locale.to_string(), translations_str.to_string())
{
Ok(translator) => translator,
Err(err) => {
return Err(FetchError::SerFailed {
url: "*".to_string(),
source: err.into(),
ty: AssetType::Translations,
}
.into())
}
};
self.cache_translator(translator);
Self::set_html_lang(locale);
}
Ok(())
}
pub(crate) async fn set_translator_for_locale<'a>(
&'a self,
locale: &'a str,
) -> Result<(), ClientError> {
if self.preflight_check(locale)? {
let path_prefix = get_path_prefix_client();
let asset_url = format!("{}/.perseus/translations/{}", path_prefix, locale);
let translations_str = fetch(&asset_url, AssetType::Translations).await?;
match translations_str {
Some(translations_str) => {
self.set_translator_for_translations_str(locale, &translations_str)?;
Self::set_html_lang(locale);
}
None => {
return Err(ClientInvariantError::ValidLocaleNotProvided {
locale: locale.to_string(),
}
.into())
}
};
}
Ok(())
}
fn set_html_lang(locale: &str) {
let document = web_sys::window().unwrap().document().unwrap();
let html = document.document_element().unwrap();
let _ = html.set_attribute("lang", locale);
}
}