Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Auto-detects your system language. Supported:
- 🇻🇳 Vietnamese
- 🇪🇸 Spanish
- 🇺🇦 Ukrainian
- 🇨🇳 Simplified Chinese

*(Falls back to English if system language is not supported)*

Expand Down
77 changes: 66 additions & 11 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,72 @@ pub fn greet(name: &str) -> String {
#[tauri::command]
pub fn get_system_language() -> String {
let locale = sys_locale::get_locale().unwrap_or_else(|| "en".to_string());
let lang = locale.split('-').next().unwrap_or("en").to_lowercase();
match lang.as_str() {
"pl" => "pl".to_string(),
"it" => "it".to_string(),
"de" => "de".to_string(),
"fr" => "fr".to_string(),
"ru" => "ru".to_string(),
"ja" => "ja".to_string(),
"es" => "es".to_string(),
"uk" => "uk".to_string(),
_ => "en".to_string(),
map_system_locale(&locale).to_string()
}

fn map_system_locale(locale: &str) -> &'static str {
let normalized = locale.replace('_', "-").to_lowercase();
let mut parts = normalized.split('-');
let language = parts.next().unwrap_or("en");

if language == "zh" {
let variants: Vec<&str> = parts.collect();

if variants.contains(&"hant") {
return "en";
}
if variants.contains(&"hans") {
return "zh-CN";
}
if variants
.iter()
.any(|part| matches!(*part, "tw" | "hk" | "mo"))
{
return "en";
}
if variants.iter().any(|part| matches!(*part, "cn" | "sg")) {
return "zh-CN";
}

return "en";
}

match language {
"pl" => "pl",
"it" => "it",
"de" => "de",
"fr" => "fr",
"ru" => "ru",
"ja" => "ja",
"es" => "es",
"uk" => "uk",
_ => "en",
}
}

#[cfg(test)]
mod locale_tests {
use super::map_system_locale;

#[test]
fn maps_simplified_chinese_variants_to_zh_cn() {
for locale in ["zh-CN", "zh-SG", "zh-Hans", "zh-Hans-CN", "zh_CN"] {
assert_eq!(map_system_locale(locale), "zh-CN", "locale: {locale}");
}
}

#[test]
fn falls_back_for_traditional_and_ambiguous_chinese_locales() {
for locale in ["zh-TW", "zh-HK", "zh-MO", "zh-Hant", "zh-Hant-TW", "zh"] {
assert_eq!(map_system_locale(locale), "en", "locale: {locale}");
}
}

#[test]
fn preserves_existing_supported_language_mapping() {
assert_eq!(map_system_locale("pl-PL"), "pl");
assert_eq!(map_system_locale("ja_JP"), "ja");
assert_eq!(map_system_locale("en-US"), "en");
}
}

Expand Down
270 changes: 142 additions & 128 deletions src-tauri/src/i18n.rs
Original file line number Diff line number Diff line change
@@ -1,128 +1,142 @@
use std::collections::HashMap;

pub struct TrayI18n {
strings: HashMap<&'static str, &'static str>,
}

impl TrayI18n {
pub fn new(lang: &str) -> Self {
let mut strings = HashMap::new();
match lang {
"pl" => {
strings.insert("quit", "Zamknij");
strings.insert("settings", "Ustawienia");
strings.insert("clean_now", "Uporządkuj teraz");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} plik czeka");
strings.insert("tooltip_many_pending", "Mouzi – {} pliki czekają");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Ustawienia Mouzi");
strings.insert("organized", "Uporządkowano {} plik(i)");
}
"it" => {
strings.insert("quit", "Esci");
strings.insert("settings", "Impostazioni");
strings.insert("clean_now", "Organizza ora");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} file in attesa");
strings.insert("tooltip_many_pending", "Mouzi – {} file in attesa");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Impostazioni Mouzi");
strings.insert("organized", "Organizzati {} file");
}
"de" => {
strings.insert("quit", "Beenden");
strings.insert("settings", "Einstellungen");
strings.insert("clean_now", "Jetzt organisieren");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} Datei wartend");
strings.insert("tooltip_many_pending", "Mouzi – {} Dateien wartend");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Mouzi Einstellungen");
strings.insert("organized", "{} Datei(en) organisiert");
}
"fr" => {
strings.insert("quit", "Quitter");
strings.insert("settings", "Paramètres");
strings.insert("clean_now", "Organiser maintenant");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} fichier en attente");
strings.insert("tooltip_many_pending", "Mouzi – {} fichiers en attente");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Paramètres Mouzi");
strings.insert("organized", "{} fichier(s) organisé(s)");
}
"ru" => {
strings.insert("quit", "Выход");
strings.insert("settings", "Настройки");
strings.insert("clean_now", "Организовать сейчас");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} файл ожидает");
strings.insert("tooltip_many_pending", "Mouzi – {} файла ожидают");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Настройки Mouzi");
strings.insert("organized", "Организовано {} файл(ов)");
}
"ja" => {
strings.insert("quit", "終了");
strings.insert("settings", "設定");
strings.insert("clean_now", "今すぐ整理");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} 個のファイルが待機中");
strings.insert("tooltip_many_pending", "Mouzi – {} 個のファイルが待機中");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Mouziの設定");
strings.insert("organized", "{}個のファイルを整理しました");
}
"vi" => {
strings.insert("quit", "Thoát");
strings.insert("settings", "Cài đặt");
strings.insert("clean_now", "Sắp xếp ngay");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} tệp đang chờ");
strings.insert("tooltip_many_pending", "Mouzi – {} tệp đang chờ");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Cài đặt Mouzi");
strings.insert("organized", "Đã sắp xếp {} tệp");
}
"es" => {
strings.insert("quit", "Salir");
strings.insert("settings", "Configuración");
strings.insert("clean_now", "Organizar ahora");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} archivo esperando");
strings.insert("tooltip_many_pending", "Mouzi – {} archivos esperando");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Configuración de Mouzi");
strings.insert("organized", "{} archivo(s) organizado(s)");
}
"uk" => {
strings.insert("quit", "Вийти");
strings.insert("settings", "Налаштування");
strings.insert("clean_now", "Упорядкувати зараз");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi — очікує {} файл");
strings.insert("tooltip_many_pending", "Mouzi — очікує файлів: {}");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Налаштування Mouzi");
strings.insert("organized", "Впорядковано файлів: {}");
}
_ => {
strings.insert("quit", "Quit");
strings.insert("settings", "Settings");
strings.insert("clean_now", "Organize Now");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} file waiting");
strings.insert("tooltip_many_pending", "Mouzi – {} files waiting");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Mouzi Settings");
strings.insert("organized", "Organized {} file(s)");
}
}
Self { strings }
}

pub fn get<'a>(&self, key: &'a str) -> &'a str {
self.strings.get(key).copied().unwrap_or(key)
}
}
use std::collections::HashMap;

pub struct TrayI18n {
strings: HashMap<&'static str, &'static str>,
}

impl TrayI18n {
pub fn new(lang: &str) -> Self {
let mut strings = HashMap::new();
match lang {
"pl" => {
strings.insert("quit", "Zamknij");
strings.insert("settings", "Ustawienia");
strings.insert("clean_now", "Uporządkuj teraz");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} plik czeka");
strings.insert("tooltip_many_pending", "Mouzi – {} pliki czekają");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Ustawienia Mouzi");
strings.insert("organized", "Uporządkowano {} plik(i)");
}
"it" => {
strings.insert("quit", "Esci");
strings.insert("settings", "Impostazioni");
strings.insert("clean_now", "Organizza ora");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} file in attesa");
strings.insert("tooltip_many_pending", "Mouzi – {} file in attesa");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Impostazioni Mouzi");
strings.insert("organized", "Organizzati {} file");
}
"de" => {
strings.insert("quit", "Beenden");
strings.insert("settings", "Einstellungen");
strings.insert("clean_now", "Jetzt organisieren");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} Datei wartend");
strings.insert("tooltip_many_pending", "Mouzi – {} Dateien wartend");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Mouzi Einstellungen");
strings.insert("organized", "{} Datei(en) organisiert");
}
"fr" => {
strings.insert("quit", "Quitter");
strings.insert("settings", "Paramètres");
strings.insert("clean_now", "Organiser maintenant");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} fichier en attente");
strings.insert("tooltip_many_pending", "Mouzi – {} fichiers en attente");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Paramètres Mouzi");
strings.insert("organized", "{} fichier(s) organisé(s)");
}
"ru" => {
strings.insert("quit", "Выход");
strings.insert("settings", "Настройки");
strings.insert("clean_now", "Организовать сейчас");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} файл ожидает");
strings.insert("tooltip_many_pending", "Mouzi – {} файла ожидают");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Настройки Mouzi");
strings.insert("organized", "Организовано {} файл(ов)");
}
"ja" => {
strings.insert("quit", "終了");
strings.insert("settings", "設定");
strings.insert("clean_now", "今すぐ整理");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} 個のファイルが待機中");
strings.insert("tooltip_many_pending", "Mouzi – {} 個のファイルが待機中");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Mouziの設定");
strings.insert("organized", "{}個のファイルを整理しました");
}
"vi" => {
strings.insert("quit", "Thoát");
strings.insert("settings", "Cài đặt");
strings.insert("clean_now", "Sắp xếp ngay");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} tệp đang chờ");
strings.insert("tooltip_many_pending", "Mouzi – {} tệp đang chờ");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Cài đặt Mouzi");
strings.insert("organized", "Đã sắp xếp {} tệp");
}
"es" => {
strings.insert("quit", "Salir");
strings.insert("settings", "Configuración");
strings.insert("clean_now", "Organizar ahora");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} archivo esperando");
strings.insert("tooltip_many_pending", "Mouzi – {} archivos esperando");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Configuración de Mouzi");
strings.insert("organized", "{} archivo(s) organizado(s)");
}
"zh-CN" => {
strings.insert("quit", "退出");
strings.insert("settings", "设置");
strings.insert("clean_now", "立即整理");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} 个文件等待整理");
strings.insert("tooltip_many_pending", "Mouzi – {} 个文件等待整理");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Mouzi 设置");
strings.insert("organized", "已整理 {} 个文件");
strings.insert("notification_title", "Mouzi – 点击打开文件夹");
}
"uk" => {
strings.insert("quit", "Вийти");
strings.insert("settings", "Налаштування");
strings.insert("clean_now", "Упорядкувати зараз");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi — очікує {} файл");
strings.insert("tooltip_many_pending", "Mouzi — очікує файлів: {}");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Налаштування Mouzi");
strings.insert("organized", "Впорядковано файлів: {}");
}
_ => {
strings.insert("quit", "Quit");
strings.insert("settings", "Settings");
strings.insert("clean_now", "Organize Now");
strings.insert("tooltip", "Mouzi");
strings.insert("tooltip_one_pending", "Mouzi – {} file waiting");
strings.insert("tooltip_many_pending", "Mouzi – {} files waiting");
strings.insert("popup_title", "Mouzi");
strings.insert("settings_title", "Mouzi Settings");
strings.insert("organized", "Organized {} file(s)");
strings.insert("notification_title", "Mouzi – click to open folder");
}
}
Self { strings }
}

pub fn get<'a>(&self, key: &'a str) -> &'a str {
self.strings.get(key).copied().unwrap_or(key)
}
}

Loading