gemi 0.53.0 → 0.54.1

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 (239) hide show
  1. package/dist/app/index.js +2 -2
  2. package/dist/app/index.js.map +1 -1
  3. package/dist/bin/gemi.js +1456 -5
  4. package/dist/bin/gemi.js.map +9 -5
  5. package/dist/broadcasting/index.js +1 -1
  6. package/dist/bun/plugin.js +2 -2
  7. package/dist/bun/plugin.js.map +1 -1
  8. package/dist/bun/preload.js +2 -2
  9. package/dist/bun/preload.js.map +1 -1
  10. package/dist/{chunk-msz8rngs.js → chunk-004bcmsa.js} +2 -2
  11. package/dist/chunk-004bcmsa.js.map +10 -0
  12. package/dist/chunk-03f4fkh5.js +5 -0
  13. package/dist/{chunk-9279y4af.js.map → chunk-03f4fkh5.js.map} +2 -2
  14. package/dist/chunk-07t0dmdg.js +4 -0
  15. package/dist/{chunk-faa987e4.js.map → chunk-07t0dmdg.js.map} +2 -2
  16. package/dist/{chunk-cg53h5ht.js → chunk-0weeq0ke.js} +2 -2
  17. package/dist/{chunk-cg53h5ht.js.map → chunk-0weeq0ke.js.map} +1 -1
  18. package/dist/chunk-113khwbw.js +5 -0
  19. package/dist/{chunk-2qn472j4.js.map → chunk-113khwbw.js.map} +1 -1
  20. package/dist/{chunk-tmk4zfz9.js → chunk-1sh6kqjn.js} +3 -3
  21. package/dist/{chunk-tmk4zfz9.js.map → chunk-1sh6kqjn.js.map} +1 -1
  22. package/dist/{chunk-2gw6cyyj.js → chunk-1snh7yc4.js} +2 -2
  23. package/dist/{chunk-2gw6cyyj.js.map → chunk-1snh7yc4.js.map} +1 -1
  24. package/dist/{chunk-ebcgdv00.js → chunk-2pt6kyn9.js} +3 -3
  25. package/dist/{chunk-ebcgdv00.js.map → chunk-2pt6kyn9.js.map} +1 -1
  26. package/dist/{chunk-zhsaz9cr.js → chunk-3bw1jk21.js} +1 -1
  27. package/dist/chunk-4qkzdyj7.js +4 -0
  28. package/dist/{chunk-0h3jr9d9.js.map → chunk-4qkzdyj7.js.map} +1 -1
  29. package/dist/{chunk-d1ahbza9.js → chunk-50vm7x98.js} +3 -3
  30. package/dist/{chunk-d1ahbza9.js.map → chunk-50vm7x98.js.map} +1 -1
  31. package/dist/{chunk-qyaqg07q.js → chunk-6j1z2cqt.js} +2 -2
  32. package/dist/{chunk-qyaqg07q.js.map → chunk-6j1z2cqt.js.map} +1 -1
  33. package/dist/chunk-6rhebm18.js +5 -0
  34. package/dist/chunk-6rhebm18.js.map +10 -0
  35. package/dist/{chunk-rq770c71.js → chunk-71m47kad.js} +2 -2
  36. package/dist/{chunk-rq770c71.js.map → chunk-71m47kad.js.map} +1 -1
  37. package/dist/{chunk-0h3jr9d9.js → chunk-7f5ad759.js} +2 -2
  38. package/dist/{chunk-4e61qbp4.js.map → chunk-7f5ad759.js.map} +1 -1
  39. package/dist/chunk-85av4ncy.js +4 -0
  40. package/dist/{chunk-3d3nmr5g.js.map → chunk-85av4ncy.js.map} +2 -2
  41. package/dist/{chunk-23g7qdpg.js → chunk-9taz1h3t.js} +3 -3
  42. package/dist/{chunk-23g7qdpg.js.map → chunk-9taz1h3t.js.map} +1 -1
  43. package/dist/{chunk-ppt296ye.js → chunk-agabw2w1.js} +2 -2
  44. package/dist/{chunk-ppt296ye.js.map → chunk-agabw2w1.js.map} +1 -1
  45. package/dist/{chunk-092pj2j2.js → chunk-bb3zvxsf.js} +3 -3
  46. package/dist/{chunk-092pj2j2.js.map → chunk-bb3zvxsf.js.map} +1 -1
  47. package/dist/{chunk-h7jv3ame.js → chunk-br8ten26.js} +2 -2
  48. package/dist/{chunk-h7jv3ame.js.map → chunk-br8ten26.js.map} +1 -1
  49. package/dist/{chunk-4e61qbp4.js → chunk-bzhtymvv.js} +2 -2
  50. package/dist/{chunk-8p6rqegw.js.map → chunk-bzhtymvv.js.map} +1 -1
  51. package/dist/{chunk-68w225rv.js → chunk-c0wcsmpj.js} +2 -2
  52. package/dist/{chunk-68w225rv.js.map → chunk-c0wcsmpj.js.map} +1 -1
  53. package/dist/{chunk-xsmt86n3.js → chunk-c22vcxty.js} +2 -2
  54. package/dist/{chunk-xsmt86n3.js.map → chunk-c22vcxty.js.map} +1 -1
  55. package/dist/{chunk-q09mmr05.js → chunk-cz3szqhq.js} +2 -2
  56. package/dist/{chunk-q09mmr05.js.map → chunk-cz3szqhq.js.map} +1 -1
  57. package/dist/{chunk-69w4egkg.js → chunk-dwx2y7br.js} +4 -4
  58. package/dist/{chunk-69w4egkg.js.map → chunk-dwx2y7br.js.map} +1 -1
  59. package/dist/{chunk-2sfz64xh.js → chunk-dxw8k6f1.js} +2 -2
  60. package/dist/{chunk-2sfz64xh.js.map → chunk-dxw8k6f1.js.map} +1 -1
  61. package/dist/chunk-e3mggavt.js +5 -0
  62. package/dist/chunk-e3mggavt.js.map +11 -0
  63. package/dist/{chunk-1pqfmw5h.js → chunk-efp54183.js} +3 -3
  64. package/dist/{chunk-1pqfmw5h.js.map → chunk-efp54183.js.map} +1 -1
  65. package/dist/{chunk-j1knf8gv.js → chunk-efsk1wy0.js} +3 -3
  66. package/dist/{chunk-j1knf8gv.js.map → chunk-efsk1wy0.js.map} +1 -1
  67. package/dist/{chunk-t4n25km9.js → chunk-f13f68c0.js} +2 -2
  68. package/dist/{chunk-t4n25km9.js.map → chunk-f13f68c0.js.map} +1 -1
  69. package/dist/{chunk-vv72kw74.js → chunk-f418jh9k.js} +2 -2
  70. package/dist/{chunk-vv72kw74.js.map → chunk-f418jh9k.js.map} +1 -1
  71. package/dist/chunk-f4e7fh95.js +17 -0
  72. package/dist/chunk-f4e7fh95.js.map +14 -0
  73. package/dist/{chunk-ewgv1j8q.js → chunk-fcqc3e3r.js} +2 -2
  74. package/dist/{chunk-ewgv1j8q.js.map → chunk-fcqc3e3r.js.map} +1 -1
  75. package/dist/{chunk-3y9nf09k.js → chunk-g5tj10p8.js} +2 -2
  76. package/dist/{chunk-3y9nf09k.js.map → chunk-g5tj10p8.js.map} +1 -1
  77. package/dist/chunk-gn9zjgep.js +5 -0
  78. package/dist/chunk-gn9zjgep.js.map +10 -0
  79. package/dist/chunk-h6xsczr8.js +6 -0
  80. package/dist/{chunk-ffre1z8s.js.map → chunk-h6xsczr8.js.map} +2 -2
  81. package/dist/{chunk-5s45prj5.js → chunk-h7mcwfg5.js} +4 -4
  82. package/dist/{chunk-5s45prj5.js.map → chunk-h7mcwfg5.js.map} +1 -1
  83. package/dist/chunk-hk067634.js +4 -0
  84. package/dist/{chunk-vnjvd82s.js.map → chunk-hk067634.js.map} +2 -2
  85. package/dist/{chunk-qx6sahe0.js → chunk-hrrmxreg.js} +2 -2
  86. package/dist/{chunk-qx6sahe0.js.map → chunk-hrrmxreg.js.map} +1 -1
  87. package/dist/{chunk-p22rkf1g.js → chunk-jb022m7n.js} +2 -2
  88. package/dist/{chunk-p22rkf1g.js.map → chunk-jb022m7n.js.map} +1 -1
  89. package/dist/chunk-jb2nst6v.js +4 -0
  90. package/dist/{chunk-6scjrbw7.js.map → chunk-jb2nst6v.js.map} +2 -2
  91. package/dist/{chunk-kxzwem3g.js → chunk-jdgvdddd.js} +2 -2
  92. package/dist/{chunk-kxzwem3g.js.map → chunk-jdgvdddd.js.map} +1 -1
  93. package/dist/{chunk-2yth3kk2.js → chunk-jp4pf3yt.js} +4 -4
  94. package/dist/{chunk-2yth3kk2.js.map → chunk-jp4pf3yt.js.map} +1 -1
  95. package/dist/chunk-k14dmqwh.js +5 -0
  96. package/dist/{chunk-92793zh4.js.map → chunk-k14dmqwh.js.map} +4 -3
  97. package/dist/{chunk-tkv6cw94.js → chunk-k8endm5j.js} +3 -3
  98. package/dist/{chunk-tkv6cw94.js.map → chunk-k8endm5j.js.map} +1 -1
  99. package/dist/{chunk-cmq5t8p9.js → chunk-kv2ep453.js} +3 -3
  100. package/dist/{chunk-cmq5t8p9.js.map → chunk-kv2ep453.js.map} +1 -1
  101. package/dist/{chunk-z4q1ty6w.js → chunk-kz39hphm.js} +3 -3
  102. package/dist/{chunk-z4q1ty6w.js.map → chunk-kz39hphm.js.map} +1 -1
  103. package/dist/{chunk-kaxvw75w.js → chunk-ms8qd7da.js} +3 -3
  104. package/dist/{chunk-kaxvw75w.js.map → chunk-ms8qd7da.js.map} +1 -1
  105. package/dist/{chunk-ttzkn1qd.js → chunk-n1tkn8gv.js} +2 -2
  106. package/dist/{chunk-ttzkn1qd.js.map → chunk-n1tkn8gv.js.map} +1 -1
  107. package/dist/chunk-n382ygnp.js +81 -0
  108. package/dist/{chunk-ear03axe.js.map → chunk-n382ygnp.js.map} +8 -6
  109. package/dist/chunk-nncwsdzz.js +5 -0
  110. package/dist/chunk-nncwsdzz.js.map +10 -0
  111. package/dist/{chunk-7s1g3v1y.js → chunk-pgjk5ft3.js} +3 -3
  112. package/dist/{chunk-7s1g3v1y.js.map → chunk-pgjk5ft3.js.map} +1 -1
  113. package/dist/{chunk-07jtzbf0.js → chunk-qwbzd5w8.js} +2 -2
  114. package/dist/{chunk-07jtzbf0.js.map → chunk-qwbzd5w8.js.map} +2 -2
  115. package/dist/{chunk-tztqkat2.js → chunk-r06rxn19.js} +2 -2
  116. package/dist/{chunk-tztqkat2.js.map → chunk-r06rxn19.js.map} +1 -1
  117. package/dist/chunk-r9z5rrk0.js +4 -0
  118. package/dist/{chunk-1ab1ptq5.js.map → chunk-r9z5rrk0.js.map} +2 -2
  119. package/dist/{chunk-h5g05qwb.js → chunk-s6e7cvek.js} +2 -2
  120. package/dist/{chunk-h5g05qwb.js.map → chunk-s6e7cvek.js.map} +1 -1
  121. package/dist/{chunk-qjnv2rkh.js → chunk-sqp7kn7h.js} +3 -3
  122. package/dist/{chunk-qjnv2rkh.js.map → chunk-sqp7kn7h.js.map} +1 -1
  123. package/dist/{chunk-mt2755rs.js → chunk-w6gb9gc5.js} +3 -3
  124. package/dist/{chunk-mt2755rs.js.map → chunk-w6gb9gc5.js.map} +1 -1
  125. package/dist/{chunk-ha7n1c94.js → chunk-xxw0gz4q.js} +2 -2
  126. package/dist/{chunk-ha7n1c94.js.map → chunk-xxw0gz4q.js.map} +1 -1
  127. package/dist/{chunk-fbp5vapa.js → chunk-zckj6bs6.js} +3 -3
  128. package/dist/{chunk-fbp5vapa.js.map → chunk-zckj6bs6.js.map} +2 -2
  129. package/dist/chunks/{ThemeProvider-CTX9LOFC.js → ThemeProvider-Bk1eZymb.js} +186 -3
  130. package/dist/chunks/ThemeProvider-Bk1eZymb.js.map +1 -0
  131. package/dist/client/ComponentContext.d.ts.map +1 -1
  132. package/dist/client/DictionarySinkContext.d.ts +10 -0
  133. package/dist/client/DictionarySinkContext.d.ts.map +1 -0
  134. package/dist/client/createRoot.d.ts.map +1 -1
  135. package/dist/client/index.d.ts +2 -0
  136. package/dist/client/index.d.ts.map +1 -1
  137. package/dist/client/index.js +231 -20
  138. package/dist/client/index.js.map +1 -1
  139. package/dist/client/useDictionary.d.ts +34 -0
  140. package/dist/client/useDictionary.d.ts.map +1 -0
  141. package/dist/client/useDictionary.test-d.d.ts +2 -0
  142. package/dist/client/useDictionary.test-d.d.ts.map +1 -0
  143. package/dist/client/useLocale.d.ts.map +1 -1
  144. package/dist/client/useTranslator.d.ts +8 -0
  145. package/dist/client/useTranslator.d.ts.map +1 -1
  146. package/dist/config/index.js +1 -1
  147. package/dist/console/run.js +2 -2
  148. package/dist/console/run.js.map +1 -1
  149. package/dist/container/index.js +2 -2
  150. package/dist/container/index.js.map +1 -1
  151. package/dist/database/index.js +2 -2
  152. package/dist/database/index.js.map +1 -1
  153. package/dist/email/index.js +2 -2
  154. package/dist/email/index.js.map +1 -1
  155. package/dist/facades/Lang.d.ts.map +1 -1
  156. package/dist/facades/index.js +2 -2
  157. package/dist/facades/index.js.map +1 -1
  158. package/dist/foundation/index.js +2 -2
  159. package/dist/foundation/index.js.map +1 -1
  160. package/dist/http/index.js +2 -2
  161. package/dist/http/index.js.map +1 -1
  162. package/dist/i18n/Dictionary.d.ts +7 -0
  163. package/dist/i18n/Dictionary.d.ts.map +1 -1
  164. package/dist/i18n/I18nRouter.d.ts.map +1 -1
  165. package/dist/i18n/Translator.d.ts +12 -0
  166. package/dist/i18n/Translator.d.ts.map +1 -1
  167. package/dist/i18n/config.d.ts +6 -0
  168. package/dist/i18n/config.d.ts.map +1 -1
  169. package/dist/i18n/defineDictionary.d.ts +65 -0
  170. package/dist/i18n/defineDictionary.d.ts.map +1 -0
  171. package/dist/i18n/dictionaryRegistry.d.ts +85 -0
  172. package/dist/i18n/dictionaryRegistry.d.ts.map +1 -0
  173. package/dist/i18n/dictionaryRuntime.d.ts +16 -0
  174. package/dist/i18n/dictionaryRuntime.d.ts.map +1 -0
  175. package/dist/i18n/dictionaryRuntime.js +4 -0
  176. package/dist/i18n/dictionaryRuntime.js.map +9 -0
  177. package/dist/i18n/dictionaryShape.d.ts +66 -0
  178. package/dist/i18n/dictionaryShape.d.ts.map +1 -0
  179. package/dist/i18n/dictionarySink.d.ts +31 -0
  180. package/dist/i18n/dictionarySink.d.ts.map +1 -0
  181. package/dist/i18n/index.d.ts +3 -0
  182. package/dist/i18n/index.d.ts.map +1 -1
  183. package/dist/i18n/index.js +2 -2
  184. package/dist/i18n/index.js.map +5 -4
  185. package/dist/i18n/translate.d.ts +21 -0
  186. package/dist/i18n/translate.d.ts.map +1 -0
  187. package/dist/internal/gemiExternals.d.ts +1 -1
  188. package/dist/internal/gemiExternals.d.ts.map +1 -1
  189. package/dist/kernel/index.js +2 -2
  190. package/dist/kernel/index.js.map +2 -2
  191. package/dist/orm/index.js +2 -2
  192. package/dist/orm/index.js.map +2 -2
  193. package/dist/server/index.js +2 -2
  194. package/dist/server/index.js.map +1 -1
  195. package/dist/services/index.js +4 -4
  196. package/dist/services/index.js.map +2 -2
  197. package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
  198. package/dist/services/router/streamQueryInjection.d.ts +9 -1
  199. package/dist/services/router/streamQueryInjection.d.ts.map +1 -1
  200. package/dist/support/index.js +2 -2
  201. package/dist/support/index.js.map +1 -1
  202. package/dist/testing/index.js +1 -1
  203. package/dist/vite/__vite-browser-external-S5EYS4bz.mjs +7 -0
  204. package/dist/vite/api_vite-DSBC5Nzy.mjs +5 -0
  205. package/dist/vite/browser-DFEUWTkA.mjs +6086 -0
  206. package/dist/vite/build-C0lmnz6d.mjs +5326 -0
  207. package/dist/vite/index.mjs +1349 -1
  208. package/dist/vite/lib-TT6NqN6b.mjs +363 -0
  209. package/dist/vite/lib-U4DF62jt.mjs +48846 -0
  210. package/dist/vite/main-Drp2rSLR.mjs +2123 -0
  211. package/dist/vite/node-BgyIm-M7.mjs +17799 -0
  212. package/dist/vite/node-yGkKTK1d.mjs +789 -0
  213. package/dist/vite/postcss-hCXrlC4m.mjs +3515 -0
  214. package/dist/vite/postcss-import-rYEe0OKc.mjs +448 -0
  215. package/dist/vite/prompt--dNycKSZ-BmZ8jzP_.mjs +889 -0
  216. package/dist/vite/rolldown-runtime-B4lejLz5.mjs +37 -0
  217. package/package.json +3 -1
  218. package/dist/chunk-1ab1ptq5.js +0 -4
  219. package/dist/chunk-2qn472j4.js +0 -5
  220. package/dist/chunk-3d3nmr5g.js +0 -4
  221. package/dist/chunk-6scjrbw7.js +0 -4
  222. package/dist/chunk-88pq4gmf.js +0 -5
  223. package/dist/chunk-88pq4gmf.js.map +0 -10
  224. package/dist/chunk-8p6rqegw.js +0 -4
  225. package/dist/chunk-92793zh4.js +0 -5
  226. package/dist/chunk-9279y4af.js +0 -5
  227. package/dist/chunk-bq4w14a6.js +0 -5
  228. package/dist/chunk-bq4w14a6.js.map +0 -10
  229. package/dist/chunk-ear03axe.js +0 -81
  230. package/dist/chunk-faa987e4.js +0 -4
  231. package/dist/chunk-ffre1z8s.js +0 -6
  232. package/dist/chunk-msz8rngs.js.map +0 -10
  233. package/dist/chunk-vnjvd82s.js +0 -4
  234. package/dist/chunk-xw44bwnh.js +0 -5
  235. package/dist/chunk-xw44bwnh.js.map +0 -11
  236. package/dist/chunk-y4djde42.js +0 -5
  237. package/dist/chunk-y4djde42.js.map +0 -11
  238. package/dist/chunks/ThemeProvider-CTX9LOFC.js.map +0 -1
  239. /package/dist/{chunk-zhsaz9cr.js.map → chunk-3bw1jk21.js.map} +0 -0
@@ -2252,6 +2252,184 @@ async function readSettledRoutePayload(response) {
2252
2252
  return envelope;
2253
2253
  }
2254
2254
  //#endregion
2255
+ //#region i18n/dictionaryRegistry.ts
2256
+ /**
2257
+ * Parked on `globalThis` rather than in module scope, because this module gets
2258
+ * bundled more than once and the copies have to agree.
2259
+ *
2260
+ * gemi ships `gemi/client` from one Vite lib build and `gemi/dictionary` from a
2261
+ * separate Bun build, an SSR view graph externalizes some gemi subpaths and
2262
+ * bundles others, and a dictionary imported by both a view and a controller is
2263
+ * evaluated on both sides. Every one of those splits would otherwise produce a
2264
+ * second registry: views would register into one Map while the view router
2265
+ * preloaded and snapshotted from another, and the hydration payload would come
2266
+ * out empty. Module identity is not something this can depend on; a global key
2267
+ * is.
2268
+ */
2269
+ var GLOBAL_KEY = "__GEMI_DICTIONARY_REGISTRY__";
2270
+ var state = globalThis[GLOBAL_KEY] ??= {
2271
+ registry: /* @__PURE__ */ new Map(),
2272
+ resolved: /* @__PURE__ */ new Map(),
2273
+ inFlight: /* @__PURE__ */ new Map(),
2274
+ degraded: /* @__PURE__ */ new Map(),
2275
+ order: [],
2276
+ warmed: /* @__PURE__ */ new Map(),
2277
+ activeLocale: null
2278
+ };
2279
+ var { registry, resolved, inFlight, degraded, order, warmed } = state;
2280
+ function cacheKey(id, locale) {
2281
+ return `${id}\0${locale}`;
2282
+ }
2283
+ function registerDictionary(entry) {
2284
+ if (registry.has(entry.id)) return;
2285
+ registry.set(entry.id, entry);
2286
+ order.push(entry.id);
2287
+ }
2288
+ /** A marker for "everything registered so far", for `preloadDictionaries`. */
2289
+ function dictionaryRegistrationMark() {
2290
+ return order.length;
2291
+ }
2292
+ function getResolved(id, locale) {
2293
+ return resolved.get(id)?.get(locale);
2294
+ }
2295
+ function putResolved(id, locale, strings) {
2296
+ let byLocale = resolved.get(id);
2297
+ if (!byLocale) {
2298
+ byLocale = /* @__PURE__ */ new Map();
2299
+ resolved.set(id, byLocale);
2300
+ }
2301
+ byLocale.set(locale, strings);
2302
+ }
2303
+ /**
2304
+ * Load one dictionary's locale, de-duplicating concurrent callers. Returns the
2305
+ * strings directly (not a promise) when they are already resolved, so the hook
2306
+ * can take a synchronous path without a microtask hop.
2307
+ */
2308
+ function loadDictionary(id, locale) {
2309
+ const already = getResolved(id, locale);
2310
+ if (already) return already;
2311
+ const key = cacheKey(id, locale);
2312
+ const pending = inFlight.get(key);
2313
+ if (pending) return pending;
2314
+ const entry = registry.get(id);
2315
+ if (!entry) throw new Error(`Unknown dictionary "${id}". A dictionary must be created with defineDictionary() and its module must have been evaluated before it is read.`);
2316
+ const result = entry.load(locale);
2317
+ if (!(result instanceof Promise)) {
2318
+ putResolved(id, locale, result);
2319
+ return result;
2320
+ }
2321
+ const promise = result.then((strings) => {
2322
+ putResolved(id, locale, strings);
2323
+ inFlight.delete(key);
2324
+ return strings;
2325
+ }, (err) => {
2326
+ inFlight.delete(key);
2327
+ throw err;
2328
+ });
2329
+ inFlight.set(key, promise);
2330
+ return promise;
2331
+ }
2332
+ /**
2333
+ * The same load, but as something safe to hand React's `use()`.
2334
+ *
2335
+ * A rejecting promise passed to `use()` rethrows during render, which unmounts
2336
+ * the whole route into its error boundary — or, before the shell is ready,
2337
+ * fails the server render outright. A missing locale chunk is a routine event
2338
+ * (a browser holding stale HTML after a rolling deploy requests a hashed
2339
+ * filename that no longer exists), and the deprecated `useTranslator` degraded
2340
+ * every i18n failure to rendering the raw key. This keeps that behaviour: the
2341
+ * returned promise resolves to no strings, and the per-key lookup in
2342
+ * `useDictionary` then logs and falls back to the key.
2343
+ *
2344
+ * The degraded promise is cached because `use()` requires a stable reference —
2345
+ * a fresh `.then()` per render would suspend forever. It is only consulted
2346
+ * after `getResolved` misses, so a later successful load supersedes it without
2347
+ * needing to be evicted.
2348
+ */
2349
+ function loadDictionaryForRender(id, locale) {
2350
+ const already = getResolved(id, locale);
2351
+ if (already) return already;
2352
+ const key = cacheKey(id, locale);
2353
+ const cached = degraded.get(key);
2354
+ if (cached) return cached;
2355
+ const result = loadDictionary(id, locale);
2356
+ if (!(result instanceof Promise)) return result;
2357
+ const safe = result.then((strings) => strings, (err) => {
2358
+ console.error(`Failed to load dictionary ${id} for locale ${locale}; rendering keys instead.`, err);
2359
+ return EMPTY_STRINGS;
2360
+ });
2361
+ degraded.set(key, safe);
2362
+ return safe;
2363
+ }
2364
+ var EMPTY_STRINGS = {};
2365
+ /**
2366
+ * Warm dictionaries for `locale`, so a subsequent render reads them
2367
+ * synchronously instead of suspending.
2368
+ *
2369
+ * With a `mark` — the value taken *before* importing a view module — only that
2370
+ * view's newly announced dictionaries are loaded. That is the client's use: it
2371
+ * knows exactly which chunk just arrived.
2372
+ *
2373
+ * Without one, it resumes from where this locale last got to. The server calls
2374
+ * it per request and has no mark to give (view modules were imported long
2375
+ * before the request arrived), so a plain scan from zero would walk every
2376
+ * dictionary in the app on every request — re-deriving the per-request cost this
2377
+ * whole change exists to remove, just with a smaller constant.
2378
+ *
2379
+ * An empty `locale` means the app configured none, and each dictionary is warmed
2380
+ * under its own source language — the same key `useDictionary` will ask for, so
2381
+ * the warmed entry is the one the render actually reads.
2382
+ *
2383
+ * Failures are swallowed: a dictionary that cannot load should surface at the
2384
+ * component that actually reads it, where the error names the key, rather than
2385
+ * take down an unrelated navigation.
2386
+ */
2387
+ async function preloadDictionaries(locale, mark) {
2388
+ const from = mark ?? warmed.get(locale) ?? 0;
2389
+ const ids = order.slice(from);
2390
+ if (ids.length === 0) return;
2391
+ const settled = await Promise.all(ids.map(async (id) => {
2392
+ try {
2393
+ await loadDictionary(id, localeFor(id, locale));
2394
+ return true;
2395
+ } catch {
2396
+ return false;
2397
+ }
2398
+ }));
2399
+ if (mark === void 0) {
2400
+ const firstFailure = settled.indexOf(false);
2401
+ const reached = firstFailure === -1 ? ids.length : firstFailure;
2402
+ warmed.set(locale, Math.max(warmed.get(locale) ?? 0, from + reached));
2403
+ }
2404
+ }
2405
+ /**
2406
+ * Which locale a given dictionary should be warmed under.
2407
+ *
2408
+ * `useDictionary` falls back to the dictionary's own source language when the
2409
+ * app has no locale configured, so the preload has to make the same choice or
2410
+ * it caches under a key no render ever reads — warming `""`, then suspending on
2411
+ * `"en-US"` a moment later.
2412
+ */
2413
+ function localeFor(id, locale) {
2414
+ if (locale) return locale;
2415
+ return registry.get(id)?.locales[0] ?? locale;
2416
+ }
2417
+ function setActiveLocale(locale) {
2418
+ if (locale) state.activeLocale = locale;
2419
+ }
2420
+ function getActiveLocale() {
2421
+ return state.activeLocale;
2422
+ }
2423
+ if (typeof window !== "undefined") {
2424
+ const w = window;
2425
+ const adopt = ([id, locale, strings]) => {
2426
+ putResolved(id, locale, strings);
2427
+ };
2428
+ const buffered = Array.isArray(w.__GEMI_DICT__) ? w.__GEMI_DICT__ : [];
2429
+ w.__GEMI_DICT__ = { push: adopt };
2430
+ for (const entry of buffered) adopt(entry);
2431
+ }
2432
+ //#endregion
2255
2433
  //#region client/helpers/flattenComponentTree.ts
2256
2434
  function flattenComponentTree(componentTree) {
2257
2435
  let out = [];
@@ -2273,13 +2451,18 @@ var viewModuleListeners = /* @__PURE__ */ new Set();
2273
2451
  function loadViewModule(name) {
2274
2452
  const loader = typeof window !== "undefined" ? window.loaders?.[name] : void 0;
2275
2453
  if (!loader) return Promise.resolve(null);
2276
- return Promise.resolve(loader()).then((mod) => {
2454
+ const mark = dictionaryRegistrationMark();
2455
+ return Promise.resolve(loader()).then(async (mod) => {
2277
2456
  const isNew = !viewModules.has(name);
2278
2457
  viewModules.set(name, mod);
2279
2458
  if (isNew) for (const listener of viewModuleListeners) listener();
2459
+ await preloadDictionaries(currentLocale(), mark);
2280
2460
  return mod;
2281
2461
  });
2282
2462
  }
2463
+ function currentLocale() {
2464
+ return getActiveLocale() ?? (typeof window !== "undefined" ? window.__GEMI_DATA__?.i18n?.currentLocale ?? "" : "");
2465
+ }
2283
2466
  function subscribeViewModules(listener) {
2284
2467
  viewModuleListeners.add(listener);
2285
2468
  return () => {
@@ -2713,6 +2896,6 @@ function useTheme() {
2713
2896
  return context;
2714
2897
  }
2715
2898
  //#endregion
2716
- export { toVariantKey as A, useLocation as C, useParams as D, createMemoryHistory as E, DEFAULT_STALE_TIME as F, QueryError as I, Subject as L, QueryConfigContext as M, QueryManagerContext as N, RouteStateContext as O, QueryManagerProvider as P, ServerDataProvider as S, Action as T, useSearchParams as _, m as a, I18nProvider as b, ClientRouterContext as c, ComponentsProvider as d, loadViewModule as f, useRoute as g, routeDataUrl as h, WebSocketContextProvider as i, applyParams as j, RouteStateProvider as k, ClientRouterProvider as l, readRoutePayload as m, useTheme as n, RouteTransitionProvider as o, subscribeViewModules as p, WebSocketContext as r, useRouteTransition as s, ThemeProvider as t, ComponentsContext as u, useNavigate as v, ProgressManager as w, ServerDataContext as x, I18nContext as y };
2899
+ export { createMemoryHistory as A, QueryError as B, I18nContext as C, useLocation as D, ServerDataProvider as E, applyParams as F, QueryConfigContext as I, QueryManagerContext as L, RouteStateContext as M, RouteStateProvider as N, ProgressManager as O, toVariantKey as P, QueryManagerProvider as R, useNavigate as S, ServerDataContext as T, Subject as V, setActiveLocale as _, m as a, useRoute as b, ClientRouterContext as c, ComponentsProvider as d, loadViewModule as f, registerDictionary as g, loadDictionaryForRender as h, WebSocketContextProvider as i, useParams as j, Action as k, ClientRouterProvider as l, loadDictionary as m, useTheme as n, RouteTransitionProvider as o, subscribeViewModules as p, WebSocketContext as r, useRouteTransition as s, ThemeProvider as t, ComponentsContext as u, readRoutePayload as v, I18nProvider as w, useSearchParams as x, routeDataUrl as y, DEFAULT_STALE_TIME as z };
2717
2900
 
2718
- //# sourceMappingURL=ThemeProvider-CTX9LOFC.js.map
2901
+ //# sourceMappingURL=ThemeProvider-Bk1eZymb.js.map