//! i18n utilities using trait-based dependency injection use crate::*; use std::collections::HashMap; /// Simple localization provider using HashMap storage /// /// This provides basic localization functionality. Implementations can /// extend this or provide their own LocalizationProvider implementation. pub struct SimpleLocalizationProvider { /// Translations storage: language -> key -> value pub translations: HashMap>, /// Default language pub default_language: String, } impl SimpleLocalizationProvider { /// Create new localization provider pub fn new(default_language: String) -> Self { Self { translations: HashMap::new(), default_language, } } /// Add translations for a language pub fn add_translations(&mut self, language: String, translations: HashMap) { self.translations.insert(language, translations); } /// Add single translation pub fn add_translation(&mut self, language: String, key: String, value: String) { self.translations .entry(language) .or_default() .insert(key, value); } /// Simple string interpolation fn interpolate(&self, template: &str, args: &HashMap) -> String { let mut result = template.to_string(); for (key, value) in args { result = result.replace(&format!("{{{}}}", key), value); } result } } impl LocalizationProvider for SimpleLocalizationProvider { fn get_localized_string( &self, key: &str, language: &str, args: &HashMap, ) -> ComponentResult { let lang_translations = self.translations.get(language) .ok_or_else(|| ComponentError::ContentError(format!("Language not found: {}", language)))?; let template = lang_translations.get(key) .ok_or_else(|| ComponentError::ContentError(format!("Translation key not found: {}", key)))?; Ok(self.interpolate(template, args)) } fn available_languages(&self) -> Vec { self.translations.keys().cloned().collect() } fn default_language(&self) -> String { self.default_language.clone() } }