use std::collections::HashMap;
use std::error::Error as StdError;
use crate::core::error::api_error::ApiError;
pub type Locale = String;
pub trait LocalizedError {
fn localized_message(&self, locale: &Locale) -> String;
fn default_message(&self) -> String;
}
#[derive(Debug, Clone, Default)]
pub struct TranslationStore {
translations: HashMap<Locale, HashMap<String, String>>,
}
impl TranslationStore {
pub fn new() -> Self {
Self {
translations: HashMap::new(),
}
}
pub fn add_translation(&mut self, locale: Locale, key: String, translation: String) {
self.translations
.entry(locale)
.or_default()
.insert(key, translation);
}
pub fn get(&self, locale: &Locale, key: &str) -> Option<&String> {
self.translations
.get(locale)
.and_then(|translations| translations.get(key))
}
pub fn load_from_json(&mut self, json_path: &str) -> Result<(), Box<dyn StdError>> {
let content = std::fs::read_to_string(json_path)?;
let json_value: serde_json::Value = serde_json::from_str(&content)?;
if let Some(obj) = json_value.as_object() {
for (locale, translations) in obj {
if let Some(trans_obj) = translations.as_object() {
for (key, value) in trans_obj {
if let Some(value_str) = value.as_str() {
self.add_translation(
locale.clone(),
key.clone(),
value_str.to_string(),
);
}
}
}
}
}
Ok(())
}
}
impl LocalizedError for ApiError {
fn localized_message(&self, locale: &Locale) -> String {
match locale.as_str() {
"zh" | "zh-CN" | "zh-Hans" => match self {
ApiError::NotFound { resource, .. } => {
format!("资源未找到:{}", resource)
}
ApiError::InvalidInput { message, .. } => {
format!("无效输入:{}", message)
}
ApiError::AuthenticationFailed { reason } => {
format!("认证失败:{}", reason)
}
ApiError::AccessDenied { permission, .. } => {
format!("访问被拒绝:{}", permission)
}
ApiError::RateLimitExceeded {
limit,
window_seconds,
} => {
format!("请求频率超限:{} 次 / {} 秒", limit, window_seconds)
}
ApiError::Internal { message, .. } => {
format!("内部错误:{}", message)
}
ApiError::ServiceUnavailable { service, .. } => {
format!("服务不可用:{}", service)
}
ApiError::ValidationError { field, constraint } => {
format!("验证失败:{} - {}", field, constraint)
}
},
"fr" | "fr-FR" => match self {
ApiError::NotFound { resource, .. } => {
format!("Ressource introuvable: {}", resource)
}
ApiError::InvalidInput { message, .. } => {
format!("Entrée invalide: {}", message)
}
ApiError::AuthenticationFailed { reason } => {
format!("Échec de l'authentification: {}", reason)
}
ApiError::AccessDenied { permission, .. } => {
format!("Accès refusé: {}", permission)
}
ApiError::RateLimitExceeded {
limit,
window_seconds,
} => {
format!(
"Limite de débit dépassée: {} requêtes / {} secondes",
limit, window_seconds
)
}
ApiError::Internal { message, .. } => {
format!("Erreur interne: {}", message)
}
ApiError::ServiceUnavailable { service, .. } => {
format!("Service indisponible: {}", service)
}
ApiError::ValidationError { field, constraint } => {
format!("Erreur de validation: {} - {}", field, constraint)
}
},
"es" | "es-ES" => match self {
ApiError::NotFound { resource, .. } => {
format!("Recurso no encontrado: {}", resource)
}
ApiError::InvalidInput { message, .. } => {
format!("Entrada inválida: {}", message)
}
ApiError::AuthenticationFailed { reason } => {
format!("Autenticación fallida: {}", reason)
}
ApiError::AccessDenied { permission, .. } => {
format!("Acceso denegado: {}", permission)
}
ApiError::RateLimitExceeded {
limit,
window_seconds,
} => {
format!(
"Límite de tasa excedido: {} solicitudes / {} segundos",
limit, window_seconds
)
}
ApiError::Internal { message, .. } => {
format!("Error interno: {}", message)
}
ApiError::ServiceUnavailable { service, .. } => {
format!("Servicio no disponible: {}", service)
}
ApiError::ValidationError { field, constraint } => {
format!("Error de validación: {} - {}", field, constraint)
}
},
_ => self.default_message(),
}
}
fn default_message(&self) -> String {
self.to_string()
}
}