i18n(ru): translate the dynamic labels the Russian catalog was missing

The Russian catalog passed `cargo xtask i18n-coverage` (100% of measured keys)
but lacked the runtime-only labels the other catalogs already carry, so they
showed in English: filter and adjustment parameter names and choices, gallery
names, Camera Raw panels (Balance/Clarity/Dehaze/Color Mixer/Texture/…),
History/Layers/paths/channels menu labels, metadata and File Info fields,
System Info and hardware status lines, rasterize prompts, composed status
templates and dialog text.

All of them are translated (1,229 keys added; the catalog is now 4,227 keys
against upstream's 2,998), written from the meaning of the English labels and
reusing the vocabulary the catalog already uses (Highlights → Света,
Midtones → Полутона, Feather → Растушёвка, Pattern → узор). Filter and gallery
names are aligned with the menu labels already in the catalog so a filter never
reads two ways (Texturizer → Текстуризатор, Unsharp Mask → Нерезкое
маскирование, Shape Blur → Размытие по фигуре, …).

Tests: `russian_covers_generated_filter_options_and_gallery_names`
(filter_dialog.rs, the Italian/Korean/Spanish check) and
`russian_dynamic_status_hardware_and_dialog_labels_are_translated` (i18n/mod.rs).
Docs: docs/localization-ru.md (terminology), localization-parity, gaps G13,
ROADMAP, ATTRIBUTION and LICENSE-translations.

Validated on a rebase onto upstream/main: `cargo test -p photocraft-ui-egui
--lib` 2,998 passed / 0 failed; clippy clean (the only lint is a pre-existing
`nonminimal_bool` in canvas.rs, untouched here and present on upstream main);
`xtask layers` OK; `xtask wasm` OK; `xtask i18n-coverage` ru 1,863 / 1,863;
offscreen `snapshot` in Russian checked.
This commit is contained in:
Stepan Pavlenko
2026-10-18 02:27:44 +03:00
parent 235e7578f3
commit e4bc5c25e8
9 changed files with 1391 additions and 12 deletions
+1
View File
@@ -25,6 +25,7 @@ next to them.
| `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) |
| `crates/ui-egui/src/i18n/sr.tsv` | Serbian (Latin, Ekavian) 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/ru.tsv` | Russian 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`, `gradient.svg`, `type-mask.svg`, `type-mask-vertical.svg`, `clip-below.svg`, `clip-release.svg`, `layer-mask.svg`, `adjustment-layer.svg`, `brush-replace.svg`, `quick-selection.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) |
+3 -2
View File
@@ -2,7 +2,7 @@
**Stage: alpha** · next: beta, ~30 points (ready for real work ~45% → ~75%, with reliable PSD) and ~1,100–1,800 h away
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-13 · **Change:** minor (oracle floor 145 of 258 and 953 open issues, as in gaps.md and on GitHub; toolbox count 56 of 68, 12 missing) · **Target:** Adobe Photoshop 2026
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-15 · **Change:** minor (Russian catalog covers every dynamic label; previously minor: oracle floor 145 of 258 and 953 open issues, as in gaps.md and on GitHub; toolbox count 56 of 68, 12 missing) · **Target:** Adobe Photoshop 2026
PhotoCraft's one-page summary of how close it is to Adobe Photoshop 2026 (27.11.0, measured from
the installed app on 2026-10-10) at version 0.6.0. Detail: [target-app parity](docs/target-app-parity.md)
@@ -104,7 +104,7 @@ because engine messages are still English. Detail: [localization-parity](docs/lo
| Korean | `ko` | 100% | partial |
| Vietnamese | `vi` | 0% | none |
Also shipped: Traditional Chinese, Russian, Ukrainian, Czech, Polish, Greek, Dutch, Italian (8).
Also shipped: Traditional Chinese, Russian (every dynamic label, [notes](docs/localization-ru.md)), Ukrainian, Czech, Polish, Greek, Dutch, Italian (8).
## Upcoming
@@ -136,6 +136,7 @@ Detail and the next releases: [docs/roadmap.md](docs/roadmap.md).
| Date | Change | Summary |
|---|---|---|
| 2026-10-13 | minor | Focus item 1 quoted the oracle floor as 133 of 256; it is 145 of 258 (`crates/io/tests/corpus.rs`, gaps.md G1). Open issues 579 → 953 (2026-10-13) |
| 2026-10-15 | minor | Russian catalog covers every dynamic UI label the other catalogs translate |
| 2026-10-11 | minor | Toolbox count 56 of 68 (12 missing) with the Convert Point tool (#3204) |
| 2026-10-10 | minor | Readiness by audience with hours per tier |
| 2026-10-10 | minor | Mainstream-practitioner and essentials-user numbers added |
+6
View File
@@ -1475,6 +1475,12 @@ mod tests {
assert!(missing.is_empty(), "missing Spanish dynamic labels: {missing:#?}");
}
#[test]
fn russian_covers_generated_filter_options_and_gallery_names() {
let missing = missing_generated_filter_labels(crate::i18n::lang_from_tag("ru-RU").unwrap());
assert!(missing.is_empty(), "missing Russian dynamic labels: {missing:#?}");
}
/// The Select menu's generated dialogs (Select and Mask, Modify ▸ …) show their
/// params, choices and title in every UI language, not just Korean.
#[test]
@@ -1,6 +1,6 @@
PhotoCraft's Korean, German, Spanish, Brazilian Portuguese, Italian, Ukrainian, Dutch, Czech,
Turkish, Hungarian and Serbian UI translation catalogs are licensed under MIT OR Apache-2.0,
at your option.
Turkish, Hungarian, Serbian and Russian 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.
Korean translations: PhotoCraft contributors, original translations of
@@ -37,3 +37,6 @@ PhotoCraft's English labels; no proprietary translation resources were used.
Serbian translations: PhotoCraft contributors, original translations of
PhotoCraft's English labels; no proprietary translation resources were used.
Russian translations: PhotoCraft contributors, original translations of
PhotoCraft's English labels; no proprietary translation resources were used.
+51
View File
@@ -1111,6 +1111,57 @@ mod tests {
}
}
/// Russian dynamic labels added in the fourth pass (filter parameters, Camera Raw panels,
/// hardware status, rasterize prompts, History/paths menus) render in Russian, not English.
#[test]
fn russian_dynamic_status_hardware_and_dialog_labels_are_translated() {
let ru = Lang::from_code("ru").expect("ru registered");
for kind in [
crate::rasterize_prompt::Kind::Type,
crate::rasterize_prompt::Kind::Shape,
crate::rasterize_prompt::Kind::SmartObject,
crate::rasterize_prompt::Kind::Fill,
] {
assert_ne!(tr(ru, kind.message()), kind.message(), "{:?}", kind);
}
assert_eq!(fmt(tr(ru, "Driver: {driver}"), &[("driver", "Mesa 25.0")]), "Драйвер: Mesa 25.0");
assert_eq!(
fmt(tr(ru, "Monitor profile on {display}: {profile}"), &[("display", "DELL U2720Q"), ("profile", "sRGB IEC61966-2.1")]),
"Профиль монитора для DELL U2720Q: sRGB IEC61966-2.1"
);
assert_eq!(fmt(tr(ru, "Platform: {os} {arch}"), &[("os", "Linux"), ("arch", "x86_64")]), "Платформа: Linux x86_64");
assert_eq!(tr(ru, "Graphics adapter"), "Графический адаптер");
assert_eq!(tr(ru, "Image compositor: {processor}"), "Компоновщик изображения: {processor}");
// Filter / adjustment parameter names.
for label in [
"Amount",
"Radius",
"Threshold",
"Angle",
"High Pass",
"Smart Blur",
"Reduce Noise",
"Lens Correction",
"Colored Pencil",
"Angled Strokes",
"Stained Glass",
"Sumi-e",
"Film Grain",
"Unsharp Mask",
"Lens Flare",
] {
assert!(has(ru, label), "Russian filter label missing: {label}");
}
// Dynamic composed status templates.
assert_eq!(fmt(tr(ru, "Step {step} ({id}) failed: {error}"), &[("step", "2"), ("id", "file.export"), ("error", "ok")]), "Шаг 2 (file.export) не выполнен: ok");
assert_eq!(fmt(tr(ru, "Couldn't open {name}: {error}"), &[("name", "scan.tif"), ("error", "denied")]), "Не удалось открыть scan.tif: denied");
assert_eq!(fmt(tr(ru, "Exported {path} ({size})"), &[("path", "/tmp/a.png"), ("size", "12 KB")]), "Экспортировано: /tmp/a.png (12 KB)");
assert_eq!(fmt(tr(ru, "Data Set: {name} ({index}/{total})"), &[("name", "Set 1"), ("index", "1"), ("total", "2")]), "Набор данных: Set 1 (1/2)");
// Document and layer names stay verbatim.
let text = fmt(tr(ru, "Saved {path}; image assets: {n} in {dir}"), &[("path", "/tmp/a.pcraft"), ("n", "3"), ("dir", "/tmp/assets")]);
assert!(text.contains("/tmp/a.pcraft") && text.contains("/tmp/assets"), "{text}");
}
/// Every `tl!("literal")` in the shell has an entry in each language that claims complete menus
/// (so a new label can't ship untranslated by accident). Literals that are deliberately shown as
/// they are (names, units) are listed in `KEEP_AS_IS`.
File diff suppressed because it is too large Load Diff
+7 -4
View File
@@ -1,7 +1,6 @@
# Where PhotoCraft falls short of Photoshop
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as Photoshop bins it, psd-tools oracle floor 241/309; G1: Gradient Map driven by the W3C luminosity, Photoshop-oracle floor 147/258; G7: Field Blur's on-canvas pins, #3373; G4: Hue Jitter amount track, #3825 partial; G4: minimum field interaction, #3825 partial; G1: CMYK Invert, Posterize and Threshold on the inks, 16-bit Lab Invert; Photoshop-oracle floor 145/258; G11: `.atn` import maps 112 events: Select and Mask, Filter Gallery Spatter, Ripple, Crystallize, Pattern Fill layers, mask targeting, Step Backward, nudges in points, Bitmap mode; G5: Free Transform H/V skew fields; G9: toolbar tool shortcut editing; refreshed against main: G2, G5, G7, G9, G10, G13, G14, G17 items that landed; G10: DPX read and write, #1049; G4: checkbox-only Brush Settings rows; G11: Load/Save Actions `.atn` landed, AUTO-219-2 partial; G5: hold-a-key spring-loaded tools landed, #2672; G1: #2465 fixed; stale missing-tool rows corrected: Color Replacement, Red Eye and Add/Delete Anchor Point are live tools, so only Art History Brush is missing; no estimate changed) · **Target:** Adobe Photoshop 2026
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-15 · **Change:** minor (G13: Russian gained the 1,233 dynamic UI labels other catalogs already had; no estimate changed; previously minor: G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as Photoshop bins it, psd-tools oracle floor 241/309; G1: Gradient Map driven by the W3C luminosity, Photoshop-oracle floor 147/258; G7: Field Blur's on-canvas pins, #3373; G4: Hue Jitter amount track, #3825 partial; G4: minimum field interaction, #3825 partial; G1: CMYK Invert, Posterize and Threshold on the inks, 16-bit Lab Invert; Photoshop-oracle floor 145/258; G11: `.atn` import maps 112 events: Select and Mask, Filter Gallery Spatter, Ripple, Crystallize, Pattern Fill layers, mask targeting, Step Backward, nudges in points, Bitmap mode; G5: Free Transform H/V skew fields; G9: toolbar tool shortcut editing; refreshed against main: G2, G5, G7, G9, G10, G13, G14, G17 items that landed; G10: DPX read and write, #1049; G4: checkbox-only Brush Settings rows; G11: Load/Save Actions `.atn` landed, AUTO-219-2 partial; G5: hold-a-key spring-loaded tools landed, #2672; G1: #2465 fixed; stale missing-tool rows corrected: Color Replacement, Red Eye and Add/Delete Anchor Point are live tools, so only Art History Brush is missing; no estimate changed) · **Target:** Adobe Photoshop 2026
Every known shortfall against Photoshop 2026 (27.11.0), one entry each, ranked by user impact
on the way to beta. This is the work list agents pick from: take the highest-ranked entry that
nobody is working on, and when you close part of one, update its evidence and estimate here and
@@ -254,6 +253,10 @@ what an agent can't finish alone.
as tofu (#1408, #1693).
- **Evidence (2026-10-11):** Czech dynamic UI wrappers, hardware labels and composed messages
translate at display sites; engine errors remain English. This does not close G13.
- **Evidence (2026-10-15):** Russian gained the 1,233 dynamic labels the other catalogs already
had (filter and adjustment parameters, Camera Raw, lighting, History/Layers/paths menus,
metadata, System Info, status templates, dialogs), with a terminology note
([localization-ru](localization-ru.md)); engine errors remain English. This does not close G13.
- **Detail:** [`localization-parity.md`](localization-parity.md).
- **Estimate:** 80–140 h. **Human:** native-speaker review of every catalog (none is recorded).
@@ -270,6 +273,7 @@ what an agent can't finish alone.
| Date | Change | Summary |
|---|---|---|
| 2026-10-15 | minor | G13: Russian gained the 1,233 dynamic UI labels other catalogs already had (filter and adjustment parameters, Camera Raw, lighting, History/Layers/paths menus, metadata, System Info, status templates, dialogs); engine messages and native review remain open |
| 2026-10-14 | minor | G1: a PSD smart object's filter mask shows when the file opens (Photoshop stores the filtered pixels unmasked); export stores them that way too; Photoshop-oracle floor 185 → 188 of 258 |
| 2026-10-13 | minor | G14: D90 image area measured (4288 × 2848 at (10, 10)); gap remains open |
| 2026-10-14 | minor | Corpus floors raised to the measured results of the CMYK, Lab, 32-bit, Levels, Threshold, Posterize, feather and pass-through fixes landed together: Photoshop-authored 165 → 185 of 258, io 146 → 148 of 170, psd-tools 242 → 249 of 309 |
@@ -286,8 +290,7 @@ what an agent can't finish alone.
| 2026-10-13 | minor | G1: Threshold splits on Photoshop's luminosity of whole samples (8- and 16-bit rules exact on four oracles); psd-tools threshold_rgb and threshold_16bits_rgb pass; psd-tools floor → 241 of 309 |
| 2026-10-13 | minor | G1: a pass-through group that is a clipping base and holds an adjustment layer renders isolated; psd-tools passthrough_clipping_mask_adjustment passes; psd-tools floor → 240 of 309 |
| 2026-10-13 | minor | G1: 16-bit Posterize bins the 16-bit sample, as Photoshop does (exact on two oracles); psd-tools floor → 241 of 309 |
| 2026-10-13 | minor | G1: Gradient Map driven by the W3C luminosity (0.3, 0.59, 0.11), as Photoshop is; rgb8/rgb16 gradient-map pass; Photoshop-oracle floor 145 → 147 of 258 |
| 2026-10-13 | minor | G6: stale "missing tool" list corrected against `main` — Color Replacement (`paint.colorReplacement`), Red Eye (`paint.redEye`) and Add/Delete Anchor Point (P flyout, #4144) are live tools, so the toolbox is 67 of 68 and Art History Brush is the only one missing; no percentage or estimate changed |
| 2026-10-13 | minor | G1: Gradient Map driven by the W3C luminosity (0.3, 0.59, 0.11), as Photoshop is; rgb8/rgb16 gradient-map pass; Photoshop-oracle floor 145 → 147 of 258 || 2026-10-13 | minor | G6: stale "missing tool" list corrected against `main` — Color Replacement (`paint.colorReplacement`), Red Eye (`paint.redEye`) and Add/Delete Anchor Point (P flyout, #4144) are live tools, so the toolbox is 67 of 68 and Art History Brush is the only one missing; no percentage or estimate changed |
| 2026-10-13 | minor | G4: Hue Jitter amount-track appearance (#3825, partial); no readiness percentage or estimate changed |
| 2026-10-13 | minor | G4: minimum inputs in Shape Dynamics and Transfer follow their Control (#3825, partial); no readiness percentage or estimate changed |
| 2026-10-12 | minor | G5: Free Transform options bar H/V skew fields done |
+5 -4
View File
@@ -1,10 +1,10 @@
# Localization parity
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-13 · **Change:** minor (Spanish dynamic labels; previously minor: Serbian catalog) · **Target:** Adobe Photoshop 2026
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-18 · **Change:** minor (Russian dynamic labels; previously minor: Spanish dynamic labels) · **Target:** Adobe Photoshop 2026
Per-language status of PhotoCraft's UI. How catalogs work and how to add one:
[`localization.md`](localization.md). Language notes: [Korean](localization-ko.md), [Spanish](localization-es.md),
[Simplified Chinese](localization-zh-hans.md), [Italian](localization-it.md).
[Simplified Chinese](localization-zh-hans.md), [Italian](localization-it.md), [Russian](localization-ru.md).
**How measured.** `cargo xtask i18n-coverage` (`xtask/src/i18n_coverage.rs`) defines the key
universe: `tl!("…")` literals and `trn(` plurals in `ui-egui` (tests excluded), menu-catalog
@@ -46,8 +46,8 @@ speakers, ~55% ready. Remaining: 80–140 h, plus native-speaker review (recorde
## Other shipped languages
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` (4,008; also every dynamic label the
Chinese `zh-hant` (2,329 rows), Russian `ru` (4,227 keys; also every dynamic label the
other catalogs translate, [notes](localization-ru.md)), Ukrainian `uk` (3,375), Czech `cs` (3,522),
Polish `pl` (3,366), Greek `el` (3,481), Dutch `nl` (3,568), Italian `it` (4,164; also every dynamic label the
other catalogs translate; reviewed by a native speaker, [notes](localization-it.md)). Turkish `tr`
(3,731 rows) also covers every measured key. Serbian `sr` (4,022 rows, Latin script, Ekavian, added 2026-10-12) covers every
@@ -87,3 +87,4 @@ engine localization or native review is complete.
| 2026-10-12 | minor | Spanish: 1,276 runtime-only labels added (filter and adjustment parameters, Camera Raw, panels, dialogs and status wrappers); generated-label coverage test added |
| 2026-10-12 | minor | Italian native-speaker review: mistranslations (Trap, HDR Toning, Display Text) and phrasing fixed |
| 2026-10-12 | minor | Serbian (`sr`, Latin, Ekavian) catalog: every measured key plus the dynamic labels of the other catalogs |
| 2026-10-18 | minor | Russian: 1,229 dynamic labels added (filter and adjustment parameters, Camera Raw, lighting, History/Layers/paths menus, metadata, System Info, status templates, dialogs) with a terminology note ([localization-ru](localization-ru.md)) |
+75
View File
@@ -0,0 +1,75 @@
# Russian terminology and dynamic UI labels
This note goes with the completion of the Russian catalog (`crates/ui-egui/src/i18n/ru.tsv`).
The catalog already covered every key `cargo xtask i18n-coverage` measures, but it lacked the
labels that only exist at runtime and that other catalogs (Italian, Serbian, Czech, Hungarian)
already translate: filter and adjustment parameter names, Camera Raw panels, lighting effects,
History / Layers / paths / channels menu labels, metadata fields, status messages, System Info
and dialog text. In Russian those showed in English.
They are now translated, reusing the vocabulary the catalog already uses elsewhere so the same
term reads the same everywhere. Translations are written from the meaning of PhotoCraft's English
labels; no proprietary translation resources, fonts, screenshots or user documents are included.
## Register and style
Commands are imperatives in the second person plural (*Сохранить*, *Удалить*, *Заново*);
where the catalog already uses a noun it is kept (*Уровни…*, *Кривые…*). Sentence case after the
first word, as in the rest of the catalog. Ellipses on dialog commands are preserved (`Ветер…`
→ `Ветер…`). Decimals use a comma (the file format's own labels keep their dots, e.g.
`Landscape, 10 x 8` stays `Альбомная, 10 x 8`). Latin product and technology names are not
translated (PhotoCraft, Camera Raw, RGB, CMYK, Lab, LUT, WebP); Camera Raw keeps `.xmp`; the
`HDR`, `HSL`, `HSB` and `W3C` acronyms and the `sGray`/`Pro Photo` identifiers stay Latin.
## Terminology
Existing choices were followed rather than re-invented, so the new rows use:
| English source | Russian | Note |
|---|---|---|
| Highlight(s) | Света | already in the catalog (`Highlights` → `Света`) |
| Midtone(s) | Полутона | already in the catalog |
| Shadow(s) | Тени | pairs with *Света* |
| Feather | Растушёвка | never *перо* |
| Fuzziness | Разброс | Color Range's tolerance |
| Dither | Дизеринг | |
| Pattern | Узор | also in *Узорный штамп* |
| Preset | Набор | *Набор кистей*, *набор инструментов* |
| Guide | Направляющая | *Схема направляющих* |
| Artboard | Монтажная область | |
| Workspace | Рабочая среда | |
| Stroke (contour) | Обводка | painterly strokes stay *штрихи*/*мазки* |
| Stroke (paint param) | Штрихи / мазки | `Strokes` → `Штрихи` |
| Amount | Величина | `Штрихи`, never *количество*, when it is a strength |
| Fill Opacity | Непрозрачность заливки | distinct from layer *Непрозрачность* |
| Feather Radius | Радиус растушёвки | |
| Sharpen | Резкость | `Smart Sharpen` → *Умная резкость*, `Unsharp Mask` → *Контурная резкость* |
| Noise | Шум | `Reduce Noise` → *Уменьшить шум* |
| Content-Aware | С учётом содержимого | |
| Camera Raw | Camera Raw | the panel name stays Latin (as German/Spanish do; Greek translates it) |
| Place Embedded / Linked | Поместить встроенный / связанный | |
| Rasterize | Растрировать | |
## Native review
The review was AI-assisted and each row was checked against the meaning of PhotoCraft's own
English label. A review by a native speaker is still welcome.
## Not covered
Engine error and status messages, user document, layer and preset names, and automation command
IDs stay in English, as in every language ([`localization-parity.md`](localization-parity.md)).
A few dynamic labels the other catalogs carry are not used by the current code; they are
translated to stay aligned with the other catalogs.
## Validation
- `russian_covers_generated_filter_options_and_gallery_names` (`crates/ui-egui/src/filter_dialog.rs`)
enumerates every filter and adjustment parameter, symbolic choice and gallery name and requires
a Russian row for each, like the Korean and Italian tests.
- `russian_dynamic_status_hardware_and_dialog_labels_are_translated` (`crates/ui-egui/src/i18n/mod.rs`)
covers the rasterize prompts, hardware status lines, composed status templates and a sample of
filter labels.
- `cargo test -p photocraft-ui-egui --lib`: 2,998 passed, 0 failed.
- `cargo xtask i18n-coverage`: `ru` remains at 100% of the measured keys.
- The offscreen `snapshot` example with `PHOTOCRAFT_LOCALE=ru` renders the dialogs with Russian
labels, without missing glyphs or clipped text.