Native menu bar, provider status strings, export dialog, layer panel,
and image-panel popovers now resolve through op-i18n instead of
hardcoded English; the three ad-hoc mini locale tables fold into the
canonical catalogs. New *_panel.rs overflow shards keep every table
under the 800-line cap (catalog at 1098 keys). The desktop menu also
rebuilds live on locale change instead of waiting for the next launch.
Includes the pending interactions/quick-action/dialog locale entries
and locale.rs additions from the working tree.
Earlier convert-locales.py was line-based + single-quote-only, missing
~16 keys per locale where:
- the value spans onto the next line ('long.key.name':\n 'value')
- the value uses double quotes for English contractions ('topbar.dontSave': "Don't Save")
Switch to a regex.finditer over the whole file with multi-line +
double-quote alternation. All 15 locales now report 706 keys each,
matching the TS source (apps/web/src/i18n/locales/*.ts).
Stop-hook: 'locale import is incomplete'.
Replaces the hand-rolled 25-key i18n.rs with 15 generated locale
modules (~700 keys each) mirrored from
apps/web/src/i18n/locales/*.ts via tools/convert-locales.py.
Locale enum expanded to match the TS dropdown:
EnUs / ZhCn / ZhTw / Ja / Ko / Fr / Es / De / Pt / Ru / Hi / Tr /
Th / Vi / Id (15 total). Each carries its native-script
display_name() (English / 简体中文 / 繁體中文 / 日本語 / 한국어 /
Français / Español / Deutsch / Português / Русский / हिन्दी /
Türkçe / ไทย / Tiếng Việt / Bahasa Indonesia).
Globe icon click cycles all 15 via Locale::next() (round-robin
through Locale::ALL).
Chrome key references updated to TS dot.case naming so the same
key resolves on both sides:
- topbar.untitled → common.untitled
- layer_panel.pages → pages.title
- layer_panel.layers → layers.title
- chat.new_chat → ai.newChat
- chat.start_with_ai → ai.tryExample
- chat.input_placeholder → ai.designWithAgent
Generator script lives at tools/convert-locales.py (re-run when
TS strings update). Each locale .rs file is ≤ 710 lines (under
the 800-line ceiling). Cross-locale fallback: missing keys try
EN before falling through to the key itself.
68 lib tests pass (+1 i18n fallback test).