use crate::config::Config;
pub const SUPPORTED_LANGS: &[(&str, &str)] = &[
("en", "English"),
("ko", "한국어"),
("pt-BR", "Português (Brasil)"),
("ja", "日本語"),
];
pub fn init() {
let locale = detect_locale();
rust_i18n::set_locale(&locale);
}
pub fn detect_locale() -> String {
if let Ok(lang) = std::env::var("SCOOP_LANG") {
let normalized = normalize(&lang);
if is_supported(&normalized) {
return normalized;
}
let lang_code = normalized.split('-').next().unwrap_or("en");
if is_supported(lang_code) {
return lang_code.to_string();
}
}
if let Ok(config) = Config::load() {
if let Some(lang) = config.lang {
if is_supported(&lang) {
return lang;
}
}
}
if let Some(locale) = sys_locale::get_locale() {
let normalized = normalize(&locale);
let lang_code = normalized.split('-').next().unwrap_or("en");
if is_supported(lang_code) {
return lang_code.to_string();
}
}
"en".to_string()
}
pub fn current() -> String {
rust_i18n::locale().to_string()
}
pub fn is_supported(lang: &str) -> bool {
SUPPORTED_LANGS.iter().any(|(code, _)| *code == lang)
}
pub fn language_name(code: &str) -> Option<&'static str> {
SUPPORTED_LANGS
.iter()
.find(|(c, _)| *c == code)
.map(|(_, name)| *name)
}
fn normalize(locale: &str) -> String {
locale
.split('.')
.next()
.unwrap_or("en")
.replace('_', "-")
.to_lowercase()
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
#[test]
fn test_normalize() {
assert_eq!(normalize("ko_KR.UTF-8"), "ko-kr");
assert_eq!(normalize("en_US"), "en-us");
assert_eq!(normalize("ja"), "ja");
assert_eq!(normalize("zh_CN.UTF-8"), "zh-cn");
}
#[test]
fn test_is_supported() {
assert!(is_supported("en"));
assert!(is_supported("ko"));
assert!(is_supported("ja"));
assert!(is_supported("pt-BR"));
assert!(!is_supported("fr"));
assert!(!is_supported("zh-CN")); }
#[test]
fn test_language_name() {
assert_eq!(language_name("en"), Some("English"));
assert_eq!(language_name("ko"), Some("한국어"));
assert_eq!(language_name("ja"), Some("日本語"));
assert_eq!(language_name("pt-BR"), Some("Português (Brasil)"));
assert_eq!(language_name("fr"), None);
}
#[test]
#[serial]
fn test_detect_with_env() {
let original = std::env::var("SCOOP_LANG").ok();
unsafe {
std::env::set_var("SCOOP_LANG", "ko");
assert_eq!(detect_locale(), "ko");
std::env::set_var("SCOOP_LANG", "en");
assert_eq!(detect_locale(), "en");
match original {
Some(val) => std::env::set_var("SCOOP_LANG", val),
None => std::env::remove_var("SCOOP_LANG"),
}
}
}
#[test]
#[serial]
fn test_detect_with_unsupported_env() {
let original = std::env::var("SCOOP_LANG").ok();
unsafe {
std::env::set_var("SCOOP_LANG", "fr");
let locale = detect_locale();
assert!(is_supported(&locale) || locale == "en");
match original {
Some(val) => std::env::set_var("SCOOP_LANG", val),
None => std::env::remove_var("SCOOP_LANG"),
}
}
}
}