feat(i18n): training-panel strings across all locales (RFC 0003) - #55
Merged
Merged
Conversation
Bumps shared-resources to the merged training-strings catalogue (dasher-shared-resources#2) and regenerates all 33 .resx files. The four interpolated status messages now use string.Format around Loc.Tr with {0}/{1} placeholders, so translated values interpolate correctly instead of shipping pre-baked English strings.
Signed-off-by: will wade <willwade@gmail.com>
willwade
force-pushed
the
feat/training-locale-pass
branch
from
September 8, 2026 17:23
bc14011 to
6f45f12
Compare
5 tasks
willwade
added a commit
that referenced
this pull request
Sep 10, 2026
…, caret-move seeding (RFC 0019) (#56) ## What Implements RFC 0019 (the editor contract) Workstreams A+B on Windows — v5-parity editing reported missing by a long-term v5 user after v0.1.26 ("clicked at the end of the word, the canvas didn't move to that word like it did in 5"). Governance PR: dasher-project/governance#38. Engine-side needed nothing — all APIs shipped with the RFC 0015 context work. ### A. Regular mode: editable pane + caret re-anchor + New - `MessageArea` read-only → editable; `UndoLimit=0` (v1 — undo stance tracked as RFC 0019 open question 2) - **User edits seed the engine immediately** (no debounce): the canvas pushes engine text into the VM every frame, so a debounced edit would be clobbered before the timer fired. The engine buffer is the loop-guard's origin of truth — pane == buffer means an engine push landing (nothing to seed), a difference is a user edit → `dasher_seed_buffer(text, caretBytes)` - **Engine-origin pushes preserve the caret** (at-end follows growth, else clamped) via a suppress-flagged programmatic set - **Pure caret moves re-anchor** via `dasher_set_offset` immediately — v5's `CEdit::OnLButtonUp → SetOffset` parity - **New** button (normal action row + keyboard mini-bar) → `dasher_reset` — buffer + context + rate window; `reset_output_text` alone would resume mid-sentence (v5 `SetBuffer(0)` semantics, per GTK's documented distinction) ### B. Direct mode: caret-move re-seeding - UIA `TextSelectionChanged` watch (subtree of the tracked target root) → existing `SeedContextFromTargetAsync` path — caret moves **within an already-focused field** were invisible to the focus/foreground hooks (RFC 0015 clause-8 amendment). The handler only signals (UIA re-entrancy rule); the existing debounce + stale-target foreground guard do the rest. Re-armed on root change, torn down on mode exit. ### Fix found along the way (pre-existing bug) The four text-bearing P/Invokes (`dasher_seed_buffer`, `dasher_import_training_text`, both byte-offset converters) marshalled as **`LPStr` (ANSI)** — non-ASCII text silently corrupted to Latin-1 bytes. This affected the shipped v0.1.26 context seeding and training import for any non-ASCII target text (accents, umlauts, CJK). Now `LPUTF8Str` per the engine's UTF-8 contract. Paths/ids deliberately stay `LPStr` (ANSI bytes round-trip through ANSI file APIs; changing those without an engine-side wide-path audit would break non-ASCII user dirs). ## Tests - New engine-integration test pins the contract through the Windows P/Invoke surface: seed caret lands on the converted byte offset, `set_offset` re-anchors, New clears buffer + offset — **85/85** - The test is what exposed the marshalling bug (é in the fixture landed on the wrong byte) ## Manual checklist (needs a human pass — the v5 behaviours) - [ ] Click mid-word in the pane → canvas re-targets; predictions continue from the click - [ ] Type/paste into the pane with the physical keyboard → predictions incorporate; caret stays sane; no flicker while zooming after manual edits - [ ] New (both bars) → empty pane, predictions restart from scratch (not mid-sentence) - [ ] Direct mode: click around caret positions in Notepad/browser → re-seeds each time - [ ] Regression: focus-switch seeding, clipboard bar, speak-on-space, training panel ## Notes - Loc.Tr keys for New tooltips use English fallbacks; shared-resources batch to follow (same pattern as #54→#55) - Undo disabled is deliberate v1 scope — RFC 0019 open question 2 tracks the decision <!-- greptile_comment --> <!-- greptile_summary --> <h2><a href="https://app.greptile.com/api/retrigger?id=62600775"><picture><source media="(prefers-color-scheme: dark)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/RetriggerDark.svg?v=1"><source media="(prefers-color-scheme: light)" srcset="https://greptile-static-assets.s3.amazonaws.com/badges/Retrigger.svg?v=1"><img alt="Retrigger" src="https://greptile-static-assets.s3.amazonaws.com/badges/Retrigger.svg?v=1" align="right"></picture></a>Confidence Score: 5/5</h2> The PR appears safe to merge. <h3>Summary</h3> - Makes the message pane editable and synchronizes user edits and caret movements with the native engine. - Adds full-session reset actions to the normal and keyboard-mode toolbars. - Watches UI Automation selection changes to refresh direct-mode context. - Corrects UTF-8 marshalling for text-bearing native calls and adds an engine integration test. - Hardens editor synchronization against null binding values during pane-mode transitions. <details open><summary><h3>Diagram</h3></summary> ```mermaid sequenceDiagram participant User participant Editor as MessageArea participant Window as MainWindow participant Bridge as NativeBridge participant Engine as DasherCore participant Target as Direct-mode target User->>Editor: Edit text or move caret Editor->>Window: Text/Caret change Window->>Bridge: seed_buffer or set_offset Bridge->>Engine: Update buffer context Engine-->>Window: Current output each frame Window-->>Editor: Suppressed caret-preserving update Target-->>Window: UIA selection changed Window->>Target: Read focused text and caret Window->>Bridge: seed_buffer(text, byte offset) Bridge->>Engine: Re-anchor direct-mode context ``` </details> <sub>Reviews (2) · Last reviewed commit: ["fix(editor): harden editor-sync against ..."](https://github.com/dasher-project/dasher-windows/commit/7342adae1fdeeacf5748bcaa3b2eda6bdf2ef450)</sub> <!-- /greptile_comment --> --------- Signed-off-by: will wade <willwade@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The RFC 0003 locale pass for the training panel — the follow-up flagged in #54's pre-merge review:
shared-resourcesto merged main (dasher-shared-resources#2: the 13 training keys, machine-translated across all catalogue locales).resxfiles viagen-translations.py(CI freshness gate satisfied)training_current_size,training_imported,training_imported_restart,training_reset_partial) now usestring.FormataroundLoc.Trwith{0}/{1}placeholders — previously the English defaults were pre-interpolated, which would have shown literal{0}from translated resx valuesStack
Stacked on #54 — merge that first; this retargets to main automatically.
Verified
The PR appears safe to merge.
Summary
{0}and{1}receive runtime values.