The desktop app has a working i18n system for the renderer (ui/src/i18n, with
en / zh / zh-Hant / ja), but the main process has none. Every native
surface is hardcoded, so a user who picks 中文 in Settings still gets a mix of
languages in OS-rendered UI.
Where it shows
Native strings are currently a mix of both languages:
| Surface |
Current string |
| Tray menu |
Show OpenAlice, Pet, Quit (English) |
| Companion submenu |
Hide pet / Show pet, Size, Small/Medium/Large (English) |
| Companion context menu |
Show OpenAlice, Quit OpenAlice (English, previously partly Chinese) |
Menu.setApplicationMenu |
OS roles only, no custom strings |
Switching the UI language changes the renderer only. The tray, the pet's
right-click menu, and any future native dialog stay as-is.
Why it is not a one-liner
The renderer's locale lives in localStorage (openalice.locale.v1, see
ui/src/i18n/store.ts), which the main process cannot read. So the locale has
to be pushed to the main process over IPC before native menus can be localized —
that is new plumbing, not a string swap.
Rough shape of the work:
- Persist the locale somewhere the main process can read, or mirror it on
change (ipcRenderer.send('openalice:locale', locale) from a subscription
in ui/src/i18n/index.ts).
- Add a main-process translation table for the native strings. It cannot reuse
ui/src/i18n/locales/* directly — the desktop package does not currently
depend on the ui package, so either add that dependency or keep a small
native-only table.
- Rebuild menus on locale change. The tray already rebuilds on every open, so
it would pick up a new locale on the next right-click; setApplicationMenu
would need an explicit refresh.
Scope question for maintainers
This affects all native surfaces, not just the tray — the companion context
menu and the app menu have the same problem. So before implementing, it would
help to know the preferred direction:
- (a) mirror the locale over IPC and translate native strings, or
- (b) treat main-process menus as English-only and make that explicit, or
- (c) something else.
Happy to implement whichever you prefer once the approach is settled.
The desktop app has a working i18n system for the renderer (
ui/src/i18n, withen/zh/zh-Hant/ja), but the main process has none. Every nativesurface is hardcoded, so a user who picks 中文 in Settings still gets a mix of
languages in OS-rendered UI.
Where it shows
Native strings are currently a mix of both languages:
Show OpenAlice,Pet,Quit(English)Hide pet/Show pet,Size,Small/Medium/Large(English)Show OpenAlice,Quit OpenAlice(English, previously partly Chinese)Menu.setApplicationMenuSwitching the UI language changes the renderer only. The tray, the pet's
right-click menu, and any future native dialog stay as-is.
Why it is not a one-liner
The renderer's locale lives in
localStorage(openalice.locale.v1, seeui/src/i18n/store.ts), which the main process cannot read. So the locale hasto be pushed to the main process over IPC before native menus can be localized —
that is new plumbing, not a string swap.
Rough shape of the work:
change (
ipcRenderer.send('openalice:locale', locale)from a subscriptionin
ui/src/i18n/index.ts).ui/src/i18n/locales/*directly — the desktop package does not currentlydepend on the ui package, so either add that dependency or keep a small
native-only table.
it would pick up a new locale on the next right-click;
setApplicationMenuwould need an explicit refresh.
Scope question for maintainers
This affects all native surfaces, not just the tray — the companion context
menu and the app menu have the same problem. So before implementing, it would
help to know the preferred direction:
Happy to implement whichever you prefer once the approach is settled.