use std::sync::OnceLock;
use crate::i18n::Language;
static GLOBAL_LANGUAGE: OnceLock<Language> = OnceLock::new();
pub fn resolve_language(force_lang: Option<&str>) -> Language {
if let Some(codigo) = force_lang {
if let Some(language) = code_to_language(codigo) {
return language;
}
}
if let Ok(env_lang) = std::env::var("SSH_CLI_LANG") {
if let Some(language) = code_to_language(&env_lang) {
return language;
}
}
if let Some(locale) = sys_locale::get_locale() {
if let Some(language) = code_to_language(&locale) {
return language;
}
}
Language::English
}
pub fn set_language(language: Language) {
let _ = GLOBAL_LANGUAGE.set(language);
}
pub fn current_language() -> Language {
GLOBAL_LANGUAGE.get().copied().unwrap_or(Language::English)
}
fn code_to_language(codigo: &str) -> Option<Language> {
let normalizado = codigo.to_lowercase();
match normalizado.as_str() {
"pt" | "pt-br" | "pt_br" => Some(Language::Portuguese),
"en" | "en-us" | "en_us" => Some(Language::English),
outro => {
if outro.starts_with("pt") {
Some(Language::Portuguese)
} else if outro.starts_with("en") {
Some(Language::English)
} else {
None
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn code_pt_returns_portuguese() {
assert_eq!(code_to_language("pt"), Some(Language::Portuguese));
}
#[test]
fn code_pt_br_returns_portuguese() {
assert_eq!(code_to_language("pt-BR"), Some(Language::Portuguese));
}
#[test]
fn code_pt_br_underscore_returns_portuguese() {
assert_eq!(code_to_language("pt_BR"), Some(Language::Portuguese));
}
#[test]
fn code_en_returns_english() {
assert_eq!(code_to_language("en"), Some(Language::English));
}
#[test]
fn code_en_us_returns_english() {
assert_eq!(code_to_language("en-US"), Some(Language::English));
}
#[test]
fn code_en_gb_returns_english_by_prefix() {
assert_eq!(code_to_language("en-GB"), Some(Language::English));
}
#[test]
fn unknown_code_returns_none() {
assert_eq!(code_to_language("fr-FR"), None);
}
#[test]
fn empty_code_returns_none() {
assert_eq!(code_to_language(""), None);
}
#[test]
fn uppercase_code_normalized() {
assert_eq!(code_to_language("PT"), Some(Language::Portuguese));
assert_eq!(code_to_language("EN"), Some(Language::English));
}
#[test]
fn resolve_force_pt_returns_portuguese() {
let result = resolve_language(Some("pt-BR"));
assert_eq!(result, Language::Portuguese);
}
#[test]
fn resolve_force_en_returns_english() {
let result = resolve_language(Some("en-US"));
assert_eq!(result, Language::English);
}
#[test]
fn resolve_force_invalid_uses_next_layers() {
std::env::remove_var("SSH_CLI_LANG");
let result = resolve_language(Some("xx-YY"));
assert!(
result == Language::English || result == Language::Portuguese,
"resolve_language must return a valid language even with invalid code"
);
}
#[test]
fn resolve_without_force_returns_valid_language() {
std::env::remove_var("SSH_CLI_LANG");
let result = resolve_language(None);
assert!(
result == Language::English || result == Language::Portuguese,
"resolve_language must return a valid language"
);
}
#[test]
fn current_language_fallback_english_before_set() {
let result = current_language();
assert!(
result == Language::English || result == Language::Portuguese,
"current_language must return a valid language"
);
}
}