Summary
Bot command menus (!help, !translation, !transcription, !privacy, thread help, etc.) are currently English-only. We need a durable way to manage menu language so that every language in !list-langs can have a localized menu, with bot-text UI for users to pick that language.
Today translation content can target the full catalog in translate_lang.rs (ALL_LANGUAGES / !list-langs), but UI copy lives in menu_locale.rs as static English strings. Per-group preference plumbing still assumes a tiny MenuLanguage enum (en / es only) in menu_language.rs; the old !set-en / !set-es handlers are being removed / deferred while menus stay EN-only.
Goals
- Parity with
!list-langs — For each supported translation language code, the bot should be able to render menus in that language (or a clear fallback policy if a translation is missing).
- Selectable via bot text — Users must be able to choose menu language through Signal commands / menu UI (not only env or operator config). Prefer something that scales beyond two hard-coded
!set-xx commands (e.g. !set-lang <code>, a language picker menu, or selection from !list-langs).
- Any language works — Design should not hard-limit UI locales to a small enum; adding a new code to
ALL_LANGUAGES should be the main gate for both translation and menu locale availability (or document an explicit subset + path to full coverage).
- Preserve mobile menu layout — Localized strings must keep the stacked command-list standard in
docs/solutions/signal-mobile-menus.md (title / section / !cmd + indented description).
Scope (product surfaces)
At minimum, localize (or define fallback for):
- Hub / role
!help
- Language Thread
!help
!translation product menu (including auto-translate disabled variant)
!transcription / pairing messages
!privacy (both roles)
- Any footer / confirmation copy tied to menu-language changes
Out of scope unless it falls out naturally: translating user message content (already handled by translation product paths).
Open design questions
- Storage: Keep per-group preference (current
GroupPreferencesStore shape) vs per-user preference for DMs / mixed groups?
- Authoring: Hand-maintained static strings per locale vs generate/translate from a single EN source (quality, TEE/privacy, review process)?
- Fallback: Missing key → English? Missing locale → English? Partial coverage OK for MVP?
- Discovery UX: How does a non-English speaker find the language picker if the default menu is English?
- Scaling commands:
!set-en / !set-es does not scale to ~30 codes; what replaces it?
Acceptance criteria
References
Summary
Bot command menus (
!help,!translation,!transcription,!privacy, thread help, etc.) are currently English-only. We need a durable way to manage menu language so that every language in!list-langscan have a localized menu, with bot-text UI for users to pick that language.Today translation content can target the full catalog in
translate_lang.rs(ALL_LANGUAGES/!list-langs), but UI copy lives inmenu_locale.rsas static English strings. Per-group preference plumbing still assumes a tinyMenuLanguageenum (en/esonly) inmenu_language.rs; the old!set-en/!set-eshandlers are being removed / deferred while menus stay EN-only.Goals
!list-langs— For each supported translation language code, the bot should be able to render menus in that language (or a clear fallback policy if a translation is missing).!set-xxcommands (e.g.!set-lang <code>, a language picker menu, or selection from!list-langs).ALL_LANGUAGESshould be the main gate for both translation and menu locale availability (or document an explicit subset + path to full coverage).docs/solutions/signal-mobile-menus.md(title / section /!cmd+ indented description).Scope (product surfaces)
At minimum, localize (or define fallback for):
!help!help!translationproduct menu (including auto-translate disabled variant)!transcription/ pairing messages!privacy(both roles)Out of scope unless it falls out naturally: translating user message content (already handled by translation product paths).
Open design questions
GroupPreferencesStoreshape) vs per-user preference for DMs / mixed groups?!set-en/!set-esdoes not scale to ~30 codes; what replaces it?Acceptance criteria
!list-langscodes get menus).ALL_LANGUAGEScodes (full strings or explicit fallback) without requiring a new Rust enum variant per language.References
crates/signal-bot/src/commands/menu_locale.rs— current EN-only menus (multi-language UI is deferred)crates/signal-bot/src/commands/translate_lang.rs—ALL_LANGUAGES/!list-langscrates/signal-bot/src/menu_language.rs—En/Esonly todaydocs/solutions/signal-mobile-menus.md— menu layout standard