ADR 0280: Plugin-Owned UI Localizes from the Host Locale
- Status: Accepted
- Date: 2026-09-17
- Related: ADR 0009 · ADR 0082 · ADR 0159 · ADR 0160 · ADR 0267 · 07-plugins/02-plugin-manifest-schema · 07-plugins/03-plugin-api
Context
The host already resolves two kinds of plugin copy it renders itself: manifest.i18n for identity (name / description / safetyNotes), and inline { en, "zh-CN" } on a few chrome labels (ui.title, view titles, settings destinations, session sources). Putting the same maps on generated contributes.settings (and then on commands, tools, themes) would grow a second incomplete i18n system inside the manifest: only two contract locales, two declaration shapes, and still no way for a panel or widget to relabel its own HTML.
A plugin process can already read the app language (pi.app.getLocale, pi.app.getAppearance().locale). Open panels already receive appearance:changed. The plugin process did not.
Decision
- For plugin-owned copy the host publishes the active language and nothing else:
pi.app.getLocale(),getAppearance().locale, andappearance:changedto open panels and loaded plugin processes. - Plugin-owned UI (panels, views, widgets, settings destinations, toasts, runtime command titles) localizes itself from that tag. Authors pick any catalog they want; the host does not translate it.
- Do not add more
PluginLocalizedStringmaps to contribution fields. Generatedcontributes.settingstitle/description/enum[].labelstay author-language plain strings. A plugin that needs a localized settings surface shipssettingsDestinations. - Host-owned surfaces that render without plugin code keep the contracts they already have:
manifest.i18n(ADR 0267) and the shipped chrome labels in (2) of the Context.
Consequences
- A language switch restyles plugin-owned UI live, without a reload and without rewriting the registry.
- Authors are not required to maintain bilingual maps for every setting.
- Existing host chrome localization is unchanged.
Alternatives
- Host-resolved locale maps on every contribution field: two models in one manifest, still only
en/zh-CN, and plugin HTML remains unsolved. - Resolve plugin copy in the renderer: rejected in ADR 0267; the renderer still must not parse a manifest.