@seed-ship/mcp-ui-solid 6.19.0 → 6.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/CHANGELOG.md +532 -0
  2. package/README.md +798 -1
  3. package/dist/adapters/connector.cjs +15 -4
  4. package/dist/adapters/connector.cjs.map +1 -1
  5. package/dist/adapters/connector.d.ts +38 -0
  6. package/dist/adapters/connector.d.ts.map +1 -1
  7. package/dist/adapters/connector.js +15 -4
  8. package/dist/adapters/connector.js.map +1 -1
  9. package/dist/adapters/index.d.ts +4 -3
  10. package/dist/adapters/index.d.ts.map +1 -1
  11. package/dist/adapters/macro-run.cjs +25 -13
  12. package/dist/adapters/macro-run.cjs.map +1 -1
  13. package/dist/adapters/macro-run.d.ts +37 -2
  14. package/dist/adapters/macro-run.d.ts.map +1 -1
  15. package/dist/adapters/macro-run.js +25 -13
  16. package/dist/adapters/macro-run.js.map +1 -1
  17. package/dist/adapters.cjs +2 -0
  18. package/dist/adapters.cjs.map +1 -1
  19. package/dist/adapters.js +4 -2
  20. package/dist/components/ActionGroupRenderer.cjs +3 -1
  21. package/dist/components/ActionGroupRenderer.cjs.map +1 -1
  22. package/dist/components/ActionGroupRenderer.d.ts.map +1 -1
  23. package/dist/components/ActionGroupRenderer.js +3 -1
  24. package/dist/components/ActionGroupRenderer.js.map +1 -1
  25. package/dist/components/AgentCard.cjs +11 -8
  26. package/dist/components/AgentCard.cjs.map +1 -1
  27. package/dist/components/AgentCard.d.ts.map +1 -1
  28. package/dist/components/AgentCard.js +11 -8
  29. package/dist/components/AgentCard.js.map +1 -1
  30. package/dist/components/AgentHandoff.cjs +6 -1
  31. package/dist/components/AgentHandoff.cjs.map +1 -1
  32. package/dist/components/AgentHandoff.d.ts.map +1 -1
  33. package/dist/components/AgentHandoff.js +6 -1
  34. package/dist/components/AgentHandoff.js.map +1 -1
  35. package/dist/components/ArtifactRenderer.cjs +25 -6
  36. package/dist/components/ArtifactRenderer.cjs.map +1 -1
  37. package/dist/components/ArtifactRenderer.d.ts.map +1 -1
  38. package/dist/components/ArtifactRenderer.js +25 -6
  39. package/dist/components/ArtifactRenderer.js.map +1 -1
  40. package/dist/components/AutocompleteDropdown.cjs +30 -24
  41. package/dist/components/AutocompleteDropdown.cjs.map +1 -1
  42. package/dist/components/AutocompleteDropdown.d.ts.map +1 -1
  43. package/dist/components/AutocompleteDropdown.js +30 -24
  44. package/dist/components/AutocompleteDropdown.js.map +1 -1
  45. package/dist/components/AutocompleteFormField.cjs +3 -1
  46. package/dist/components/AutocompleteFormField.cjs.map +1 -1
  47. package/dist/components/AutocompleteFormField.d.ts.map +1 -1
  48. package/dist/components/AutocompleteFormField.js +4 -2
  49. package/dist/components/AutocompleteFormField.js.map +1 -1
  50. package/dist/components/BriefingDiff.cjs +45 -39
  51. package/dist/components/BriefingDiff.cjs.map +1 -1
  52. package/dist/components/BriefingDiff.d.ts.map +1 -1
  53. package/dist/components/BriefingDiff.js +45 -39
  54. package/dist/components/BriefingDiff.js.map +1 -1
  55. package/dist/components/CarouselRenderer.cjs +8 -2
  56. package/dist/components/CarouselRenderer.cjs.map +1 -1
  57. package/dist/components/CarouselRenderer.d.ts.map +1 -1
  58. package/dist/components/CarouselRenderer.js +8 -2
  59. package/dist/components/CarouselRenderer.js.map +1 -1
  60. package/dist/components/ChartJSRenderer.cjs +60 -36
  61. package/dist/components/ChartJSRenderer.cjs.map +1 -1
  62. package/dist/components/ChartJSRenderer.d.ts.map +1 -1
  63. package/dist/components/ChartJSRenderer.js +61 -37
  64. package/dist/components/ChartJSRenderer.js.map +1 -1
  65. package/dist/components/ChatPrompt.cjs +15 -9
  66. package/dist/components/ChatPrompt.cjs.map +1 -1
  67. package/dist/components/ChatPrompt.d.ts.map +1 -1
  68. package/dist/components/ChatPrompt.js +15 -9
  69. package/dist/components/ChatPrompt.js.map +1 -1
  70. package/dist/components/CodeBlockRenderer.cjs +34 -16
  71. package/dist/components/CodeBlockRenderer.cjs.map +1 -1
  72. package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
  73. package/dist/components/CodeBlockRenderer.js +34 -16
  74. package/dist/components/CodeBlockRenderer.js.map +1 -1
  75. package/dist/components/DataPreviewSection.cjs +91 -44
  76. package/dist/components/DataPreviewSection.cjs.map +1 -1
  77. package/dist/components/DataPreviewSection.d.ts.map +1 -1
  78. package/dist/components/DataPreviewSection.js +92 -45
  79. package/dist/components/DataPreviewSection.js.map +1 -1
  80. package/dist/components/DegradedFallback.cjs +20 -16
  81. package/dist/components/DegradedFallback.cjs.map +1 -1
  82. package/dist/components/DegradedFallback.d.ts.map +1 -1
  83. package/dist/components/DegradedFallback.js +20 -16
  84. package/dist/components/DegradedFallback.js.map +1 -1
  85. package/dist/components/FeedbackInline.cjs +19 -3
  86. package/dist/components/FeedbackInline.cjs.map +1 -1
  87. package/dist/components/FeedbackInline.js +19 -3
  88. package/dist/components/FeedbackInline.js.map +1 -1
  89. package/dist/components/FooterRenderer.cjs +21 -17
  90. package/dist/components/FooterRenderer.cjs.map +1 -1
  91. package/dist/components/FooterRenderer.d.ts.map +1 -1
  92. package/dist/components/FooterRenderer.js +21 -17
  93. package/dist/components/FooterRenderer.js.map +1 -1
  94. package/dist/components/FormFieldRenderer.cjs +116 -93
  95. package/dist/components/FormFieldRenderer.cjs.map +1 -1
  96. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  97. package/dist/components/FormFieldRenderer.js +116 -93
  98. package/dist/components/FormFieldRenderer.js.map +1 -1
  99. package/dist/components/FormRenderer.cjs +55 -31
  100. package/dist/components/FormRenderer.cjs.map +1 -1
  101. package/dist/components/FormRenderer.d.ts.map +1 -1
  102. package/dist/components/FormRenderer.js +55 -31
  103. package/dist/components/FormRenderer.js.map +1 -1
  104. package/dist/components/GenerativeUIErrorBoundary.cjs +20 -15
  105. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
  106. package/dist/components/GenerativeUIErrorBoundary.d.ts.map +1 -1
  107. package/dist/components/GenerativeUIErrorBoundary.js +20 -15
  108. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
  109. package/dist/components/GraphRenderer.cjs +56 -33
  110. package/dist/components/GraphRenderer.cjs.map +1 -1
  111. package/dist/components/GraphRenderer.d.ts.map +1 -1
  112. package/dist/components/GraphRenderer.js +56 -33
  113. package/dist/components/GraphRenderer.js.map +1 -1
  114. package/dist/components/ImageGalleryRenderer.cjs +13 -4
  115. package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
  116. package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
  117. package/dist/components/ImageGalleryRenderer.js +13 -4
  118. package/dist/components/ImageGalleryRenderer.js.map +1 -1
  119. package/dist/components/LightboxOverlay.cjs +16 -8
  120. package/dist/components/LightboxOverlay.cjs.map +1 -1
  121. package/dist/components/LightboxOverlay.d.ts.map +1 -1
  122. package/dist/components/LightboxOverlay.js +17 -9
  123. package/dist/components/LightboxOverlay.js.map +1 -1
  124. package/dist/components/MapRenderer.cjs +59 -29
  125. package/dist/components/MapRenderer.cjs.map +1 -1
  126. package/dist/components/MapRenderer.d.ts +10 -2
  127. package/dist/components/MapRenderer.d.ts.map +1 -1
  128. package/dist/components/MapRenderer.js +60 -30
  129. package/dist/components/MapRenderer.js.map +1 -1
  130. package/dist/components/ModalRenderer.cjs +4 -1
  131. package/dist/components/ModalRenderer.cjs.map +1 -1
  132. package/dist/components/ModalRenderer.d.ts.map +1 -1
  133. package/dist/components/ModalRenderer.js +5 -2
  134. package/dist/components/ModalRenderer.js.map +1 -1
  135. package/dist/components/ScratchpadPanel.cjs +578 -535
  136. package/dist/components/ScratchpadPanel.cjs.map +1 -1
  137. package/dist/components/ScratchpadPanel.d.ts.map +1 -1
  138. package/dist/components/ScratchpadPanel.js +578 -535
  139. package/dist/components/ScratchpadPanel.js.map +1 -1
  140. package/dist/components/StreamingUIRenderer.cjs +92 -28
  141. package/dist/components/StreamingUIRenderer.cjs.map +1 -1
  142. package/dist/components/StreamingUIRenderer.d.ts.map +1 -1
  143. package/dist/components/StreamingUIRenderer.js +92 -28
  144. package/dist/components/StreamingUIRenderer.js.map +1 -1
  145. package/dist/components/UIResourceRenderer.cjs +456 -363
  146. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  147. package/dist/components/UIResourceRenderer.d.ts +21 -0
  148. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  149. package/dist/components/UIResourceRenderer.js +458 -365
  150. package/dist/components/UIResourceRenderer.js.map +1 -1
  151. package/dist/components/VerifiedText.cjs +39 -20
  152. package/dist/components/VerifiedText.cjs.map +1 -1
  153. package/dist/components/VerifiedText.d.ts +2 -1
  154. package/dist/components/VerifiedText.d.ts.map +1 -1
  155. package/dist/components/VerifiedText.js +39 -20
  156. package/dist/components/VerifiedText.js.map +1 -1
  157. package/dist/components/VideoRenderer.cjs +10 -5
  158. package/dist/components/VideoRenderer.cjs.map +1 -1
  159. package/dist/components/VideoRenderer.d.ts.map +1 -1
  160. package/dist/components/VideoRenderer.js +10 -5
  161. package/dist/components/VideoRenderer.js.map +1 -1
  162. package/dist/components/chart-data-table.cjs +38 -17
  163. package/dist/components/chart-data-table.cjs.map +1 -1
  164. package/dist/components/chart-data-table.d.ts +30 -1
  165. package/dist/components/chart-data-table.d.ts.map +1 -1
  166. package/dist/components/chart-data-table.js +38 -17
  167. package/dist/components/chart-data-table.js.map +1 -1
  168. package/dist/context/MCPActionContext.cjs +3 -1
  169. package/dist/context/MCPActionContext.cjs.map +1 -1
  170. package/dist/context/MCPActionContext.d.ts.map +1 -1
  171. package/dist/context/MCPActionContext.js +3 -1
  172. package/dist/context/MCPActionContext.js.map +1 -1
  173. package/dist/context/MCPUIStringsContext.cjs +285 -2
  174. package/dist/context/MCPUIStringsContext.cjs.map +1 -1
  175. package/dist/context/MCPUIStringsContext.d.ts +600 -3
  176. package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
  177. package/dist/context/MCPUIStringsContext.js +285 -2
  178. package/dist/context/MCPUIStringsContext.js.map +1 -1
  179. package/dist/hooks/index.d.ts +2 -2
  180. package/dist/hooks/index.d.ts.map +1 -1
  181. package/dist/hooks/useStreamingUI.cjs +28 -10
  182. package/dist/hooks/useStreamingUI.cjs.map +1 -1
  183. package/dist/hooks/useStreamingUI.d.ts +37 -0
  184. package/dist/hooks/useStreamingUI.d.ts.map +1 -1
  185. package/dist/hooks/useStreamingUI.js +28 -10
  186. package/dist/hooks/useStreamingUI.js.map +1 -1
  187. package/dist/hooks.cjs +1 -0
  188. package/dist/hooks.cjs.map +1 -1
  189. package/dist/hooks.js +2 -1
  190. package/dist/index.cjs +23 -8
  191. package/dist/index.cjs.map +1 -1
  192. package/dist/index.d.cts +9 -3
  193. package/dist/index.d.ts +9 -3
  194. package/dist/index.d.ts.map +1 -1
  195. package/dist/index.js +18 -3
  196. package/dist/index.js.map +1 -1
  197. package/dist/services/validation.cjs +41 -16
  198. package/dist/services/validation.cjs.map +1 -1
  199. package/dist/services/validation.d.ts +47 -2
  200. package/dist/services/validation.d.ts.map +1 -1
  201. package/dist/services/validation.js +41 -16
  202. package/dist/services/validation.js.map +1 -1
  203. package/dist/utils/degraded-projections.cjs +37 -12
  204. package/dist/utils/degraded-projections.cjs.map +1 -1
  205. package/dist/utils/degraded-projections.d.ts +39 -3
  206. package/dist/utils/degraded-projections.d.ts.map +1 -1
  207. package/dist/utils/degraded-projections.js +37 -12
  208. package/dist/utils/degraded-projections.js.map +1 -1
  209. package/dist/utils/format-string.cjs +10 -0
  210. package/dist/utils/format-string.cjs.map +1 -0
  211. package/dist/utils/format-string.d.ts +26 -0
  212. package/dist/utils/format-string.d.ts.map +1 -0
  213. package/dist/utils/format-string.js +10 -0
  214. package/dist/utils/format-string.js.map +1 -0
  215. package/dist/validation.cjs +3 -0
  216. package/dist/validation.cjs.map +1 -1
  217. package/dist/validation.d.cts +2 -1
  218. package/dist/validation.d.ts +2 -1
  219. package/dist/validation.d.ts.map +1 -1
  220. package/dist/validation.js +4 -1
  221. package/package.json +1 -1
  222. package/src/adapters/connector.ts +58 -4
  223. package/src/adapters/index.ts +12 -2
  224. package/src/adapters/macro-run.ts +71 -11
  225. package/src/components/ActionGroupRenderer.tsx +3 -1
  226. package/src/components/AgentCard.tsx +27 -9
  227. package/src/components/AgentHandoff.tsx +4 -1
  228. package/src/components/ArtifactRenderer.tsx +17 -5
  229. package/src/components/AutocompleteDropdown.tsx +8 -6
  230. package/src/components/AutocompleteFormField.tsx +5 -1
  231. package/src/components/BriefingDiff.tsx +11 -3
  232. package/src/components/CarouselRenderer.tsx +4 -2
  233. package/src/components/ChartJSRenderer.tsx +18 -9
  234. package/src/components/ChatPrompt.tsx +13 -8
  235. package/src/components/CodeBlockRenderer.tsx +12 -10
  236. package/src/components/DataPreviewSection.tsx +92 -26
  237. package/src/components/DegradedFallback.tsx +4 -2
  238. package/src/components/FeedbackInline.tsx +2 -2
  239. package/src/components/FooterRenderer.tsx +3 -1
  240. package/src/components/FormFieldRenderer.tsx +34 -19
  241. package/src/components/FormRenderer.tsx +38 -10
  242. package/src/components/GenerativeUIErrorBoundary.tsx +8 -3
  243. package/src/components/GraphRenderer.tsx +31 -16
  244. package/src/components/ImageGalleryRenderer.tsx +8 -4
  245. package/src/components/LightboxOverlay.tsx +6 -4
  246. package/src/components/MapRenderer.tsx +57 -20
  247. package/src/components/ModalRenderer.tsx +3 -1
  248. package/src/components/ScratchpadPanel.tsx +95 -44
  249. package/src/components/StreamingUIRenderer.tsx +41 -11
  250. package/src/components/UIResourceRenderer.tsx +145 -63
  251. package/src/components/VerifiedText.tsx +19 -9
  252. package/src/components/VideoRenderer.tsx +6 -4
  253. package/src/components/chart-data-table.ts +68 -14
  254. package/src/context/MCPActionContext.tsx +4 -1
  255. package/src/context/MCPUIStringsContext.tsx +1004 -1
  256. package/src/hooks/index.ts +2 -1
  257. package/src/hooks/useStreamingUI.ts +64 -10
  258. package/src/index.ts +23 -0
  259. package/src/services/validation.ts +93 -16
  260. package/src/utils/degraded-projections.ts +75 -12
  261. package/src/utils/format-string.ts +33 -0
  262. package/src/validation.ts +5 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,538 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [6.20.0] - 2026-09-17
9
+
10
+ Every user-visible chrome string the library itself renders — button titles,
11
+ `aria-label`s, placeholders, empty states, degraded-fallback captions, form
12
+ validation messages, and more — is now localizable: through `MCPUIStrings`
13
+ for components (`useMCPUIStrings()`), or through an exported `messages` /
14
+ `labels` option with an English default table for the runtime-free adapters,
15
+ services, helpers and hooks that cannot read Solid context. `MCPUIStrings`
16
+ now covers **270 keys** (9 required, carried over from the original v6.6.0
17
+ surface, plus 261 optional — every key added since defaults to English and
18
+ falls back cleanly when omitted). The only strings still hardcoded fall under
19
+ the explicit exclusion policy below (P1–P8). Both are enforced by an
20
+ AST-based guard test over all of `src` and a runtime pseudo-localization
21
+ render test — see **Tests**.
22
+
23
+ ### Added
24
+
25
+ - **251 new optional `MCPUIStrings` keys** (the released 6.19.1 had 19),
26
+ bringing the total to 270. Each defaults to the exact English literal it
27
+ replaced, except the defaults listed under **Changed**. The complete list,
28
+ with defaults and where each key is used, is the key reference table in
29
+ the README (*Internationalization (i18n) — `MCPUIStrings`*). Selected
30
+ groups:
31
+
32
+ - **Generic chrome** — `download`: `"Download"` (`ArtifactRenderer`
33
+ download link), `unknown`: `"unknown"` (`GenerativeUIErrorBoundary`
34
+ metadata fallback)
35
+ - **`UIResourceRenderer` table citations** — `citationUnresolved`:
36
+ `"[ref. {id}]"` (template `{id}`; placeholder for a citation marker no
37
+ `citationMap` resolves, empty map only — see **Changed**)
38
+ - **`UIResourceRenderer` error / fallback chrome** — `invalidComponent`:
39
+ `"Invalid {type}"`, `toolErrorTitle`: `"Tool Error: {tool}"`,
40
+ `errorTypeLabel`: `"Type: {type}"`, `errorSuggestions`: `"Suggestions:"`,
41
+ `chartInvalidData`: `"Invalid chart data: missing data.datasets"`,
42
+ `unsupportedComponentType`: `"Unsupported component type:"`
43
+ - **`UIResourceRenderer` table (search, pagination, tool-error clipboard)**
44
+ — `tableVirtualizedRows`: `"(virtualized: {count} rows)"`,
45
+ `tableSearchResultsOne` / `tableSearchResultsMany`:
46
+ `"{count} result(s) on {total}"` (was one template with a hardcoded
47
+ `s`), `tableServerPageRange`: `"Showing {start} - {end} of {total}"`,
48
+ `errorCopyText`: `"Error in {tool}: {message}"` (text the tool-error
49
+ card's Copy button puts on the clipboard), `errorUnknownTool`:
50
+ `"unknown tool"` (tool name inside `errorCopyText` when the error has
51
+ none)
52
+ - **`DataPreviewSection`** — `previewPrev`: `"Prev"`, `previewNext`:
53
+ `"Next"`, `previewPageIndicator`: `"Page {page} / {total}"`,
54
+ `previewShowingRange`: `"Showing {start}–{end} of {total}"`,
55
+ `previewRowsOne`: `"{count} row"`, `previewRowsMany`: `"{count} rows"`,
56
+ `previewTotalSuffix`: `" ({total} total)"`
57
+ - **`FormFieldRenderer`** — `fieldResolving`: `"Resolving..."`,
58
+ `fieldAddMorePlaceholder`: `"Add more..."`, `fieldUnknownType`:
59
+ `"Unknown field type: {type}"`, `fieldSelectedCount`: `"{count}
60
+ selected"`
61
+ - **`FormRenderer`** — `formPrefilledOne`: `"{count} field pre-filled out
62
+ of {total}"`, `formPrefilledMany`: `"{count} fields pre-filled out of
63
+ {total}"` (shared with `ScratchpadPanel`'s prefill summary — see
64
+ **Changed**), `formSubmitting`: `"Submitting..."`, `formReset`:
65
+ `"Reset"`
66
+ - **`GenerativeUIErrorBoundary`** — `errorBoundaryTitle`: `"Component
67
+ Failed to Render"`, `errorBoundaryMeta`: `"Type: {type} | ID:
68
+ {id}..."` (both fall back to `unknown`), `errorBoundaryRetry`: `"Retry
69
+ Rendering"`
70
+ - **`ScratchpadPanel`** — `scratchpadSearch`: `"Search"`
71
+ (`waiting_human` search button), `scratchpadNextStep`: `"Next"`
72
+ (steps view advance button), `scratchpadPlan`: `"Plan:"`,
73
+ `scratchpadModify`: `"Modify"` (prompt-section edit button),
74
+ `scratchpadDetails`: `"Details"` (error-section toggle),
75
+ `scratchpadItems`: `"items"` (action-section item-count suffix),
76
+ `statusLoading` / `statusActionAvailable` / `statusYourTurn` /
77
+ `statusProcessing` / `statusComplete` — status badge, one key per
78
+ state (the `error` state reuses `scratchpadError`),
79
+ `scratchpadErrorCode`: `"Code: {code}"`, `scratchpadResultCount`:
80
+ `"{count} results"` (data-source card row count)
81
+ - **`VideoRenderer`** — `videoUnsupported`: `"Your browser does not
82
+ support the video tag."` (`<video>` fallback text)
83
+ - **`AgentCard` / `AgentStatusBadge`** — `agentStatusIdle`: `"Idle"`,
84
+ `agentStatusRunning`: `"Running"`, `agentStatusWaiting`: `"Waiting"`,
85
+ `agentStatusDone`: `"Done"`, `agentStatusError`: `"Error"`
86
+ - **`AgentHandoff`** — `handoffItems`: `"{count} items"` (fallback;
87
+ `content.summary` still wins)
88
+ - **Fallback ladder** (`DegradedFallback`, `ChartJSRenderer`,
89
+ `GraphRenderer`, `MapRenderer`) — `degradedMoreRows`: `"+{count} more
90
+ rows not shown."`, `chartDegradedCaption`, `chartRenderFailed`:
91
+ `"Chart rendering failed: {error}"`, `chartRenderError`,
92
+ `chartQuickchartCaption`, `graphDegradedCaption`, `graphRenderFailed`,
93
+ `graphRenderError`, `graphPngUnsupported`, `graphPngExportFailed`,
94
+ `mapLibraryUnavailable`, `mapDegradedCaption`, `mapRenderFailed`,
95
+ `mapRenderError`
96
+ - **Degraded / accessible table headers** — `degradedColType`,
97
+ `degradedColLat`, `degradedColLng`, `degradedColInfo`,
98
+ `degradedColSource`, `degradedColTarget`, `degradedColNode`,
99
+ `degradedColLabel`, `degradedSeries`: `"Series {n}"`, `chartTableSeries`,
100
+ `chartTablePoint`, plus `degradedMarker`: `"marker"` and
101
+ `degradedFeature`: `"feature"` — the degraded map table's `Type` cell
102
+ for a marker row / a GeoJSON feature without a geometry type (mirrored
103
+ in `DEGRADED_PROJECTION_LABELS`, see below)
104
+ - **`AutocompleteDropdown` / `AutocompleteFormField`** —
105
+ `autocompleteHintNavigate`: `" to navigate, "`, `autocompleteHintSelect`:
106
+ `" to select, "`, `autocompleteHintDismiss`: `" to dismiss"`,
107
+ `autocompleteTabToAccept`: `"Tab to accept"` (the `<kbd>` key caps
108
+ themselves stay hardcoded — P1)
109
+ - **Images and chart fallbacks** — `galleryViewImage`: `"View image
110
+ {index}"`, `galleryImageAlt`: `"Image {index}"` (a payload `image.alt`
111
+ still wins for both), `imageAltFallback`: `"image"`,
112
+ `chartVisualizationAlt`: `"Chart visualization"`, `chartWithTitleAlt`:
113
+ `"Chart: {title}"`, `chartLoadFailed`: `"Failed to load chart"`
114
+ - **Table pagination** — `paginationAllRows`: `"All"`
115
+ - **Form validation** — `fieldRequired`, `fieldMustBeChecked`,
116
+ `fieldMinLength`, `fieldMaxLength`, `fieldInvalidPattern`,
117
+ `fieldInvalidEmail`, `fieldInvalidNumber`, `fieldMinValue`,
118
+ `fieldMaxValue`, `fieldMinDate`, `fieldMaxDate`, `fieldInvalidOption`,
119
+ `fieldInvalidFormat`: `"Invalid format (expected: {format})"`
120
+ (`field.valueFormatHint` wins when set) — `FormRenderer` feeds these
121
+ into `validateFieldValue` / `validateFormData` from `useMCPUIStrings()`
122
+ - **`BriefingDiff`** — `briefingAdded`: `"+{count} added"`,
123
+ `briefingRemoved`: `"{count} removed"`, `briefingChanged`: `"{count}
124
+ changed"`
125
+ - **`FooterRenderer`** — `footerSources`: `"{count} sources"`
126
+ - **`StreamingUIRenderer` / `useStreamingUI`** — `streamInitializing`:
127
+ `"Initializing..."`, `streamConnecting`: `"Connecting to server..."`,
128
+ `streamLoadingComponent`: `"Loading {type} component..."`,
129
+ `streamDashboardLoaded`: `"Dashboard loaded"`, `streamErrorProgress`:
130
+ `"Error: {message}"`, `streamConnectionFailed`: `"Stream connection
131
+ failed"`, `streamRequestFailed`: `"Stream request failed"`,
132
+ `streamEmptyResponse`: `"Response body is null"`, `streamServerSide`:
133
+ `"Streaming UI cannot start on server-side"`, `streamUnknownError`:
134
+ `"Unknown error"`
135
+ - **`locale`**: `"en-US"` — see **Changed**
136
+ - **Unavailable and degraded states shown to end users** —
137
+ `streamServerSideTitle`: `"Streaming unavailable"` (see **Changed**),
138
+ `graphUnavailable`: `"Graph rendering unavailable"`,
139
+ `mapPmtilesUnavailable`: `"PMTiles layer unavailable — the optional
140
+ \"protomaps-leaflet\" peer dependency failed to load or render."`,
141
+ `mapBaseMapStillShown`: `"The base map is still shown."`,
142
+ `chartJsUnavailable`: `"Chart.js is not available. Install chart.js peer
143
+ dependency."`, `chartIframeUnavailable`: `"Interactive chart unavailable
144
+ — install the chart.js peer dependency, or set allowQuickchartFallback to
145
+ use the external quickchart.io renderer."`, `previewInvalidContent`:
146
+ `"[DataPreviewSection] Invalid content format"`. Their text names a peer
147
+ or a config flag, but end users see them, so a host can translate them.
148
+ - **Citation chip tooltip** — `citationViewSource`: `"View source -
149
+ {label}"` (template `{label}`: file name and page)
150
+ - **`ArtifactRenderer` file sizes** — `sizeBytes`: `"{size} B"`,
151
+ `sizeKilobytes`: `"{size} KB"`, `sizeMegabytes`: `"{size} MB"` (the number
152
+ is formatted with `locale`)
153
+
154
+ - **`useStreamingUI({ messages })`** — new optional `messages?:
155
+ Partial<StreamingUIMessages>` on `UseStreamingUIOptions`, with exported
156
+ `DEFAULT_STREAMING_UI_MESSAGES` and `StreamingUIMessages` (root barrel and
157
+ `/hooks`). Covers `initializing`, `connecting`, `loadingComponent`,
158
+ `dashboardLoaded`, `errorProgress`, `connectionFailed`, `requestFailed`,
159
+ `emptyResponse`, `serverSide`, `unknownError`. `StreamingUIRenderer` feeds
160
+ it from the `stream*` `MCPUIStrings` keys through getters (a `messages`
161
+ prop passed directly to the renderer still wins over the context). Every
162
+ other hook in the library (`useAction`, `useAutocomplete`, `useModal`, …)
163
+ is unchanged.
164
+
165
+ - **`CitationCtx.unresolvedLabel?: string`** — new optional field on the
166
+ exported `CitationCtx` interface (`UIResourceRenderer.tsx`). It supplies
167
+ the placeholder `transformCellCitations` keeps in a table cell for a
168
+ citation marker that no `citationMap` resolves (empty map only). Optional,
169
+ so every existing `renderCellValue(value, citationCtx?)` call site keeps
170
+ type-checking; the placeholder now defaults to English (`citationUnresolved`)
171
+ instead of hardcoded French. A second optional field,
172
+ **`CitationCtx.viewSourceLabel?: string`**, carries the default citation
173
+ chip's tooltip template (`citationViewSource`); the table renderer fills
174
+ both from `useMCPUIStrings()`.
175
+
176
+ - **New export `formatMCPUIString(template, vars)`** (root barrel) —
177
+ replaces `{name}` placeholders in a template with `vars[name]`; an
178
+ unrecognized `{placeholder}` is left verbatim rather than throwing or
179
+ rendering `undefined`. It lives in the dependency-free
180
+ `src/utils/format-string.ts` (no imports), so the runtime-free adapters
181
+ use it too, and `MCPUIStringsContext.tsx` re-exports it.
182
+
183
+ - **New `messages` / `labels` options on the runtime-free adapters,
184
+ services and helpers** — these modules cannot read
185
+ `MCPUIStringsProvider` (no `solid-js` import), so their English ships as
186
+ a TRAILING OPTIONAL parameter with an exported default table; every
187
+ existing call site keeps type-checking and behaving identically:
188
+
189
+ - **`connectorResultToUILayout(result, options?)`**
190
+ (`src/adapters/connector.ts`) — `options.messages?:
191
+ Partial<ConnectorAdapterMessages>`. Covers the connector adapter's two
192
+ degraded-state paragraphs: `degradedNotice` (unreadable payload,
193
+ template `{versionSuffix}`), `degradedVersionSuffix` (template
194
+ `{version}`), `versionWarning` (unrecognized schema version, template
195
+ `{version}`, `{expected}`). New exports `ConnectorAdapterMessages` and
196
+ `DEFAULT_CONNECTOR_MESSAGES` from `@seed-ship/mcp-ui-solid/adapters`
197
+ (not the root barrel — no other connector-adapter export is there
198
+ either):
199
+
200
+ ```ts
201
+ import { connectorResultToUILayout } from '@seed-ship/mcp-ui-solid/adapters'
202
+
203
+ connectorResultToUILayout(result, {
204
+ messages: {
205
+ versionWarning: '> ⚠ Schéma connecteur non reconnu (`{version}`, attendu `{expected}`).',
206
+ },
207
+ })
208
+ ```
209
+
210
+ - **`macroRunToScratchpadState(run, options?)` /
211
+ `macroInterrogationToChatPromptConfig(q, options?)`**
212
+ (`src/adapters/macro-run.ts`) — `options.messages?:
213
+ Partial<MacroRunAdapterMessages>`. The real fields are
214
+ `agentSectionTitle` (`"Agent"`), `progressSectionTitle` (`"Progress"`),
215
+ `resultSectionTitle` (`"Result"`), `runAborted` (`"Macro run
216
+ aborted."`), `runFailed` (`"Macro run failed."`), `confirmDefault`
217
+ (`"Please confirm to continue."`). New exports
218
+ `MacroRunAdapterMessages`, `MacroRunAdapterOptions` and
219
+ `DEFAULT_MACRO_RUN_MESSAGES` from `@seed-ship/mcp-ui-solid/adapters`:
220
+
221
+ ```ts
222
+ macroRunToScratchpadState(run, { messages: { resultSectionTitle: 'Résultat' } })
223
+ ```
224
+
225
+ - **`validateFieldValue(value, field, messages?)` /
226
+ `validateFormData(data, fields, messages?)`** (`src/services/validation.ts`)
227
+ — `messages?: Partial<FormValidationMessages>` (13 fields: `required`,
228
+ `mustBeChecked`, `minLength`, `maxLength`, `invalidPattern`,
229
+ `invalidEmail`, `invalidNumber`, `minValue`, `maxValue`, `minDate`,
230
+ `maxDate`, `invalidOption`, `invalidFormat`). New exports
231
+ `validateFieldValue`, `validateFormData`, `FormValidationMessages` and
232
+ `DEFAULT_VALIDATION_MESSAGES` from the root barrel and
233
+ `@seed-ship/mcp-ui-solid/validation` (the two validators were not
234
+ exported from any entry point before). `FormRenderer` feeds
235
+ this from `useMCPUIStrings()` (the `field*` keys above) — a host does
236
+ not normally call `validateFieldValue` directly for that path. The
237
+ STRUCTURAL validators (`validateComponent`, `validateLayout`, …) keep
238
+ their English `ValidationError.message` — see the exclusion policy
239
+ below.
240
+
241
+ - **`graphToDegradedTable` / `mapToDegradedTable` /
242
+ `chartToDegradedTable`** (`src/utils/degraded-projections.ts`) —
243
+ `labels?: Partial<DegradedProjectionLabels>` (`source`, `target`,
244
+ `label`, `node`, `type`, `lat`, `lng`, `info`, `marker`, `feature`,
245
+ `series`). **`chartToDataTable(params, labels?)`**
246
+ (`src/components/chart-data-table.ts`) — `labels?:
247
+ Partial<ChartDataTableLabels>` (`series`, `point`, `label`,
248
+ `seriesName`, `x`, `y`, `r` — the last three are the Chart.js point
249
+ property names the cells mirror, still overridable). New root-barrel
250
+ exports `graphToDegradedTable`, `mapToDegradedTable`,
251
+ `chartToDegradedTable`, `chartToDataTable` (not exported from any entry
252
+ point before), `DegradedProjectionLabels`, `DEGRADED_PROJECTION_LABELS`,
253
+ `ChartDataTableLabels`, `CHART_DATA_TABLE_LABELS`. The renderers pass
254
+ the `degradedCol*` / `chartTable*` keys from `useMCPUIStrings()`.
255
+
256
+ ```ts
257
+ graphToDegradedTable(graph, { source: 'Origine', target: 'Destination' })
258
+ ```
259
+
260
+ - **The chrome-strings guard is now a TypeScript-AST scanner over all of
261
+ `src`.** `scripts/chrome-scan.ts` (outside `src`, not published; `node
262
+ scripts/chrome-scan.ts [root] [--json] [--raw]`) parses every non-test
263
+ source and flags: JSX text; literals reaching a visible attribute, a JSX
264
+ child or the clipboard through `||` / `??`, each ternary branch, template
265
+ spans, `formatMCPUIString`, helper returns, `const` variables and signal
266
+ setters; prose in object properties, `*Label`-style helper returns and
267
+ arrays; French text (accented characters or stopwords); and hardcoded
268
+ BCP-47 locale tags or argument-less `toLocaleString()` calls in
269
+ components. `console.*` / logger / telemetry calls, `onError` payloads and
270
+ thrown errors are skipped by AST context (see **P7** below) — the scanner
271
+ never has to allow-list them individually. The repository's exclusions
272
+ (`ALLOW_LIST`, `SANCTIONED_TABLES`, `SCOPED_EXCLUSIONS`) live in
273
+ `scripts/chrome-scan.policy.ts` and are enforced by
274
+ `mcpui-strings-guard.test.ts` — see **Tests**.
275
+
276
+ - **Runtime pseudo-localization test**, `MCPUIStrings.pseudolocale.test.tsx`
277
+ — see **Tests**.
278
+
279
+ ### Changed
280
+
281
+ - **New `locale` key (default `'en-US'`) drives every number, date and
282
+ collation call the library makes on its own behalf.** `strings.locale` now
283
+ feeds:
284
+ - `UIResourceRenderer` — table sort (`localeCompare`, was hardcoded
285
+ `'fr'`) and the client-side pagination range total (`toLocaleString`,
286
+ was hardcoded `'fr-FR'`), and the tool-error card timestamp
287
+ (`toLocaleString`, was called with no argument at all — the runtime's
288
+ implicit locale, which can differ between SSR and hydration);
289
+ - `DataPreviewSection` — number / currency / date cell formatting and
290
+ sort comparison (were `'fr-FR'` / `'fr'`; the `" EUR"` currency suffix
291
+ itself stays — P4), the page-info row counts (were `'fr-FR'`), and
292
+ percent cells (were `toFixed(1)` + `"%"`, now `Intl.NumberFormat` with
293
+ `style: 'percent'` — identical output in `en-US`);
294
+ - `StreamingUIRenderer` — the metadata panel cost (was `"$"` +
295
+ `toFixed(4)`, now `Intl.NumberFormat` currency USD with a narrow symbol
296
+ — identical output in `en-US`);
297
+ - `ArtifactRenderer` — the file-size number (was `toFixed(1)`);
298
+ - `ScratchpadPanel` — the filter-preview row count and the data-source
299
+ card's `row_count` (were argument-less);
300
+ - `MapRenderer` — `buildPopupContent(feature, popup, allowHtml?, locale?)`
301
+ and `addGeoJSONLayer(..., allowHtml?, locale?)` gain a new trailing
302
+ optional `locale` parameter for the numbers in auto-generated popups
303
+ (was hardcoded `'fr-FR'`).
304
+
305
+ Restore the previous French formatting with
306
+ `<MCPUIStringsProvider strings={{ locale: 'fr-FR' }}>`.
307
+
308
+ `useMCPUIStrings()` always returns a valid tag: an empty or invalid
309
+ `locale` (for example `'not_a_locale'`, which makes `Intl` throw a
310
+ `RangeError`) resolves to `'en-US'`, and a valid one is canonicalized
311
+ (`'fr-fr'` → `'fr-FR'`). The same check is exported as
312
+ `resolveMCPUILocale(locale)`. A locale change re-renders the counts and
313
+ citation wording that depend on it; GeoJSON map popups read it when they
314
+ open, so the map is not rebuilt.
315
+
316
+ Time zones are a separate concern from the locale. Date-only
317
+ `DataPreviewSection` cells (`2026-09-17`) are now formatted in UTC, so the
318
+ server and every viewer show the same calendar date. Date-time cells and the
319
+ tool-error card timestamp are formatted only after mount, in the viewer's
320
+ time zone, because the server cannot know it: server markup shows the raw
321
+ date-time value, then the formatted date replaces it.
322
+
323
+ - **Five more chrome defaults move from French to English**, matching
324
+ every other key (a published library ships no hardcoded non-English
325
+ chrome):
326
+ - `tableSearchPlaceholder`: `"Rechercher dans le tableau..."` → `"Search
327
+ the table..."` (`UIResourceRenderer` table search input; a connector's
328
+ own `tableParams.searchPlaceholder` still wins when set);
329
+ - `verifiedStripLabel`: `"[non vérifié]"` → `"[unverified]"`
330
+ (`VerifiedText` `mode="strip"`);
331
+ - `scratchpadEdit`: `"Modifier"` → `"Edit"` (`ScratchpadPanel`'s
332
+ collapsed auto-submit form edit button);
333
+ - `citationUnresolved`: `"[réf. {id}]"` → `"[ref. {id}]"`, now backed by
334
+ the new `CitationCtx.unresolvedLabel`;
335
+ - `formPrefilledOne` / `formPrefilledMany`: `"{count} champ(s)
336
+ pré-rempli(s) sur {total}"` → `"{count} field(s) pre-filled out of
337
+ {total}"` (`FormRenderer` and `ScratchpadPanel`'s prefill summary).
338
+
339
+ Restore the previous French text for these five, and the connector
340
+ adapter's degraded-state text (also changed from French to English —
341
+ `DEFAULT_CONNECTOR_MESSAGES`, below), with:
342
+
343
+ ```tsx
344
+ <MCPUIStringsProvider
345
+ strings={{
346
+ locale: 'fr-FR',
347
+ tableSearchPlaceholder: 'Rechercher dans le tableau...',
348
+ verifiedStripLabel: '[non vérifié]',
349
+ scratchpadEdit: 'Modifier',
350
+ citationUnresolved: '[réf. {id}]',
351
+ formPrefilledOne: '{count} champ pré-rempli sur {total}',
352
+ formPrefilledMany: '{count} champs pré-remplis sur {total}',
353
+ }}
354
+ >
355
+ <App />
356
+ </MCPUIStringsProvider>
357
+ ```
358
+
359
+ ```ts
360
+ connectorResultToUILayout(result, {
361
+ messages: {
362
+ degradedNotice:
363
+ '### Résultat non rendu\n\nLe résultat du connecteur n\'a pas pu être interprété{versionSuffix}. Cet état explicite remplace une disparition silencieuse du rendu.',
364
+ degradedVersionSuffix: ' (schéma : `{version}`)',
365
+ versionWarning:
366
+ '> ⚠ Schéma connecteur non reconnu (`{version}`, attendu `{expected}`). Le rendu ci-dessous est en mode dégradé.',
367
+ },
368
+ })
369
+ ```
370
+
371
+ - **`StreamingUIRenderer` no longer shows the machine code `ssr` as its
372
+ error heading** when streaming is started during server rendering. It
373
+ renders `streamServerSideTitle` (`"Streaming unavailable"`) instead. The
374
+ hook's `StreamError.error` keeps the code `'ssr'` for consumers that test
375
+ it.
376
+
377
+ - **`ScratchpadPanel`'s feedback badge now shows the option's label**, not
378
+ its machine value (`approve` / `reject` / `comment`); nothing is shown
379
+ after the icon for a free-text comment.
380
+
381
+ - **`MCPActionProvider`'s fallback action error** — when the action
382
+ executor throws a non-`Error` value, `ActionResult.error` (which
383
+ `FormRenderer` displays) now reads `errorUnknown` instead of a hardcoded
384
+ string.
385
+
386
+ ### Exclusion policy
387
+
388
+ Every user-visible chrome string now reads from `MCPUIStrings` (components)
389
+ or an exported `messages`/`labels` option (runtime-free adapters, services,
390
+ helpers, hooks) — enforced by `mcpui-strings-guard.test.ts`: anything the
391
+ scanner flags must become a key or an option, or be allow-listed here under
392
+ one of P1–P8.
393
+
394
+ - **P1 — keyboard key caps inside `<kbd>`.** `AutocompleteDropdown`'s
395
+ `<kbd>Enter</kbd>` and `<kbd>Esc</kbd>` — the physical key reads "Enter"
396
+ whatever the UI language. The surrounding hint prose IS localized
397
+ (`autocompleteHintNavigate` / `autocompleteHintSelect` /
398
+ `autocompleteHintDismiss`).
399
+ - **P2 — legal attribution wording.** `MapRenderer`'s `"OpenStreetMap</a>
400
+ contributors"` tile attribution — exact wording required by the ODbL. A
401
+ host overrides the whole notice via `params.attribution` for another
402
+ language.
403
+ - **P3 — developer diagnostics** that name an npm package, a peer
404
+ dependency or a config flag; bracketed `[Component] …` messages;
405
+ debug-only panels behind an explicit debug flag; developer-misuse errors;
406
+ and the structural payload-schema diagnostics of `services/validation.ts`:
407
+ - `GraphRenderer`'s install hint under the localized
408
+ `graphUnavailable` heading: `"Install"` / `"@antv/g6"` / `"peer
409
+ dependency to render"` / `"type: \"graph\""` / `"components."` — it
410
+ names the missing optional `@antv/g6` peer, for whoever installs the
411
+ host.
412
+ - `RenderContext`'s `'Component "'` / `'" cannot be rendered outside of
413
+ UIResourceRenderer'` — a developer-misuse error (a renderer used
414
+ outside `<UIResourceRenderer>`).
415
+ - `ScratchpadPanel`'s debug overlay (`| ev:`, `| sec:`, `| last:`,
416
+ behind the `debugOverlay` prop) and its `FormDebugTrace` panel (behind
417
+ the `debugTrace` prop) — both mirror raw server/event keys verbatim, for
418
+ developers.
419
+ - `services/validation.ts`'s structural validators — `mapZodIssuesToErrors`,
420
+ `validateGridPosition`, `validateChartComponent`, `validateTableComponent`,
421
+ `validatePayloadSize`, `validateIframeDomain`, `validateComponent`,
422
+ `validateLayout` — their `ValidationError.message` quotes a payload
423
+ path (e.g. `params.data.datasets[0]`) and is addressed to whoever
424
+ produced the payload, not to the end user. The validation CARD chrome
425
+ around them (`validationError`, `validationWarning`,
426
+ `validationUnknownError`) IS localized; the end-user form messages of
427
+ `validateFieldValue` / `validateFormData` ARE localized through
428
+ `DEFAULT_VALIDATION_MESSAGES`.
429
+ - **P4 — machine tokens**: file-format acronyms, HTTP verbs, unit symbols,
430
+ ISO currency codes, and chart point property names. `DataPreviewSection`'s
431
+ `"CSV"` / `"JSON"` export-button glyphs (their `title` attributes,
432
+ `exportCsvRows` / `exportJsonRows`, ARE localized) and its `" EUR"`
433
+ currency suffix; `"ms"` after execution times and durations
434
+ (`FooterRenderer`, `StreamingUIRenderer`, `ScratchpadPanel`); and
435
+ `chartToDataTable`'s `x` / `y` / `r` column headers (the Chart.js point
436
+ property names the cells mirror — still overridable through the
437
+ `labels` parameter).
438
+ - **P5 — pure module functions with a documented render override.** No
439
+ occurrence remains: the default citation chip's tooltip used to be the
440
+ only one and is now localized (`citationViewSource`, passed through
441
+ `CitationCtx.viewSourceLabel`). The item stays in the policy for future
442
+ helpers.
443
+ - **P6 — components with their own documented `labels`/`messages` prop.**
444
+ `PresentationFeedback`'s `DEFAULT_PRESENTATION_FEEDBACK_LABELS` — the
445
+ component documents its own `labels` prop
446
+ (`<PresentationFeedback labels={{ prompt: '…' }} />`) and does not read
447
+ `MCPUIStringsProvider`. (`DEFAULT_CONNECTOR_MESSAGES`,
448
+ `DEFAULT_MACRO_RUN_MESSAGES`, `DEFAULT_VALIDATION_MESSAGES`,
449
+ `DEGRADED_PROJECTION_LABELS` and `CHART_DATA_TABLE_LABELS` are the same
450
+ kind of sanctioned default table for a `messages`/`labels` option — see
451
+ **Added**.)
452
+ - **P7 — strings the library never renders itself.** Hook-level errors
453
+ returned to the consumer (`useAction`'s `"Max retries (…) exceeded"` /
454
+ `"Action cancelled by onBefore callback"`, `useAutocomplete`'s `"Unknown
455
+ error"`); `props.onError` payloads (`"Chart rendering failed"`,
456
+ `"Component validation failed"`, `"Video failed to load"`); and
457
+ `console.*` / logger / telemetry-only strings. A consumer that reads them
458
+ chooses how to display them. One edge case: the SSR stub executor's
459
+ `"Actions not available server-side"` is an `ActionResult.error` that
460
+ `FormRenderer` would display, but a form cannot be submitted during
461
+ server rendering, so it never reaches the DOM in practice.
462
+ - **P8 — LLM-facing schema descriptions, example payloads, comments and
463
+ JSDoc.** `services/component-registry.ts` in full, and the `plugins/`
464
+ system prompts — a catalogue of JSON-schema descriptions and example
465
+ payloads shown to the model; translating it would teach the model to
466
+ emit non-English payloads.
467
+
468
+ Also out of scope (not i18n): the auto-footer's `poweredBy: 'Deposium'`
469
+ brand string (pre-existing since v1.2.0). Payload/content strings in
470
+ general (`params.title`, `action.label`, and similar) remain the
471
+ producing MCP server's responsibility — this sweep only touches the
472
+ library's own chrome.
473
+
474
+ ### Tests
475
+
476
+ - **`mcpui-strings-guard.test.ts` — AST-based chrome scanner.** Runs
477
+ `scanChrome()` (`scripts/chrome-scan.ts`) over every non-test source under
478
+ `src` and asserts zero unallowed findings. Separately asserts: every
479
+ `ALLOW_LIST` entry still matches a real finding (a fixed literal that no
480
+ longer exists fails the build instead of silently going stale); every
481
+ `SCOPED_EXCLUSIONS` function still exists in its file; every
482
+ `SANCTIONED_TABLES` entry is still exported and non-empty; every entry
483
+ across all three names the policy item (P1–P8) it invokes; and no
484
+ sanctioned table or scoped-exclusion function lets French text or a
485
+ hardcoded locale tag through. A second `describe` block carries
486
+ non-vacuity fixtures — one small source snippet per finding class the
487
+ scanner understands (JSX text, attribute literal, ternary branch,
488
+ template span, helper return, signal setter, prose array/object
489
+ property, arrays rendered item by item through `<For>` or `.map()`,
490
+ French text including single distinctive words, hardcoded locale) —
491
+ asserting the scanner flags
492
+ each one, and a matching "does not flag" fixture per skipped AST context
493
+ (`console.*`, `onError`, thrown errors).
494
+ - **`MCPUIStrings.pseudolocale.test.tsx` — runtime pseudo-localization.**
495
+ Mounts the renderers (`UIResourceRenderer` layouts — table, chart, map,
496
+ graph, form, gallery, video, code, carousel, action, artifact, modal,
497
+ error and validation states; `DataPreviewSection`; `ScratchpadPanel`
498
+ sections and statuses; `ChatPrompt`; `FormRenderer`; `StreamingUIRenderer`;
499
+ `GenerativeUIErrorBoundary`; `VerifiedText`; the agent components;
500
+ `AutocompleteDropdown`; `GraphRenderer`'s export menu;
501
+ `EditableUIResourceRenderer`) with a `<MCPUIStringsProvider>` whose
502
+ strings are `⟦key {placeholders}⟧` markers and with CJK-only payload
503
+ content, under `locale: 'fr-FR'`. Walks `document.body` including
504
+ portals and accessible attributes (`aria-label`, `title`, `alt`), and
505
+ separately asserts the tool-error card's clipboard text. Fails on any
506
+ Latin chrome text left over. It backs up the scanner's known blind spots:
507
+ prose stored under machine-looking keys such as `name`, and values passed
508
+ to another file's component props.
509
+ - **`mcpui-strings-defaults.test.ts`** pins every `DEFAULT_MCPUI_STRINGS`
510
+ value, so a default cannot drift silently.
511
+
512
+ ### Known follow-ups
513
+
514
+ - The auto-footer's hardcoded `poweredBy: 'Deposium'` brand string is not
515
+ i18n and is out of scope for this release (pre-existing since v1.2.0).
516
+ - `DataPreviewSection` appends `" EUR"` to every `currency` cell whatever
517
+ the data's actual currency (pre-existing; a currency code belongs in the
518
+ payload, not in the library).
519
+ - `macroRunToScratchpadState` passes a whole `UIComponent` as the content of
520
+ `data_preview` / `chart` / `map` sections, while those sections expect the
521
+ component's params (pre-existing since the MacroRun adapters shipped). A
522
+ table result therefore shows `previewInvalidContent` in the panel.
523
+ - Download filenames (`chart.png`, `table-*.csv`, graph export stems) stay
524
+ in English — they are files, not DOM text, so the policy treats them as
525
+ P4 machine tokens.
526
+
527
+ ## [6.19.1] - 2026-09-16
528
+
529
+ ### Fixed
530
+
531
+ - **`FeedbackInline` accessible names were hardcoded English.** The two rating
532
+ buttons carried `aria-label="Mark response as useful"` /
533
+ `"Mark response as not useful"` regardless of `MCPUIStringsProvider`, while
534
+ their tooltips already used `strings.feedbackUseful` /
535
+ `strings.feedbackNotUseful`. Both attributes now read the same strings, so
536
+ screen readers get the localized name. Default English accessible names
537
+ therefore become `"Useful"` / `"Not useful"`; the stable hook
538
+ `data-feedback-inline-rating="positive" | "negative"` is unchanged.
539
+
8
540
  ## [6.19.0] - 2026-09-16
9
541
 
10
542
  ### Security