feat(tui): localize /mode picker and composer Vim indicator (harvest of #2239)#3530
Conversation
e9350aa to
86b136c
Compare
|
Claude finished @Hmbown's task in 3m 22s —— View job Code Review — feat(tui): localize /mode picker and composer Vim indicator
SummaryThe harvest is clean and well-scoped. Model-boundary safety holds. One visible cosmetic regression for CJK users in the picker layout; everything else is correct. Model-boundary safety ✓
Issues1. CJK picker alignment regression — format!(
"{pointer} {}. {:<7}",
mode.number(),
mode.display_name_localized(self.locale)
),
This pushes the hint span rightward by 5–6 extra columns in East Asian locales, breaking the visual alignment for the only three users who care most about localization. Fix — replace the padded format with explicit width-aware padding: let name = mode.display_name_localized(self.locale);
let display_cols = UnicodeWidthStr::width(name);
let pad = " ".repeat(7usize.saturating_sub(display_cols));
format!("{pointer} {}. {name}{pad}", mode.number()),2.
Not a regression (was English before), but worth a follow-up i18n pass for the Localization qualityAll 7 locales have translations for all 10 new
Tests ✓
Dead code / cleanup ✓No remaining callers of Verdict: One fix needed for CJK display-width alignment before this is pixel-perfect. Everything else is correct and the model-boundary claim is solid. |
86b136c to
42491c3
Compare
|
Claude finished @Hmbown's task in 1m 34s —— View job Re-review Complete
Updated Review — feat(tui): localize /mode picker and composer Vim indicatorThis sync addresses the one issue flagged in the prior review. All checks pass. CJK alignment fix ✓ —
|
|
Heads-up for merge: please rebase or merge-commit, not squash. This commit carries Minor, separate: the commit's committer is |
Forward-ports the mode-system slice of the Phase 1 i18n work onto current main. The /mode picker (prompt, mode names, and hints) and the composer's Vim mode indicator now resolve through tr() across all seven shipped locales. English copy is unchanged. Model-facing surfaces stay English on purpose: AppMode::label() (footer, telemetry, context report) keeps returning the English &'static str, so the picker/composer use locale-aware *_localized helpers while the model boundary is untouched. The superseded English-only picker_hint()/ VimMode::label() are removed now that their values live in the En locale arm. Adds 10 MessageIds (mode picker prompt/names/hints + Vim Normal/Insert/ Visual) with translations in en, ja, zh-Hans, zh-Hant, pt-BR, es-419, vi, satisfying the shipped-locale completeness test, plus a no-English-leak test for the picker sentences. Most of PR #2239 already landed on main via @gordonlu's later PRs (#2891, #2892, #2896, #2901) and earlier harvests; this is the remaining user-facing mode-system surface, remade against current main. Harvested from PR #2239 by @gordonlu.
42491c3 to
8f6a73d
Compare
|
Claude finished @Hmbown's task in 1m 35s —— View job Bot Trailer — Already Clean
The synchronize event was triggered by an amended push that already resolved the issue Hunter flagged. The commit is now fully compliant:
No The branch is ready to merge via rebase or merge-commit (not squash), as Hunter noted. |
|
Both addressed:
I've got the merge — will land it via rebase as soon as CI is green, so please leave the merge button to me to avoid an accidental squash. Generated by Claude Code |

Credited harvest of the remaining user-facing mode-system slice from @gordonlu's #2239 ("i18n Phase 1–4b wiring"), remade against current
mainrather than merged.Why a remake instead of a merge
#2239's base is 1658 commits behind
main(26 conflicting files). Crucially, most of it already landed on main via @gordonlu's later PRs (#2891 approval, #2892 elevation, #2896 status picker, #2901 tool families) and earlier harvests (FanoutCounts, queue, context inspector). Main now ships 7 complete locales (en, ja, zh-Hans, zh-Hant, pt-BR, es-419, vi) enforced by a completeness test. The genuine un-harvested remainder was the mode system — exactly gordon's branch focus (i18n-phase1-composer-config-statusline). So this rebuilds that surface natively on current main.What this does
/modepicker: prompt, mode names (Agent/YOLO/Plan), and hints — the screen where users learn what each mode does.-- NORMAL/INSERT/VISUAL --).MessageIds with translations across all 7 shipped locales. Translations convey meaning (e.g. YOLO hint → "full access" / auto-approve; Agent hint → asks before changes), staying close to the English where natural. English copy is unchanged.Safety: model boundary untouched
AppMode::label()(footer + telemetry + context report — model-facing) keeps returning the English&'static str. The picker/composer use additive*_localized(locale)helpers driven byui_locale, so the localized strings can't leak into model-facing context — the exact bug flagged on the original PR. The superseded English-onlypicker_hint()/VimMode::label()are removed (their values now live in theEnlocale arm).Tests
shipped_first_pack_has_no_missing_core_messages— all 7 locales complete (exhaustive matches make a missing arm a compile error).mode_picker_strings_are_translated_in_non_english_locales— no English leak for the picker prompt + hints.cargo fmt --all --check,git diff --check, zero warnings;mode_picker(4),tui::app::tests(169),commands::groups::core(117) all green.Credit
Authored as @gordonlu (canonical noreply) +
Harvested from PR #2239 by @gordonlu; CONTRIBUTORS.md and CHANGELOG.md updated. Closes the mode-system portion of #2239 — the remaining surfaces (e.g.error/error_msgrefactor) are intentionally out of scope.Generated by Claude Code