use std::collections::HashMap;
use std::sync::OnceLock;
static I18N_INSTANCE: OnceLock<I18n> = OnceLock::new();
#[derive(Debug)]
pub struct I18n {
current_language: String,
translations: HashMap<&'static str, HashMap<&'static str, &'static str>>,
}
impl I18n {
pub fn new() -> Self {
Self {
current_language: String::new(),
translations: HashMap::new(),
}
}
pub fn set_language(&mut self, lang: &'static str) {
self.current_language = lang.to_string();
}
pub fn translate(&self, key: &'static str) -> &'static str {
if let Some(lang_map) = self.translations.get(key) {
if let Some(text) = lang_map.get(self.current_language.as_str()) {
return text;
}
}
key
}
pub fn add_translation(
&mut self,
key: &'static str,
language: &'static str,
translation: &'static str,
) {
self.translations
.entry(key)
.or_insert_with(HashMap::new)
.insert(language, translation);
}
}
pub fn init_i18n() {
let mut i18n = I18n::new();
i18n.set_language("zh");
i18n.add_translation("runtime_init", "zh", "运行时初始化");
i18n.add_translation("runtime_init", "en", "Runtime initialized");
i18n.add_translation("security_check", "zh", "安全检查");
i18n.add_translation("security_check", "en", "Security check");
i18n.add_translation("lua_error", "zh", "Lua 错误");
i18n.add_translation("lua_error", "en", "Lua error");
i18n.add_translation("config_load", "zh", "配置加载");
i18n.add_translation("config_load", "en", "Configuration loaded");
i18n.add_translation("task_complete", "zh", "任务完成");
i18n.add_translation("task_complete", "en", "Task completed");
i18n.add_translation("permission_denied", "zh", "权限拒绝");
i18n.add_translation("permission_denied", "en", "Permission denied");
i18n.add_translation("bytecode_verify", "zh", "字节码验证");
i18n.add_translation("bytecode_verify", "en", "Bytecode verification");
i18n.add_translation("env_modify_blocked", "zh", "环境修改被阻止");
i18n.add_translation("env_modify_blocked", "en", "Environment modification blocked");
i18n.add_translation("external_call_hook", "zh", "外部调用钩子");
i18n.add_translation("external_call_hook", "en", "External call hook");
i18n.add_translation("log_rate_limit", "zh", "日志速率限制");
i18n.add_translation("log_rate_limit", "en", "Log rate limit");
i18n.add_translation("promise_resolved", "zh", "Promise 已解析");
i18n.add_translation("promise_resolved", "en", "Promise resolved");
i18n.add_translation("promise_rejected", "zh", "Promise 已拒绝");
i18n.add_translation("promise_rejected", "en", "Promise rejected");
i18n.add_translation("module_loaded", "zh", "模块已加载");
i18n.add_translation("module_loaded", "en", "Module loaded");
I18N_INSTANCE.set(i18n).expect("Failed to initialize i18n");
}
pub fn t(key: &'static str) -> &'static str {
I18N_INSTANCE
.get()
.map(|i| i.translate(key))
.unwrap_or(key)
}
pub fn set_lang(lang: &'static str) {
log::info!("Language setting: {}", lang);
}
#[macro_export]
macro_rules! log_i18n {
($level:expr, $key:expr) => {
log::log!($level, "{}", $crate::i10n::t($key))
};
($level:expr, $key:expr, $($arg:tt)*) => {
log::log!($level, "{} {}", $crate::i10n::t($key), format!($($arg)*))
};
}
#[macro_export]
macro_rules! info_i18n {
($key:expr) => {
log::info!("{}", $crate::i10n::t($key))
};
($key:expr, $($arg:tt)*) => {
log::info!("{} {}", $crate::i10n::t($key), format!($($arg)*))
};
}
#[macro_export]
macro_rules! error_i18n {
($key:expr) => {
log::error!("{}", $crate::i10n::t($key))
};
($key:expr, $($arg:tt)*) => {
log::error!("{} {}", $crate::i10n::t($key), format!($($arg)*))
};
}
#[macro_export]
macro_rules! warn_i18n {
($key:expr) => {
log::warn!("{}", $crate::i10n::t($key))
};
($key:expr, $($arg:tt)*) => {
log::warn!("{} {}", $crate::i10n::t($key), format!($($arg)*))
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_translation() {
init_i18n();
assert_eq!(t("runtime_init"), "运行时初始化");
assert_eq!(t("security_check"), "安全检查");
assert_eq!(t("nonexistent_key"), "nonexistent_key");
}
}