use std::sync::LazyLock;
use i18n_embed::LanguageLoader;
use i18n_embed::fluent::{FluentLanguageLoader, fluent_language_loader};
use i18n_embed::unic_langid::LanguageIdentifier;
#[allow(
clippy::same_name_method,
reason = "RustEmbed derives inherent `get`/`iter` next to its trait methods, as sibling impls"
)]
mod embed {
#[derive(rust_embed::RustEmbed)]
#[folder = "i18n"]
pub struct Localizations;
}
use embed::Localizations;
pub static LOADER: LazyLock<FluentLanguageLoader> = LazyLock::new(|| {
fn requested_language() -> Option<LanguageIdentifier> {
let locale = ["LC_ALL", "LC_MESSAGES", "LANG"]
.into_iter()
.find_map(|var| atuin_common::env::var(var).ok().filter(|locale| !locale.is_empty()))?;
language_from_locale(&locale)
}
fn language_from_locale(locale: &str) -> Option<LanguageIdentifier> {
let name = locale.split(['.', '@']).next()?;
if matches!(name, "C" | "POSIX") {
return None;
}
name.replace('_', "-").parse().ok()
}
let loader: FluentLanguageLoader = fluent_language_loader!();
let requested: Vec<_> = requested_language().into_iter().collect();
if let Err(err) = i18n_embed::select(&loader, &Localizations, &requested) {
tracing::warn!(?err, "failed to load translations; falling back to en-US");
loader
.load_fallback_language(&Localizations)
.expect("fl! checks the en-US catalogue at compile time");
}
loader.set_use_isolating(false);
loader
});
macro_rules! fl {
($message_id:literal) => {
i18n_embed_fl::fl!($crate::i18n::LOADER, $message_id)
};
($message_id:literal, $attribute_id:literal) => {
i18n_embed_fl::fl!($crate::i18n::LOADER, $message_id, $attribute_id)
};
($message_id:literal, $attribute_id:literal, $($name:ident = $value:expr),+ $(,)?) => {
i18n_embed_fl::fl!($crate::i18n::LOADER, $message_id, $attribute_id, $($name = ($value)),+)
};
($message_id:literal, $($name:ident = $value:expr),* $(,)?) => {
i18n_embed_fl::fl!($crate::i18n::LOADER, $message_id, $($name = ($value)),*)
};
}
macro_rules! writet {
($dst:expr, $($args:tt)+) => {
::std::write!($dst, "{}", $crate::i18n::fl!($($args)+))
};
}
pub(crate) use fl;
pub(crate) use writet;