use std::sync::OnceLock;
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum CliLang {
En,
Zh,
}
impl CliLang {
pub(crate) fn detect() -> CliLang {
static DETECTED: OnceLock<CliLang> = OnceLock::new();
*DETECTED.get_or_init(|| {
if let Ok(v) = std::env::var("CURE_LANG") {
if let Some(p) = primary_tag(&v) {
if p.starts_with("zh") {
return CliLang::Zh;
}
if p.starts_with("en") {
return CliLang::En;
}
}
}
for var in ["LC_ALL", "LC_MESSAGES", "LANG", "LANGUAGE"] {
let Ok(v) = std::env::var(var) else { continue };
let first = v.split(':').find(|s| !s.is_empty()).unwrap_or("");
if let Some(p) = primary_tag(first) {
return if p.starts_with("zh") { CliLang::Zh } else { CliLang::En };
}
}
#[cfg(windows)]
{
if let Some(l) = windows_ui_lang() {
return l;
}
}
CliLang::En
})
}
}
#[cfg(windows)]
fn windows_ui_lang() -> Option<CliLang> {
#[link(name = "kernel32")]
extern "system" {
fn GetUserDefaultUILanguage() -> u16;
}
let langid = unsafe { GetUserDefaultUILanguage() };
(langid & 0x3ff == 0x04).then_some(CliLang::Zh)
}
fn primary_tag(tag: &str) -> Option<String> {
let base = tag.split('.').next().unwrap_or("");
let base = base.split('@').next().unwrap_or("");
let p = base.split(&['-', '_'][..]).next().unwrap_or("");
if p.is_empty() || p == "C" || p == "POSIX" {
return None;
}
Some(p.to_ascii_lowercase())
}