use wxdragon::{translations::Translations, widgets::choice::Choice};
use crate::{LanguageInfo, LanguageManager};
pub struct WxTranslationManager {
domain: String,
current_language: String,
available_languages: Vec<LanguageInfo>,
initialized: bool,
}
impl WxTranslationManager {
#[must_use]
pub fn new(domain: &str) -> Self {
Self {
domain: domain.to_string(),
current_language: "en".to_string(),
available_languages: vec![LanguageInfo { code: "en".to_string(), name: "English".to_string() }],
initialized: false,
}
}
pub fn initialize(&mut self, wxstd_loader: impl wxdragon::translations::TranslationsLoader + 'static) -> bool {
if self.initialized {
return true;
}
let translations = Translations::new();
translations.set_loader(wxstd_loader);
let mgr = LanguageManager::new(&self.domain);
self.available_languages = mgr.available();
let raw_sys_lang = LanguageManager::system_language();
let sys_lang = raw_sys_lang.split('_').next().unwrap_or(&raw_sys_lang).to_string();
self.current_language = if self.is_language_available(&sys_lang) { sys_lang } else { "en".to_string() };
if self.current_language != "en" {
translations.set_language_str(&self.current_language);
}
translations.add_std_catalog();
Translations::set_global(translations);
crate::set_default_domain(&self.domain);
crate::set_locale(&self.current_language);
self.initialized = true;
true
}
pub fn set_language(
&mut self,
language_code: &str,
wxstd_loader: impl wxdragon::translations::TranslationsLoader + 'static,
) -> bool {
if !self.initialized || !self.is_language_available(language_code) {
return false;
}
self.current_language = language_code.to_string();
let translations = Translations::new();
translations.set_loader(wxstd_loader);
translations.set_language_str(language_code);
translations.add_std_catalog();
Translations::set_global(translations);
crate::set_locale(language_code);
true
}
#[must_use]
pub fn current_language(&self) -> String {
self.current_language.clone()
}
#[must_use]
pub fn available_languages(&self) -> Vec<LanguageInfo> {
self.available_languages.clone()
}
#[must_use]
pub fn is_language_available(&self, language_code: &str) -> bool {
self.available_languages.iter().any(|lang| lang.code == language_code)
}
}
pub fn populate_language_choice(combo: &Choice, languages: &[LanguageInfo]) -> Vec<String> {
let mut codes = Vec::with_capacity(languages.len());
for lang in languages {
combo.append(&lang.name);
codes.push(lang.code.clone());
}
codes
}
#[must_use]
pub fn resolve_language_choice(combo: &Choice, codes: &[String]) -> Option<String> {
combo.get_selection().and_then(|index| usize::try_from(index).ok()).and_then(|index| codes.get(index).cloned())
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use wxdragon::translations::TranslationsLoader;
use super::*;
struct NoopLoader;
impl TranslationsLoader for NoopLoader {
fn load_catalog(&self, _domain: &str, _lang: &str) -> Option<Cow<'_, [u8]>> {
None
}
fn available_translations(&self, _domain: &str) -> Vec<String> {
Vec::new()
}
}
#[test]
fn new_manager_has_english_available_by_default() {
let manager = WxTranslationManager::new("test_domain");
assert_eq!(manager.current_language(), "en");
assert!(manager.is_language_available("en"));
assert!(!manager.is_language_available("zz"));
}
#[test]
fn set_language_fails_when_not_initialized() {
let mut manager = WxTranslationManager::new("test_domain");
assert!(!manager.set_language("en", NoopLoader));
assert_eq!(manager.current_language(), "en");
}
#[test]
fn available_languages_returns_clone() {
let manager = WxTranslationManager::new("test_domain");
let mut langs = manager.available_languages();
langs.push(LanguageInfo { code: "xx".to_string(), name: "Fake".to_string() });
assert!(!manager.is_language_available("xx"));
}
}