use crate::error::{ValidationIssue, VldError};
use std::collections::HashMap;
pub trait MessageResolver {
fn resolve(&self, key: &str) -> Option<String>;
}
pub struct MapResolver {
map: HashMap<String, String>,
}
impl MapResolver {
pub fn new(map: HashMap<String, String>) -> Self {
Self { map }
}
}
impl MessageResolver for MapResolver {
fn resolve(&self, key: &str) -> Option<String> {
self.map.get(key).cloned()
}
}
pub struct FnResolver<F: Fn(&str) -> Option<String>> {
f: F,
}
impl<F: Fn(&str) -> Option<String>> FnResolver<F> {
pub fn new(f: F) -> Self {
Self { f }
}
}
impl<F: Fn(&str) -> Option<String>> MessageResolver for FnResolver<F> {
fn resolve(&self, key: &str) -> Option<String> {
(self.f)(key)
}
}
fn apply_params(template: &str, params: &[(&str, String)]) -> String {
let mut result = template.to_string();
for (key, value) in params {
result = result.replace(&format!("{{{}}}", key), value);
}
result
}
pub fn translate_issue(issue: &ValidationIssue, resolver: &dyn MessageResolver) -> ValidationIssue {
let params = issue.code.params();
let message = match resolver.resolve(issue.code.key()) {
Some(template) => apply_params(&template, ¶ms),
None => issue.message.clone(),
};
ValidationIssue {
code: issue.code.clone(),
message,
path: issue.path.clone(),
received: issue.received.clone(),
}
}
pub fn translate_error(error: &VldError, resolver: &dyn MessageResolver) -> VldError {
VldError {
issues: error
.issues
.iter()
.map(|i| translate_issue(i, resolver))
.collect(),
}
}
pub fn english() -> MapResolver {
let mut m = HashMap::new();
m.insert(
"invalid_type".into(),
"Expected {expected}, received {received}".into(),
);
m.insert(
"too_small".into(),
"Value must be at least {minimum}".into(),
);
m.insert("too_big".into(), "Value must be at most {maximum}".into());
m.insert("invalid_string".into(), "Invalid {validation}".into());
m.insert("not_int".into(), "Expected integer, received float".into());
m.insert("not_finite".into(), "Number must be finite".into());
m.insert("missing_field".into(), "Required field is missing".into());
m.insert("unrecognized_field".into(), "Unrecognized field".into());
m.insert("parse_error".into(), "Failed to parse input".into());
MapResolver::new(m)
}
pub fn russian() -> MapResolver {
let mut m = HashMap::new();
m.insert(
"invalid_type".into(),
"Ожидалось {expected}, получено {received}".into(),
);
m.insert(
"too_small".into(),
"Значение должно быть не менее {minimum}".into(),
);
m.insert(
"too_big".into(),
"Значение должно быть не более {maximum}".into(),
);
m.insert(
"invalid_string".into(),
"Некорректное значение ({validation})".into(),
);
m.insert("not_int".into(), "Ожидалось целое число".into());
m.insert("not_finite".into(), "Число должно быть конечным".into());
m.insert(
"missing_field".into(),
"Обязательное поле отсутствует".into(),
);
m.insert("unrecognized_field".into(), "Неизвестное поле".into());
m.insert("parse_error".into(), "Ошибка разбора входных данных".into());
MapResolver::new(m)
}
pub fn german() -> MapResolver {
let mut m = HashMap::new();
m.insert(
"invalid_type".into(),
"{expected} erwartet, {received} erhalten".into(),
);
m.insert(
"too_small".into(),
"Wert muss mindestens {minimum} sein".into(),
);
m.insert(
"too_big".into(),
"Wert darf höchstens {maximum} sein".into(),
);
m.insert(
"invalid_string".into(),
"Ungültiger Wert ({validation})".into(),
);
m.insert("not_int".into(), "Ganzzahl erwartet".into());
m.insert("not_finite".into(), "Zahl muss endlich sein".into());
m.insert("missing_field".into(), "Pflichtfeld fehlt".into());
m.insert("unrecognized_field".into(), "Unbekanntes Feld".into());
m.insert(
"parse_error".into(),
"Eingabe konnte nicht verarbeitet werden".into(),
);
MapResolver::new(m)
}
pub fn spanish() -> MapResolver {
let mut m = HashMap::new();
m.insert(
"invalid_type".into(),
"Se esperaba {expected}, se recibió {received}".into(),
);
m.insert(
"too_small".into(),
"El valor debe ser al menos {minimum}".into(),
);
m.insert(
"too_big".into(),
"El valor debe ser como máximo {maximum}".into(),
);
m.insert(
"invalid_string".into(),
"Valor inválido ({validation})".into(),
);
m.insert("not_int".into(), "Se esperaba un número entero".into());
m.insert("not_finite".into(), "El número debe ser finito".into());
m.insert("missing_field".into(), "Campo obligatorio faltante".into());
m.insert("unrecognized_field".into(), "Campo no reconocido".into());
m.insert("parse_error".into(), "Error al procesar la entrada".into());
MapResolver::new(m)
}