use std::env;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Language {
Russian,
English,
}
impl Language {
pub fn is_ru(self) -> bool { self == Language::Russian }
}
#[derive(Debug, Clone)]
pub struct Localizer {
pub lang: Language,
}
impl Localizer {
pub fn detect() -> Self {
let lang = detect_locale();
Self { lang }
}
pub fn from_override(s: &str) -> Self {
let s = s.to_lowercase();
let lang = if s == "ru" || s.starts_with("ru_") {
Language::Russian
} else {
Language::English
};
Self { lang }
}
pub fn t<'a>(&self, ru: &'a str, en: &'a str) -> &'a str {
match self.lang {
Language::Russian => ru,
Language::English => en,
}
}
pub fn msg(&self, key: &str) -> String {
messages(self.lang, key)
}
pub fn fmt(&self, ru: &str, en: &str, args: &[(&str, &str)]) -> String {
let template = self.t(ru, en);
let mut result = template.to_string();
for (k, v) in args {
result = result.replace(&format!("{{{k}}}"), v);
}
result
}
}
fn detect_locale() -> Language {
for var in &["LC_ALL", "LC_MESSAGES", "LANG"] {
if let Ok(val) = env::var(var) {
let val = val.to_lowercase();
if val == "ru" || val.starts_with("ru_") {
return Language::Russian;
}
}
}
Language::English
}
fn messages(lang: Language, key: &str) -> String {
match lang {
Language::Russian => ru_messages(key),
Language::English => en_messages(key),
}
}
fn ru_messages(key: &str) -> String {
match key {
"welcome" => "Добро пожаловать в Aurora!".to_string(),
"goodbye" => "До свидания!".to_string(),
"searching" => "Поиск...".to_string(),
"found_files" => "Найдено файлов: {count}".to_string(),
"indexing" => "Индексация...".to_string(),
"index_updated" => "Индекс обновлён: {count} файлов".to_string(),
"converting" => "Конвертация...".to_string(),
"processing" => "Обработка...".to_string(),
"error" => "Ошибка: {msg}".to_string(),
"loading" => "Загрузка...".to_string(),
"done" => "Готово!".to_string(),
"elapsed" => "Прошло: {time}с".to_string(),
"no_results" => "Ничего не найдено".to_string(),
"joke_break" => "А пока — шутка:".to_string(),
"thinking" => "Думаю...".to_string(),
"cancel_hint" => "Нажми Ctrl+C для отмены".to_string(),
"config_loaded" => "Конфиг загружен".to_string(),
"session_resumed" => "Сессия восстановлена".to_string(),
"debug_analyzing" => "Анализирую проблему...".to_string(),
"debug_suggestion" => "Возможное решение: {suggestion}".to_string(),
_ => key.to_string(),
}
}
fn en_messages(key: &str) -> String {
match key {
"welcome" => "Welcome to Aurora!".to_string(),
"goodbye" => "Goodbye!".to_string(),
"searching" => "Searching...".to_string(),
"found_files" => "Files found: {count}".to_string(),
"indexing" => "Indexing...".to_string(),
"index_updated" => "Index updated: {count} files".to_string(),
"converting" => "Converting...".to_string(),
"processing" => "Processing...".to_string(),
"error" => "Error: {msg}".to_string(),
"loading" => "Loading...".to_string(),
"done" => "Done!".to_string(),
"elapsed" => "Elapsed: {time}s".to_string(),
"no_results" => "No results found".to_string(),
"joke_break" => "Meanwhile, a joke:".to_string(),
"thinking" => "Thinking...".to_string(),
"cancel_hint" => "Press Ctrl+C to cancel".to_string(),
"config_loaded" => "Config loaded".to_string(),
"session_resumed" => "Session resumed".to_string(),
"debug_analyzing" => "Analyzing the issue...".to_string(),
"debug_suggestion" => "Possible fix: {suggestion}".to_string(),
_ => key.to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detect_ru() {
let loc = Localizer::from_override("ru_RU.UTF-8");
assert_eq!(loc.lang, Language::Russian);
}
#[test]
fn test_detect_en() {
let loc = Localizer::from_override("en_US.UTF-8");
assert_eq!(loc.lang, Language::English);
}
#[test]
fn test_translate() {
let ru = Localizer::from_override("ru_RU");
let en = Localizer::from_override("en_US");
assert_eq!(ru.t("Search", "Поиск"), "Поиск");
assert_eq!(en.t("Search", "Поиск"), "Search");
}
}