Files
own_assist/src/i18n/mod.rs
T
milan d9ade649d3
publish release / release (push) Failing after 3m38s
add experimental action
apply formatting
2026-05-08 22:30:11 +02:00

87 lines
2.3 KiB
Rust

use rmcp::serde_json;
use serde::Deserialize;
use std::collections::HashMap;
use std::sync::{LazyLock, OnceLock, RwLock};
#[derive(Debug, Deserialize)]
struct Language {
translations: HashMap<String, String>,
}
static LANGUAGES: OnceLock<HashMap<Locale, Language>> = OnceLock::new();
static LOCALE_SELECTION: LazyLock<RwLock<Locale>> = LazyLock::new(|| RwLock::new(Locale::DE));
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Locale {
DE,
}
#[macro_export]
macro_rules! include_language {
($file:expr) => {
serde_json::from_str::<Language>(include_str!($file)).unwrap()
};
}
fn load_languages() -> &'static HashMap<Locale, Language> {
LANGUAGES
.get_or_init(|| HashMap::from([(Locale::DE, include_language!("translations/de.json"))]))
}
///
/// # Examples
///
/// ```
/// let formatted = format_dynamically("{...} is cool!".to_string(),
/// vec!["Rust".to_string()]);
/// assert_eq!(formatted, "Rust is cool!");
/// ```
fn format_dynamically(mut template: String, arguments: Vec<impl Into<String>>) -> String {
let replaced_str = "{...}";
for arg in arguments {
template = template.replacen(replaced_str, arg.into().as_str(), 1);
}
template
}
pub fn translate(template_name: String, arguments: Vec<impl Into<String>>) -> String {
let locale: Locale = *LOCALE_SELECTION.read().unwrap();
let languages = load_languages();
let translation = languages
.get(&locale)
.unwrap()
.translations
.get(&template_name)
.unwrap();
format_dynamically(translation.clone(), arguments)
}
#[macro_export]
macro_rules! tlt {
($template_name:tt) => {
translate($template_name.to_string(), Vec::<String>::new())
};
($template_name:tt, $($args:tt)*) => {
translate($template_name.to_string(), vec![$($args)*])
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dynamic_formatting() {
let formatted = format_dynamically("{...} is cool!".to_string(), vec!["Rust".to_string()]);
assert_eq!(formatted, "Rust is cool!");
let formatted = format_dynamically(
"{...}, {...} and {...} are three consecutive numbers.".to_string(),
vec!["1".to_string(), "2".to_string(), "3".to_string()],
);
assert_eq!(formatted, "1, 2 and 3 are three consecutive numbers.");
}
}