use crate::{global, trace};
use super::languages::LANGUAGES;
use super::{langid, LanguageIdentifier};
use std::sync::LazyLock;
static CONFIG_LANGID: LazyLock<Option<&'static LanguageIdentifier>> = LazyLock::new(|| {
Locale::resolve(global::SETTINGS.app.language.as_deref().unwrap_or("")).as_option()
});
static FALLBACK_LANGID: LazyLock<LanguageIdentifier> = LazyLock::new(|| langid!("en-US"));
pub trait LangId {
fn langid(&self) -> &'static LanguageIdentifier;
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Locale {
Unspecified,
Resolved(&'static LanguageIdentifier),
Unsupported(String),
}
impl Default for Locale {
fn default() -> Self {
Locale::Resolved(Locale::default_langid())
}
}
impl Locale {
pub fn resolve(language: impl AsRef<str>) -> Self {
let language = language.as_ref().trim();
if language.is_empty() {
return Self::Unspecified;
}
let lang = language.to_ascii_lowercase();
if let Some(langid) = LANGUAGES.get(lang.as_str()).map(|(langid, _)| langid) {
return Self::Resolved(langid);
}
if let Some((base_lang, _)) = lang.split_once('-') {
if let Some(langid) = LANGUAGES.get(base_lang).map(|(langid, _)| langid) {
return Self::Resolved(langid);
}
}
Self::Unsupported(language.to_string())
}
#[inline]
pub fn as_option(&self) -> Option<&'static LanguageIdentifier> {
match self {
Locale::Resolved(l) => Some(l),
_ => None,
}
}
pub(crate) fn init() {
match global::SETTINGS.app.language.as_deref() {
Some(raw) if !raw.trim().is_empty() => {
if let Some(langid) = *CONFIG_LANGID {
trace::debug!("Default language \"{langid}\" (from config: \"{raw}\")");
} else {
trace::debug!(
"Default language \"{}\" (fallback, invalid config: \"{raw}\")",
*FALLBACK_LANGID
);
}
}
_ => trace::debug!(
"Default language \"{}\" (fallback, no config)",
*FALLBACK_LANGID
),
}
}
pub fn configured_langid() -> Option<&'static LanguageIdentifier> {
*CONFIG_LANGID
}
pub fn fallback_langid() -> &'static LanguageIdentifier {
&FALLBACK_LANGID
}
pub fn default_langid() -> &'static LanguageIdentifier {
(*CONFIG_LANGID).unwrap_or(&FALLBACK_LANGID)
}
}
impl LangId for Locale {
#[inline]
fn langid(&self) -> &'static LanguageIdentifier {
match self {
Locale::Resolved(l) => l,
_ => Locale::default_langid(),
}
}
}