#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Language {
#[default]
English,
French,
Spanish,
German,
Italian,
PortugueseBR,
PortuguesePT,
ChineseSimplified,
}
impl Language {
#[must_use]
pub const fn to_locale(self) -> &'static str {
match self {
Self::English => "en",
Self::French => "fr",
Self::Spanish => "es",
Self::German => "de",
Self::Italian => "it",
Self::PortugueseBR => "pt-BR",
Self::PortuguesePT => "pt-PT",
Self::ChineseSimplified => "zh-CN",
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Translations {
language: Language,
}
impl Translations {
#[must_use]
pub fn new(language: Language) -> Self {
rust_i18n::set_locale(language.to_locale());
Self { language }
}
#[must_use]
pub const fn language(&self) -> Language {
self.language
}
pub fn set_language(&mut self, language: Language) {
self.language = language;
rust_i18n::set_locale(language.to_locale());
}
#[must_use]
pub fn search_placeholder(&self) -> String {
rust_i18n::t!("search.placeholder", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn replace_placeholder(&self) -> String {
rust_i18n::t!("replace.placeholder", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn case_sensitive_label(&self) -> String {
rust_i18n::t!(
"settings.case_sensitive_label",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn previous_match_tooltip(&self) -> String {
rust_i18n::t!(
"search.previous_match_tooltip",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn next_match_tooltip(&self) -> String {
rust_i18n::t!(
"search.next_match_tooltip",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn close_search_tooltip(&self) -> String {
rust_i18n::t!(
"search.close_tooltip",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn replace_current_tooltip(&self) -> String {
rust_i18n::t!(
"replace.current_tooltip",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn replace_all_tooltip(&self) -> String {
rust_i18n::t!("replace.all_tooltip", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn context_menu_undo(&self) -> String {
rust_i18n::t!("context_menu.undo", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn context_menu_redo(&self) -> String {
rust_i18n::t!("context_menu.redo", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn context_menu_cut(&self) -> String {
rust_i18n::t!("context_menu.cut", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn context_menu_copy(&self) -> String {
rust_i18n::t!("context_menu.copy", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn context_menu_paste(&self) -> String {
rust_i18n::t!("context_menu.paste", locale = self.language.to_locale())
.into_owned()
}
#[must_use]
pub fn context_menu_select_all(&self) -> String {
rust_i18n::t!(
"context_menu.select_all",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn context_menu_reveal_in_finder(&self) -> String {
rust_i18n::t!(
"context_menu.reveal_in_finder",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn context_menu_reveal_in_file_explorer(&self) -> String {
rust_i18n::t!(
"context_menu.reveal_in_file_explorer",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn context_menu_open_containing_folder(&self) -> String {
rust_i18n::t!(
"context_menu.open_containing_folder",
locale = self.language.to_locale()
)
.into_owned()
}
#[must_use]
pub fn context_menu_reveal_in_file_manager(&self) -> String {
if cfg!(target_os = "macos") {
self.context_menu_reveal_in_finder()
} else if cfg!(target_os = "windows") {
self.context_menu_reveal_in_file_explorer()
} else {
self.context_menu_open_containing_folder()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_language() {
let translations = Translations::default();
assert_eq!(translations.language(), Language::English);
}
#[test]
fn test_new_with_language() {
let translations = Translations::new(Language::French);
assert_eq!(translations.language(), Language::French);
}
#[test]
fn test_set_language() {
let mut translations = Translations::new(Language::English);
translations.set_language(Language::Spanish);
assert_eq!(translations.language(), Language::Spanish);
}
#[test]
fn test_english_translations() {
let t = Translations::new(Language::English);
assert_eq!(t.search_placeholder(), "Search...");
assert_eq!(t.replace_placeholder(), "Replace...");
assert_eq!(t.case_sensitive_label(), "Case sensitive");
assert_eq!(t.previous_match_tooltip(), "Previous match (Shift+F3)");
assert_eq!(t.next_match_tooltip(), "Next match (F3 / Enter)");
assert_eq!(t.close_search_tooltip(), "Close search dialog (Esc)");
assert_eq!(t.replace_current_tooltip(), "Replace current match");
assert_eq!(t.replace_all_tooltip(), "Replace all matches");
}
#[test]
fn test_french_translations() {
let t = Translations::new(Language::French);
assert_eq!(t.search_placeholder(), "Rechercher...");
assert_eq!(t.replace_placeholder(), "Remplacer...");
assert_eq!(t.case_sensitive_label(), "Sensible à la casse");
assert_eq!(t.previous_match_tooltip(), "Résultat précédent (Maj+F3)");
assert_eq!(t.next_match_tooltip(), "Résultat suivant (F3 / Entrée)");
assert_eq!(t.close_search_tooltip(), "Fermer la recherche (Échap)");
assert_eq!(
t.replace_current_tooltip(),
"Remplacer l'occurrence actuelle"
);
assert_eq!(t.replace_all_tooltip(), "Tout remplacer");
}
#[test]
fn test_spanish_translations() {
let t = Translations::new(Language::Spanish);
assert_eq!(t.search_placeholder(), "Buscar...");
assert_eq!(t.replace_placeholder(), "Reemplazar...");
assert_eq!(t.case_sensitive_label(), "Distinguir mayúsculas");
assert_eq!(
t.previous_match_tooltip(),
"Coincidencia anterior (Mayús+F3)"
);
assert_eq!(
t.next_match_tooltip(),
"Siguiente coincidencia (F3 / Enter)"
);
assert_eq!(t.close_search_tooltip(), "Cerrar búsqueda (Esc)");
assert_eq!(
t.replace_current_tooltip(),
"Reemplazar coincidencia actual"
);
assert_eq!(t.replace_all_tooltip(), "Reemplazar todo");
}
#[test]
fn test_german_translations() {
let t = Translations::new(Language::German);
assert_eq!(t.search_placeholder(), "Suchen...");
assert_eq!(t.replace_placeholder(), "Ersetzen...");
assert_eq!(t.case_sensitive_label(), "Groß-/Kleinschreibung");
assert_eq!(
t.previous_match_tooltip(),
"Vorheriger Treffer (Umschalt+F3)"
);
assert_eq!(t.next_match_tooltip(), "Nächster Treffer (F3 / Enter)");
assert_eq!(t.close_search_tooltip(), "Suchdialog schließen (Esc)");
assert_eq!(t.replace_current_tooltip(), "Aktuellen Treffer ersetzen");
assert_eq!(t.replace_all_tooltip(), "Alle ersetzen");
}
#[test]
fn test_italian_translations() {
let t = Translations::new(Language::Italian);
assert_eq!(t.search_placeholder(), "Cerca...");
assert_eq!(t.replace_placeholder(), "Sostituisci...");
assert_eq!(t.case_sensitive_label(), "Distingui maiuscole");
assert_eq!(
t.previous_match_tooltip(),
"Risultato precedente (Maiusc+F3)"
);
assert_eq!(t.next_match_tooltip(), "Risultato successivo (F3 / Invio)");
assert_eq!(
t.close_search_tooltip(),
"Chiudi finestra di ricerca (Esc)"
);
assert_eq!(
t.replace_current_tooltip(),
"Sostituisci risultato corrente"
);
assert_eq!(t.replace_all_tooltip(), "Sostituisci tutto");
}
#[test]
fn test_portuguese_br_translations() {
let t = Translations::new(Language::PortugueseBR);
assert_eq!(t.search_placeholder(), "Pesquisar...");
assert_eq!(t.replace_placeholder(), "Substituir...");
assert_eq!(t.case_sensitive_label(), "Diferenciar maiúsculas");
assert_eq!(
t.previous_match_tooltip(),
"Correspondência anterior (Shift+F3)"
);
assert_eq!(
t.next_match_tooltip(),
"Próxima correspondência (F3 / Enter)"
);
assert_eq!(
t.close_search_tooltip(),
"Fechar diálogo de pesquisa (Esc)"
);
assert_eq!(
t.replace_current_tooltip(),
"Substituir correspondência atual"
);
assert_eq!(t.replace_all_tooltip(), "Substituir tudo");
}
#[test]
fn test_portuguese_pt_translations() {
let t = Translations::new(Language::PortuguesePT);
assert_eq!(t.search_placeholder(), "Pesquisar...");
assert_eq!(t.replace_placeholder(), "Substituir...");
assert_eq!(t.case_sensitive_label(), "Diferenciar maiúsculas");
assert_eq!(
t.previous_match_tooltip(),
"Correspondência anterior (Shift+F3)"
);
assert_eq!(
t.next_match_tooltip(),
"Próxima correspondência (F3 / Enter)"
);
assert_eq!(
t.close_search_tooltip(),
"Fechar diálogo de pesquisa (Esc)"
);
assert_eq!(
t.replace_current_tooltip(),
"Substituir correspondência actual"
);
assert_eq!(t.replace_all_tooltip(), "Substituir tudo");
}
#[test]
fn test_language_switching() {
let mut t = Translations::new(Language::English);
assert_eq!(t.search_placeholder(), "Search...");
t.set_language(Language::French);
assert_eq!(t.search_placeholder(), "Rechercher...");
t.set_language(Language::Spanish);
assert_eq!(t.search_placeholder(), "Buscar...");
t.set_language(Language::German);
assert_eq!(t.search_placeholder(), "Suchen...");
t.set_language(Language::Italian);
assert_eq!(t.search_placeholder(), "Cerca...");
t.set_language(Language::PortugueseBR);
assert_eq!(t.search_placeholder(), "Pesquisar...");
t.set_language(Language::PortuguesePT);
assert_eq!(t.search_placeholder(), "Pesquisar...");
t.set_language(Language::ChineseSimplified);
assert_eq!(t.search_placeholder(), "搜索...");
}
#[test]
fn test_context_menu_translations_cover_all_locales() {
let cases = [
(
Language::English,
[
"Undo",
"Redo",
"Cut",
"Copy",
"Paste",
"Select All",
"Reveal in Finder",
"Reveal in File Explorer",
"Open Containing Folder",
],
),
(
Language::French,
[
"Annuler",
"Rétablir",
"Couper",
"Copier",
"Coller",
"Tout sélectionner",
"Révéler dans le Finder",
"Afficher dans l'Explorateur de fichiers",
"Ouvrir le dossier contenant",
],
),
(
Language::Spanish,
[
"Deshacer",
"Rehacer",
"Cortar",
"Copiar",
"Pegar",
"Seleccionar todo",
"Mostrar en Finder",
"Mostrar en el Explorador de archivos",
"Abrir carpeta contenedora",
],
),
(
Language::German,
[
"Rückgängig",
"Wiederholen",
"Ausschneiden",
"Kopieren",
"Einfügen",
"Alle auswählen",
"Im Finder anzeigen",
"Im Datei-Explorer anzeigen",
"Übergeordneten Ordner öffnen",
],
),
(
Language::Italian,
[
"Annulla azione",
"Ripeti",
"Taglia",
"Copia",
"Incolla",
"Seleziona tutto",
"Visualizza in Finder",
"Visualizza in Esplora file",
"Apri cartella superiore",
],
),
(
Language::PortugueseBR,
[
"Desfazer",
"Refazer",
"Recortar",
"Copiar",
"Colar",
"Selecionar Tudo",
"Revelar no Finder",
"Revelar no Explorador de Arquivos",
"Abrir a Pasta Que Contém",
],
),
(
Language::PortuguesePT,
[
"Anular",
"Refazer",
"Cortar",
"Copiar",
"Colar",
"Selecionar tudo",
"Mostrar no Finder",
"Mostrar no Explorador de Ficheiros",
"Abrir pasta contentora",
],
),
(
Language::ChineseSimplified,
[
"撤消",
"恢复",
"剪切",
"复制",
"粘贴",
"选择全部",
"在访达中显示",
"在文件资源管理器中显示",
"打开所在的文件夹",
],
),
];
for (language, expected) in cases {
let translations = Translations::new(language);
assert_eq!(translations.context_menu_undo(), expected[0]);
assert_eq!(translations.context_menu_redo(), expected[1]);
assert_eq!(translations.context_menu_cut(), expected[2]);
assert_eq!(translations.context_menu_copy(), expected[3]);
assert_eq!(translations.context_menu_paste(), expected[4]);
assert_eq!(translations.context_menu_select_all(), expected[5]);
assert_eq!(
translations.context_menu_reveal_in_finder(),
expected[6]
);
assert_eq!(
translations.context_menu_reveal_in_file_explorer(),
expected[7]
);
assert_eq!(
translations.context_menu_open_containing_folder(),
expected[8]
);
}
}
}