use std::sync::OnceLock;
pub type TranslatorFn = fn(&str, &[(&str, &str)]) -> Option<String>;
pub(crate) static VALIDATION_TRANSLATOR: OnceLock<TranslatorFn> = OnceLock::new();
pub fn register_validation_translator(f: TranslatorFn) {
let _ = VALIDATION_TRANSLATOR.set(f);
}
pub(crate) fn translate_validation(key: &str, params: &[(&str, &str)]) -> Option<String> {
VALIDATION_TRANSLATOR.get().and_then(|f| f(key, params))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_translate_without_translator() {
let result = translate_validation("validation.required", &[("attribute", "email")]);
let _ = result;
}
#[test]
fn test_translator_fn_signature() {
fn mock_translator(key: &str, _params: &[(&str, &str)]) -> Option<String> {
Some(format!("translated: {key}"))
}
let f: TranslatorFn = mock_translator;
let result = f("validation.required", &[("attribute", "name")]);
assert_eq!(result, Some("translated: validation.required".to_string()));
}
#[test]
fn test_register_double_registration_is_noop() {
fn first(_key: &str, _params: &[(&str, &str)]) -> Option<String> {
Some("first".to_string())
}
fn second(_key: &str, _params: &[(&str, &str)]) -> Option<String> {
Some("second".to_string())
}
register_validation_translator(first);
register_validation_translator(second);
if let Some(f) = VALIDATION_TRANSLATOR.get() {
let result = f("key", &[]);
assert_ne!(result, Some("second".to_string()));
}
}
}