diff --git a/.gitignore b/.gitignore index ea8c4bf..b46cc5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +perf.data diff --git a/Cargo.toml b/Cargo.toml index a673250..9dd7cad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,6 @@ ratatui = "0.30.0" crossterm = "0.29.0" chrono = "0.4.42" rayon = "1.11.0" + +[profile.release] +debug = true diff --git a/src/i18n/translate.rs b/src/i18n/translate.rs index 2cae04a..a526444 100644 --- a/src/i18n/translate.rs +++ b/src/i18n/translate.rs @@ -1,17 +1,49 @@ use crate::i18n::loader::LOCALES; use fluent_templates::{Loader, fluent_bundle::FluentValue}; -use once_cell::sync::Lazy; -use std::borrow::Cow; -use std::{collections::HashMap, str::FromStr}; +use std::{ + borrow::Cow, + collections::HashMap, + str::FromStr, + sync::{OnceLock, RwLock}, +}; use unic_langid::LanguageIdentifier; -static SYSTEM_LOCALE: Lazy = Lazy::new(|| { - let sys_lang = sys_locale::get_locale().unwrap_or_else(|| String::from("pt-BR")); - LanguageIdentifier::from_str(&sys_lang).expect("Invalid language") -}); +static SYSTEM_LOCALE: OnceLock = OnceLock::new(); +static TRANSLATION_CACHE: OnceLock>> = OnceLock::new(); +const CACHE_INITIAL_SIZE: usize = 100; +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 { - LOCALES.lookup(&*SYSTEM_LOCALE, key) + 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 { @@ -20,8 +52,8 @@ pub fn t_with_args(key: &str, args: &HashMap<&'static str, String>) -> String { args_map = { for (key, value) in args { map.insert(Cow::Borrowed(*key), FluentValue::from(value.clone())); - }; + } &map }; - LOCALES.lookup_with_args(&*&SYSTEM_LOCALE, key, args_map) + LOCALES.lookup_with_args(&get_system_locale(), key, args_map) }