use crate::i18n::loader::LOCALES; use fluent_templates::{Loader, fluent_bundle::FluentValue}; use std::{ borrow::Cow, collections::HashMap, str::FromStr, sync::{OnceLock, RwLock}, }; use unic_langid::LanguageIdentifier; static SYSTEM_LOCALE: OnceLock = OnceLock::new(); static TRANSLATION_CACHE: OnceLock>> = OnceLock::new(); const CACHE_INITIAL_SIZE: usize = 30; const CACHE_SIZE_LIMIT: usize = 1000; fn get_system_locale() -> &'static LanguageIdentifier { SYSTEM_LOCALE.get_or_init(|| { let sys_lang = sys_locale::get_locale().unwrap_or_else(|| String::from("pt-BR")); LanguageIdentifier::from_str(&sys_lang).expect("Invalid language") }) } fn get_translation_cache() -> &'static RwLock> { TRANSLATION_CACHE.get_or_init(|| RwLock::new(HashMap::with_capacity(CACHE_INITIAL_SIZE))) } pub fn t(key: &str) -> String { let cache = get_translation_cache(); { let cache_read = cache.read().unwrap(); if let Some(cached) = cache_read.get(key) { return cached.clone(); } } let result = LOCALES.lookup(&*get_system_locale(), key); let mut cache_write = cache.write().unwrap(); if cache_write.len() >= CACHE_SIZE_LIMIT { cache_write.clear(); } cache_write.insert(key.to_string(), result.clone()); result } pub fn t_with_args(key: &str, args: &HashMap<&'static str, String>) -> String { let mut map = HashMap::new(); for (key, value) in args { map.insert(Cow::Borrowed(*key), FluentValue::from(value)); } LOCALES.lookup_with_args(&get_system_locale(), key, &map) }