🥅 Add safe results handling

This commit is contained in:
Manuel Cillero 2023-10-23 18:48:08 +02:00
parent 350829c3c8
commit 916e5d3300
6 changed files with 107 additions and 14 deletions

View file

@ -129,6 +129,9 @@ static_locales!(LOCALES_PAGETOP);
// PUBLIC API.
// *************************************************************************************************
// Handling safe results.
pub mod result;
// Functions and macro helpers.
pub mod util;

View file

@ -88,16 +88,21 @@
//! ```
use crate::html::{Markup, PreEscaped};
use crate::{config, kv, trace, LazyStatic, LOCALES_PAGETOP};
use crate::result::{SafeResult, TraceErr};
use crate::{config, kv, LazyStatic, LOCALES_PAGETOP};
pub use fluent_templates;
pub use unic_langid::LanguageIdentifier;
pub(crate) use fluent_templates::Loader;
pub(crate) use fluent_templates::StaticLoader as Locales;
pub(crate) use unic_langid::{langid, LanguageIdentifier};
use unic_langid::langid;
use std::collections::HashMap;
const LANGUAGE_SET_FAILURE: &str = "language_set_failure";
static LANGUAGES: LazyStatic<HashMap<String, (LanguageIdentifier, &str)>> = LazyStatic::new(|| {
kv![
"en" => (langid!("en-US"), "English"),
@ -114,19 +119,22 @@ static FALLBACK_LANGID: LazyStatic<LanguageIdentifier> = LazyStatic::new(|| lang
/// ([Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier))
/// global para la aplicación a partir de `SETTINGS.app.language`.
pub(crate) static LANGID: LazyStatic<&LanguageIdentifier> =
LazyStatic::new(|| langid_for(config::SETTINGS.app.language.as_str()));
LazyStatic::new(|| langid_for(config::SETTINGS.app.language.as_str()).unwrap_or_fallback());
pub fn langid_for(language: &str) -> &LanguageIdentifier {
match LANGUAGES.get(language) {
Some((langid, _)) => langid,
_ => {
trace::warn!(
"{} \"{}\"! {}",
"Failed to set language. Unicode Language Identifier",
config::SETTINGS.app.language,
"is not accepted. Using \"en-US\", check the settings file",
);
&FALLBACK_LANGID
pub fn langid_for(language: impl Into<String>) -> SafeResult<&'static LanguageIdentifier> {
let language = language.into();
match LANGUAGES.get(language.as_str()) {
Some((langid, _)) => SafeResult::Ok(langid),
None => {
if language.is_empty() {
SafeResult::Ok(&FALLBACK_LANGID)
} else {
SafeResult::Err(TraceErr::warn(
L10n::l(LANGUAGE_SET_FAILURE)
.with_arg("language", config::SETTINGS.app.language.as_str()),
&FALLBACK_LANGID,
))
}
}
}
}
@ -230,6 +238,32 @@ impl L10n {
}
}
pub(crate) fn message(&self) -> String {
match &self.op {
L10nOp::None => "".to_owned(),
L10nOp::Text(text) => text.to_owned(),
L10nOp::Translate(key) => match self.locales {
Some(locales) => locales
.lookup_with_args(
match key.as_str() {
LANGUAGE_SET_FAILURE => &FALLBACK_LANGID,
_ => &LANGID,
},
key,
&self
.args
.iter()
.fold(HashMap::new(), |mut args, (key, value)| {
args.insert(key.to_string(), value.to_owned().into());
args
}),
)
.unwrap_or(key.to_owned()),
None => key.to_owned(),
},
}
}
pub fn escaped(&self, langid: &LanguageIdentifier) -> Markup {
PreEscaped(self.using(langid).unwrap_or_default())
}

View file

@ -0,0 +1,4 @@
# DEBUG.
# ERRORS.
language_set_failure = Failed to set language. Unicode Language Identifier "{$language}" is not accepted. Using "en-US", check the settings file

View file

@ -0,0 +1,4 @@
# DEBUG.
# ERRORS.
language_set_failure = Error al establecer idioma. El Identificador de Lenguaje Unicode "{$language}" no es válido. Se usará "en-US". Comprobar archivo de configuración

View file

@ -6,6 +6,9 @@ pub use crate::{concat_string, fn_builder, main, paste, test};
// Global.
pub use crate::{Handle, HashMapResources, LazyStatic, ResultExt, Weight};
// Handling safe results.
pub use crate::result::{SafeResult, TraceErr};
// Functions and macro helpers.
pub use crate::util;
pub use crate::{kv, new_handle};

45
pagetop/src/result.rs Normal file
View file

@ -0,0 +1,45 @@
//! Handling safe results.
use crate::locale::L10n;
use crate::trace;
pub struct TraceErr<T> {
message: String,
fallback: T,
}
impl<T> TraceErr<T> {
pub fn warn(trace: L10n, fallback: T) -> Self {
let message = trace.message();
trace::warn!(message);
TraceErr { message, fallback }
}
pub fn error(trace: L10n, fallback: T) -> Self {
let message = trace.message();
trace::error!(message);
TraceErr { message, fallback }
}
pub fn message(self) -> String {
self.message
}
pub fn fallback(self) -> T {
self.fallback
}
}
pub enum SafeResult<T> {
Ok(T),
Err(TraceErr<T>),
}
impl<T> SafeResult<T> {
pub fn unwrap_or_fallback(self) -> T {
match self {
SafeResult::Ok(result) => result,
SafeResult::Err(trace) => trace.fallback(),
}
}
}