From 8fcc4897c7a89e7de37d290df562623781b60b43 Mon Sep 17 00:00:00 2001 From: Nathaniel Ledford Date: Fri, 9 Oct 2026 15:02:02 -0400 Subject: [PATCH] LRC-LIB-KEYWORDS: keyword translations: Person, merging, export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Russian had no "Person": the option showed in English (it reaches `tr` through a variable). A test now checks that every label the Keyword List passes that way is in every language's file. - The merge confirmation's button said "Merge", which some languages translate as merging photos (HDR, panorama): it says "Merge Keywords". - Traditional Chinese uses 匯出 for Export, as everywhere else in the file, not 轉存; "Export Containing Keywords" means the parent keywords in both Chinese files (上層 / 上级), not "included" ones. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/locales/ru.json | 3 ++- crates/ui-egui/locales/zh-hans.json | 2 +- crates/ui-egui/locales/zh-hant.json | 6 ++--- crates/ui-egui/src/panels/dialogs.rs | 3 ++- crates/ui-egui/src/panels/keyword_list.rs | 27 +++++++++++++++++++++++ 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/crates/ui-egui/locales/ru.json b/crates/ui-egui/locales/ru.json index 22ce2e160..57440fe76 100644 --- a/crates/ui-egui/locales/ru.json +++ b/crates/ui-egui/locales/ru.json @@ -1429,5 +1429,6 @@ "Delete Keyword…": "Удалить ключевое слово…", "Drop here for the top level": "Отпустите здесь для верхнего уровня", "Their photos and the keywords below them come together under one keyword.": "Их фото и вложенные ключевые слова объединятся под одним ключевым словом.", - "Select photos to give them keywords.": "Выберите фото, чтобы назначить им ключевые слова." + "Select photos to give them keywords.": "Выберите фото, чтобы назначить им ключевые слова.", + "Person": "Человек" } diff --git a/crates/ui-egui/locales/zh-hans.json b/crates/ui-egui/locales/zh-hans.json index e73f6593c..c652318ad 100644 --- a/crates/ui-egui/locales/zh-hans.json +++ b/crates/ui-egui/locales/zh-hans.json @@ -1744,7 +1744,7 @@ "Separated by commas": "用逗号分隔", "Keyword Tag Options": "关键字标记选项", "Include on Export": "导出时包含", - "Export Containing Keywords": "导出包含的关键字", + "Export Containing Keywords": "导出上级关键字", "Export Synonyms": "导出同义词", "Create Keyword Tag": "创建关键字标记", "Edit Keyword Tag": "编辑关键字标记", diff --git a/crates/ui-egui/locales/zh-hant.json b/crates/ui-egui/locales/zh-hant.json index 886336abb..d29103389 100644 --- a/crates/ui-egui/locales/zh-hant.json +++ b/crates/ui-egui/locales/zh-hant.json @@ -1743,9 +1743,9 @@ "Synonyms": "同義詞", "Separated by commas": "以逗號分隔", "Keyword Tag Options": "關鍵字標記選項", - "Include on Export": "轉存時包含", - "Export Containing Keywords": "轉存包含的關鍵字", - "Export Synonyms": "轉存同義詞", + "Include on Export": "匯出時包含", + "Export Containing Keywords": "匯出上層關鍵字", + "Export Synonyms": "匯出同義詞", "Create Keyword Tag": "建立關鍵字標記", "Edit Keyword Tag": "編輯關鍵字標記", "Create": "建立", diff --git a/crates/ui-egui/src/panels/dialogs.rs b/crates/ui-egui/src/panels/dialogs.rs index 058735f02..62cd8ca04 100644 --- a/crates/ui-egui/src/panels/dialogs.rs +++ b/crates/ui-egui/src/panels/dialogs.rs @@ -904,7 +904,8 @@ pub fn show(app: &mut LightcraftApp, ctx: &egui::Context) { Dialog::FaceModel { info, .. } if !informational && info["download"].is_string() => "Download", Dialog::FaceModel { .. } if !informational => "Install", Dialog::ConfirmDelete { .. } | Dialog::DeleteKeyword { .. } => "Delete", - Dialog::MoveKeyword { .. } => "Merge", + // (not "Merge": that is photo merging, HDR / panorama, in some languages) + Dialog::MoveKeyword { .. } => "Merge Keywords", Dialog::KeywordTag { editing: None, .. } => "Create", Dialog::KeywordTag { .. } => "Save", Dialog::RemoveFolder { .. } => "Remove", diff --git a/crates/ui-egui/src/panels/keyword_list.rs b/crates/ui-egui/src/panels/keyword_list.rs index 8eab45029..482db5648 100644 --- a/crates/ui-egui/src/panels/keyword_list.rs +++ b/crates/ui-egui/src/panels/keyword_list.rs @@ -563,4 +563,31 @@ mod tests { let (c, ids) = library(&[&["Ärzte", "ÄRZTE"], &[]]); assert_eq!(Ticks::of(&c, &ids).tick("ärzte"), Tick::Some); } + + /// The labels the Keyword List and its dialogs pass to `tr` through variables (out of reach of + /// a literal search) are translated in every language. + #[test] + fn labels_passed_through_variables_are_translated() { + use crate::i18n::Locale; + let labels = [ + "Include on Export", + "Export Containing Keywords", + "Export Synonyms", + "Person", + "Merge Keywords", + "No keywords yet", + "No keywords match", + "Add to Selected Photos", + "Remove from Selected Photos", + ]; + let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("locales"); + for code in ["de", "es", "pt-br", "ru", "ja", "zh-hans", "zh-hant"] { + let text = std::fs::read_to_string(dir.join(format!("{code}.json"))).unwrap(); + let catalog: std::collections::HashMap = serde_json::from_str(&text).unwrap(); + for label in labels { + assert!(catalog.contains_key(label), "{code}: “{label}”"); + } + } + assert_eq!(Locale::ALL.len(), 8, "a language added: list its file above"); + } }