i18n(tr): add Turkish UI translation catalog (#3809)

Add Turkish (tr) translation catalog covering 100% of measured UI strings (1,727/1,727 keys, 3,731 catalog entries).

- Register Turkish language in crates/ui-egui/src/i18n/mod.rs with complete_menus: true and plural_none
- Add tr.tsv translation catalog
- Add negotiation and coverage tests in system.rs, mod.rs and i18n_coverage.rs
- Add MIT OR Apache-2.0 notice in LICENSE-translations.txt
- Update docs/localization-parity.md

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Ufuk Efe
2026-10-12 18:01:46 +03:00
committed by GitHub
parent 67e4b8a499
commit b3309e27d7
7 changed files with 3800 additions and 3 deletions
+1
View File
@@ -20,6 +20,7 @@ next to them.
| `crates/ui-egui/src/i18n/uk.tsv` | Ukrainian UI translations | PhotoCraft contributors | Original translations of PhotoCraft's English labels | MIT OR Apache-2.0, [`LICENSE-translations.txt`](crates/ui-egui/src/i18n/LICENSE-translations.txt) |
| `crates/ui-egui/src/i18n/cs.tsv` | Czech UI translations | PhotoCraft contributors | Original translations of PhotoCraft's English labels | MIT OR Apache-2.0, [`LICENSE-translations.txt`](crates/ui-egui/src/i18n/LICENSE-translations.txt) |
| `crates/ui-egui/src/i18n/vi.tsv` | Vietnamese UI translations | PhotoCraft contributors | Original translations of PhotoCraft's English labels | MIT OR Apache-2.0, [`LICENSE-translations.txt`](crates/ui-egui/src/i18n/LICENSE-translations.txt) |
| `crates/ui-egui/src/i18n/tr.tsv` | Turkish UI translations | PhotoCraft contributors | Original translations of PhotoCraft's English labels | MIT OR Apache-2.0, [`LICENSE-translations.txt`](crates/ui-egui/src/i18n/LICENSE-translations.txt) |
| `assets/fonts/Inter-Regular.ttf`, `Inter-Medium.ttf`, `Inter-SemiBold.ttf` | Inter 4.001 (UI font) | The Inter Project Authors (Rasmus Andersson) | <https://github.com/rsms/inter> | SIL OFL 1.1, [`assets/fonts/OFL-Inter.txt`](assets/fonts/OFL-Inter.txt) |
| `assets/fonts/JetBrainsMono-Regular.ttf` | JetBrains Mono 2.305 (numeric font) | The JetBrains Mono Project Authors | <https://github.com/JetBrains/JetBrainsMono> | SIL OFL 1.1, [`assets/fonts/OFL-JetBrainsMono.txt`](assets/fonts/OFL-JetBrainsMono.txt) |
| `assets/icons/*.svg` except `slice-knife.svg`, `sampler.svg`, `artboard.svg`, `perspective-crop.svg`, `frame-placeholder.svg`, `type-mask.svg`, `type-mask-vertical.svg`, `clip-below.svg`, `clip-release.svg`, `layer-mask.svg`, `adjustment-layer.svg`, `brush-replace.svg`, `eraser-background.svg`, `eraser-magic.svg`, `lasso-magnetic.svg`, `direct-select.svg`, `convert-point.svg`, `pen-add-anchor.svg`, `pen-delete-anchor.svg`, `pen-freeform.svg`, `pen-curvature.svg`, `bandage-sparkle.svg`, `painting-symmetry.svg`, `symmetry-*.svg` and `marquee-{row,column}.svg` (113 files; `star-filled.svg` is `star.svg` with a solid fill) | Lucide icons | Lucide Icons and Contributors | <https://github.com/lucide-icons/lucide> (`icons/<name>.svg`; `align-*` are now named `text-align-*` upstream) | ISC, [`assets/icons/LICENSE-lucide.txt`](assets/icons/LICENSE-lucide.txt) |
@@ -1,4 +1,4 @@
PhotoCraft's Korean, German, Brazilian Portuguese, Italian, Ukrainian, Dutch and Czech UI translation catalogs are
PhotoCraft's Korean, German, Brazilian Portuguese, Italian, Ukrainian, Dutch, Czech and Turkish UI translation catalogs are
licensed under MIT OR Apache-2.0, at your option. The full license texts are in ../../../../LICENSE-MIT
and ../../../../LICENSE-APACHE.
@@ -22,3 +22,6 @@ PhotoCraft's English labels; no proprietary translation resources were used.
Czech translations: PhotoCraft contributors, original translations of
PhotoCraft's English labels; no proprietary translation resources were used.
Turkish translations: PhotoCraft contributors, original translations of
PhotoCraft's English labels; no proprietary translation resources were used.
+6 -1
View File
@@ -141,7 +141,7 @@ fn inflate(source: &[u8]) -> Result<String, String> {
}
/// The registry. English first: it is the fallback and the source language.
pub static LANGUAGES: [LangInfo; 18] = [
pub static LANGUAGES: [LangInfo; 19] = [
LangInfo { code: "en", name: "English", source: b"", plural: plural_one_other, complete_menus: false, catalog: OnceLock::new() },
LangInfo { code: "ja", name: "日本語", source: catalog!("ja"), plural: plural_none, complete_menus: true, catalog: OnceLock::new() },
LangInfo { code: "zh-hans", name: "简体中文", source: catalog!("zh-hans"), plural: plural_none, complete_menus: true, catalog: OnceLock::new() },
@@ -164,6 +164,8 @@ pub static LANGUAGES: [LangInfo; 18] = [
// Dutch; `nl-NL` and `nl-BE` locales both resolve here.
LangInfo { code: "nl", name: "Nederlands", source: catalog!("nl"), plural: plural_one_other, complete_menus: true, catalog: OnceLock::new() },
LangInfo { code: "it", name: "Italiano", source: catalog!("it"), plural: plural_one_other, complete_menus: true, catalog: OnceLock::new() },
// Turkish; `tr`, `tr-TR` and `tr_TR` locales resolve here.
LangInfo { code: "tr", name: "Türkçe", source: catalog!("tr"), plural: plural_none, complete_menus: true, catalog: OnceLock::new() },
// Vietnamese; `vi-VN` resolves here.
LangInfo { code: "vi", name: "Tiếng Việt", source: catalog!("vi"), plural: plural_none, complete_menus: true, catalog: OnceLock::new() },
];
@@ -418,6 +420,9 @@ mod tests {
assert_eq!(lang_from_tag("it-CH"), Lang::from_code("it"));
assert_eq!(lang_from_tag("nl_NL.UTF-8"), Lang::from_code("nl"));
assert_eq!(lang_from_tag("nl-BE"), Lang::from_code("nl"));
assert_eq!(lang_from_tag("tr_TR.UTF-8"), Lang::from_code("tr"));
assert_eq!(lang_from_tag("tr-TR"), Lang::from_code("tr"));
assert_eq!(lang_from_tag("tr"), Lang::from_code("tr"));
// Traditional Chinese: by region, by script, and with a region after the script.
assert_eq!(lang_from_tag("zh_TW.UTF-8"), Some(ZH()));
assert_eq!(lang_from_tag("zh-TW"), Some(ZH()));
+1
View File
@@ -96,6 +96,7 @@ mod tests {
(vec!["pt-PT"], "pt-br"),
(vec!["it-IT", "en-US"], "it"),
(vec!["nl-BE", "fr-BE"], "nl"),
(vec!["tr-TR", "en-US"], "tr"),
(vec![], "en"),
] {
with_system_tags(&tags, || assert_eq!(system_lang().code(), expected));
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -48,7 +48,8 @@ catalog).
8 more, each at 1,608 / 1,608 measured keys, status `partial` for the same reason: Traditional
Chinese `zh-hant` (2,329 rows), Russian `ru` (2,544), Ukrainian `uk` (3,375), Czech `cs` (3,522),
Polish `pl` (3,366), Greek `el` (3,481), Dutch `nl` (3,568), Italian `it` (3,928; also every dynamic label the
other catalogs translate, [notes](localization-it.md)).
other catalogs translate, [notes](localization-it.md)). Turkish `tr` (3,731 rows) also covers every
measured key.
Czech UI follow-up (2026-10-11): status and notice wrappers, hardware labels, brush and
transform accessibility names, rasterization prompts, profile mismatch messages and preset
@@ -79,3 +80,4 @@ engine localization or native review is complete.
| 2026-10-11 | minor | Czech dynamic status/notice and hardware text, render labels and Navigator zoom context; engine messages remain English |
| 2026-10-11 | minor | Czech review follow-ups: English System Info diagnostics, id-aware shortcut labels, display-only auto translation, warning punctuation and wording; catalog row count refreshed |
| 2026-10-11 | minor | Italian: 1,287 dynamic labels added (filter parameters, Camera Raw, lighting, panels, dialogs) and terminology made consistent |
| 2026-10-12 | minor | Added Turkish (`tr`) catalog with 100% measured UI coverage |
+1
View File
@@ -579,6 +579,7 @@ mod tests {
("el", "el.tsv"),
("uk", "uk.tsv"),
("nl", "nl.tsv"),
("tr", "tr.tsv"),
("vi", "vi.tsv"),
] {
let catalog_path = root.join("crates/ui-egui/src/i18n").join(path);