use crate::errors::app_error::{AppError, AppResult};
use validator::ValidationErrors;
pub fn validate(req: &dyn validator::Validate) -> AppResult<()> {
match req.validate() {
Ok(()) => Ok(()),
Err(errors) => translate_errors(&errors),
}
}
fn translate_errors(errors: &ValidationErrors) -> AppResult<()> {
let locale = crate::middleware::locale::current_locale();
rust_i18n::set_locale(&locale);
let mut messages: Vec<String> = Vec::new();
for (field, field_errors) in errors.field_errors() {
let field_name = translate_field(field);
for error in field_errors {
let msg = match error.code.as_ref() {
"required" | "length" => {
let min = error
.params
.get("min")
.and_then(serde_json::Value::as_u64)
.map(|v| v.to_string());
let max = error
.params
.get("max")
.and_then(serde_json::Value::as_u64)
.map(|v| v.to_string());
let exact = error
.params
.get("value")
.and_then(serde_json::Value::as_u64)
.map(|v| v.to_string());
match (min.as_deref(), max.as_deref()) {
(Some(min), Some(max)) if min != max => rust_i18n::t!(
"validation.length_range",
field = field_name,
min = min,
max = max
)
.to_string(),
(Some(min), Some(_)) => {
rust_i18n::t!("validation.min_length", field = field_name, min = min)
.to_string()
}
(Some(min), None) => {
rust_i18n::t!("validation.min_length", field = field_name, min = min)
.to_string()
}
(None, Some(max)) => {
rust_i18n::t!("validation.max_length", field = field_name, max = max)
.to_string()
}
_ => {
if let Some(v) = exact {
rust_i18n::t!("validation.min_length", field = field_name, min = v)
.to_string()
} else {
rust_i18n::t!("validation.required", field = field_name).to_string()
}
}
}
}
"email" => rust_i18n::t!("validation.email_invalid").to_string(),
_ => rust_i18n::t!("validation.required", field = field_name).to_string(),
};
messages.push(msg);
}
}
Err(AppError::BadRequest(messages.join("; ")))
}
fn translate_field(field: &str) -> String {
let key = format!("fields.{field}");
let translated = rust_i18n::t!(&key);
if translated == key {
field.to_string()
} else {
translated.to_string()
}
}