mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-31 15:48:33 +00:00
Two English surfaces the translation work so far could not reach. The dock's tab titles: `PanelKind::title()` is drawn by `dock_ui.rs`'s `tab_titles`, which listed only the tabs that name a comp, a layer or a script and let every other one fall back to `title()`'s English - so every panel tab (`Timeline`, `Preview`, `Properties`, `Effects & Presets`, ...) stayed English. The Window menu already carries a (`window.panel`, title) row in every catalog, so the dock reads that pair and falls back to the panel catalog for `Markers` (the one panel only it names); `History` and `ScriptUI Panel` have no row anywhere and keep their English names. `app.auto`'s labels and the dock's serialized state keep the English title, which the control channel needs. The scan's blind shapes: `converted_panels_have_no_unwrapped_literals` only sees a literal that follows a call token, so a label passed to a helper, the third argument of `Painter::text`, a `(key, label, ...)` table, a `let` binding and a `match` arm were all invisible. The two that can be checked without guessing are added (`helper_and_painter_labels_are_translated`), with the same single-character exemption the call scan makes, and the 25 sites they find now ask the catalog (`Apply`, `Analyze`, `Cancel`, `Create Camera`, `Add Point`, `Remove Point`, `Clear`, `Render`, `Stop`, `Save Current as Template...`, `New Composition From Footage`, the three search fields, `(no composition)`, `per second`, `Waveform`, `steps`), with 15 rows added to the Simplified and Traditional catalogs in the conventions those tables already use (Render 算圖, Apply 套用, Add Point 添加點). The `uic!` labels and the Keyboard Shortcuts dialog are a different shape and are still to decide (#1451). Verified on Linux: cargo fmt --all --check, cargo test -p effectcraft-ui-egui (every suite passes), cargo clippy -p effectcraft-ui-egui --all-targets -- -D warnings clean. Reverting the dock's catalog lookup fails `the_dock_draws_every_panel_it_can_in_the_interface_language`; unwrapping a helper or a painter label fails `helper_and_painter_labels_are_translated` ("panels/project.rs:434: the interface text \"Search project\" that widgets::search_field draws is not in the catalog"). Also answers #1451's question about languages whose rows have no Simplified row to be a subset of: six labels the Composition Settings dialog draws from a `(label, value)` table, a tab array and a `match` arm (`Square Pixels`, `Basic`, `Advanced`, `3D Renderer`, `Black`, `Composition Settings`, plus `White` from the same `color_name`) had no row anywhere, so every interface drew them in English; they have Simplified and Traditional rows now, in the existing menu wording. The seventh, `Lock Aspect Ratio`, is only an automation name - the drawn label is `Lock Aspect Ratio to {}`, which already had rows, and `comp_settings.rs` built it with `format!` where `dialogs.rs` already used `tr_args`, so that one is wired now too. Review fixes (CodeRabbit): the scan now runs over the whole file with line comments blanked, so a `.text(` call split across lines is still one argument list - which found five more labels the per-line loop could not see (`No effects. Drag one from Effects & Presets.`, the colour-ring hint in `fx_editors.rs`, the Learn blurb, the Script Console hint, the Templates blurb, plus `Building waveform…` from the review), all wired with rows. And the New Composition title is back to the English source: `modal_fit` keys the modal id and the drag offset on the title (its own comment says the id stays on the untranslated source) and translates the heading itself, so `tr(..)` there would have moved the dialog when the interface language changed. And the argument list is bounded by the call's closing parenthesis: `args_of` used to flush a trailing argument at end-of-string, so a last argument without a trailing comma carried the `)` and the source after it, which made the check skip it as "not a literal". Reverting that one line is a two-line test (a literal last argument in `header.rs` is caught now and was silent before). The label scan also understands the two string forms a label can be written in: a plain string ends at the first unescaped quote, a raw string (`r"…"`, `r#"…"#`) at a quote followed by as many `#` as opened it, and `literal_text` decodes the argument before the exemptions run - so an escaped or raw label is checked like any other instead of being skipped. Two more scan fixes from review: `without_comments` tracks the escape state rather than the previous character, so a string ending in a backslash (`"a\\"`) closes where it should; and the scanned range ends at the test *module* - the first `#[cfg(test)]` followed by a `mod` - rather than at the first `#[cfg(test)]`, because `dialogs.rs` keeps a test-only helper above its test module and production code between them was not scanned. And call tokens are looked for in a code-only mask: comments blanked, the contents of plain and raw strings blanked too, with the quotes kept and every byte offset preserved (a blanked character becomes as many spaces as its UTF-8 length, and a debug assertion pins the mask length). The argument list is read from the original source at that offset, so a sample string that quotes a call cannot be mistaken for one. Building the mask from chars instead of bytes shifted every offset after the first non-ASCII character, which the debug assertion now catches. The dock's display path has its own test now: `tab_titles` is called with `general.language` set to Chinese and the labels a window shows are asserted (`Timeline` 时间轴 ...), plus `History` keeping its English tab and the English interface keeping all of them. Reverting the dock to `PanelKind::title()` fails it with "Timeline is not drawn in Chinese", which the catalog-only test could not see.