feat(CODAP-1092): notify/reload plugins on locale change#2392
Conversation
Design for notifying and reloading plugins when locale changes in V3. Includes URL parameter, interactiveFrame API extension, hardcoded reload list with opt-out, and MobX-based locale change reactions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only append ?lang= to the iframe src for localized plugins that need reload. Non-localized plugins keep a stable src and receive a localeChanged notification instead of being reloaded. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2392 +/- ##
==========================================
+ Coverage 85.45% 85.51% +0.05%
==========================================
Files 753 753
Lines 41500 41540 +40
Branches 10235 10257 +22
==========================================
+ Hits 35462 35521 +59
+ Misses 6028 6006 -22
- Partials 10 13 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
codap-v3
|
||||||||||||||||||||||||||||
| Project |
codap-v3
|
| Branch Review |
main
|
| Run status |
|
| Run duration | 05m 30s |
| Commit |
|
| Committer | Kirk Swenson |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
1
|
|
|
73
|
|
|
0
|
|
|
300
|
| View all changes introduced in this branch ↗︎ | |
There was a problem hiding this comment.
Pull request overview
Implements locale-change support for embedded plugins in CODAP v3 by reloading a small set of known localized plugins via ?lang= iframe URL changes, while notifying other plugins of locale changes via iframePhone.
Changes:
- Extend the Data Interactive
interactiveFrameAPI to expose currentlangand accepthandlesLocaleChange(opt-out of reload). - Add localized-plugin detection (
kLocalizedPluginPatterns+needsLocaleReload) and compute iframesrcwith?lang=for those plugins. - Add a MobX locale reaction in the web-view DI controller to either trigger reconnect (localized) or broadcast
localeChanged(others), plus URL utility + tests.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| v3/src/data-interactive/handlers/interactive-frame-handler.ts | Returns lang and persists handlesLocaleChange onto the WebView model. |
| v3/src/data-interactive/handlers/interactive-frame-handler.test.ts | Adds coverage for lang in get() and handlesLocaleChange in update(). |
| v3/src/data-interactive/data-interactive-types.ts | Extends DIInteractiveFrame with lang and handlesLocaleChange. |
| v3/src/components/web-view/web-view.tsx | Uses a derived iframeSrc that appends ?lang= only for reload-needed plugins. |
| v3/src/components/web-view/web-view-utils.ts | Adds appendLangParam() helper for updating/adding the lang query param. |
| v3/src/components/web-view/web-view-utils.test.ts | Adds unit tests for appendLangParam() behavior. |
| v3/src/components/web-view/web-view-model.ts | Adds handlesLocaleChange + needsLocaleReload view and setter. |
| v3/src/components/web-view/web-view-model.test.ts | Adds tests for needsLocaleReload and the new volatile flag. |
| v3/src/components/web-view/web-view-defs.ts | Defines kLocalizedPluginPatterns list used to decide reload behavior. |
| v3/src/components/web-view/use-data-interactive-controller.ts | Adds locale-change reaction to bump a version counter or broadcast localeChanged. |
| v3/doc/plugin-locale-switching-design.md | Adds a design doc for the approach. |
| v3/doc/2026-02-14-plugin-locale-switching.md | Adds an implementation plan doc for the feature. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
v3/src/data-interactive/handlers/interactive-frame-handler.test.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fix hash fragment bug in appendLangParam regex replace path, gate needsLocaleReload on isPlugin/isPluginCandidate, update docs to match implementation, add test coverage for hash fragment edge cases, and clean up test naming. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bb3573b to
eaf4b50
Compare
Summary
?lang=query parameter to iframe URLs for localized plugins (Importer, TP-Sampler, Scrambler, storyBuilder) so they reload with the correct locale when the user switches languagelangin theinteractiveFrame.getAPI response so plugins can read the current localelocaleChangednotification to non-localized plugins via iframePhone so they can react programmaticallyhandlesLocaleChangeopt-out: plugins that handle locale changes themselves can set this viainteractiveFrame.updateto prevent automatic reloadHow it works
Localized plugins (matched by URL patterns in
kLocalizedPluginPatterns): their iframesrcgets?lang=<locale>appended, which changes when locale changes, triggering an iframe reload. The iframePhone connection is torn down and re-established via alocaleVersioncounter in the useEffect deps.All other plugins: receive a
localeChangednotification viabroadcastMessage(), matching V2 behavior. Their iframesrcdoesn't change, so they don't reload.Opt-out mechanism: plugins can call
interactiveFrame.update({ handlesLocaleChange: true })to signal they handle locale changes programmatically, which prevents automatic reload even for localized plugins.Test plan
interactiveFrame.getreturnslangpropertyinteractiveFrame.update({ handlesLocaleChange: true })prevents reloadnpm test— all 2138 tests pass🤖 Generated with Claude Code