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
@@ -1,5 +1,5 @@
1
- import { A as toVariantKey, C as useLocation, D as useParams, F as DEFAULT_STALE_TIME, I as QueryError, L as Subject, M as QueryConfigContext, N as QueryManagerContext, O as RouteStateContext, P as QueryManagerProvider, S as ServerDataProvider, T as Action, _ as useSearchParams, a as m, b as I18nProvider, c as ClientRouterContext, d as ComponentsProvider, f as loadViewModule, g as useRoute, h as routeDataUrl, i as WebSocketContextProvider, j as applyParams$1, k as RouteStateProvider, l as ClientRouterProvider, m as readRoutePayload, n as useTheme, o as RouteTransitionProvider, p as subscribeViewModules, r as WebSocketContext, s as useRouteTransition, t as ThemeProvider, u as ComponentsContext, v as useNavigate, x as ServerDataContext, y as I18nContext } from "../chunks/ThemeProvider-CTX9LOFC.js";
2
- import { Fragment, StrictMode, Suspense, createContext, createElement, isValidElement, memo, useCallback, useContext, useDeferredValue, useEffect, useMemo, useRef, useState, useSyncExternalStore, useTransition } from "react";
1
+ import { B as QueryError, C as I18nContext, D as useLocation, E as ServerDataProvider, F as applyParams$1, I as QueryConfigContext, L as QueryManagerContext, M as RouteStateContext, N as RouteStateProvider, P as toVariantKey, R as QueryManagerProvider, S as useNavigate, T as ServerDataContext, V as Subject, _ as setActiveLocale, a as m, b as useRoute, c as ClientRouterContext, d as ComponentsProvider, f as loadViewModule, g as registerDictionary, h as loadDictionaryForRender, i as WebSocketContextProvider, j as useParams, k as Action, l as ClientRouterProvider, m as loadDictionary, n as useTheme, o as RouteTransitionProvider, p as subscribeViewModules, r as WebSocketContext, s as useRouteTransition, t as ThemeProvider, u as ComponentsContext, v as readRoutePayload, w as I18nProvider, x as useSearchParams, y as routeDataUrl, z as DEFAULT_STALE_TIME } from "../chunks/ThemeProvider-Bk1eZymb.js";
2
+ import { Fragment, StrictMode, Suspense, createContext, createElement, isValidElement, memo, use, useCallback, useContext, useDeferredValue, useEffect, useMemo, useRef, useState, useSyncExternalStore, useTransition } from "react";
3
3
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
4
4
  import { createRoot as createRoot$1, hydrateRoot } from "react-dom/client";
5
5
  //#region client/ServerQueryContext.tsx
@@ -1332,17 +1332,30 @@ function create(RootLayout, { componentTree, loaders, routeManifest, router, i18
1332
1332
  }) }));
1333
1333
  }
1334
1334
  //#endregion
1335
+ //#region client/DictionarySinkContext.ts
1336
+ /**
1337
+ * The SSR-only collector `useDictionary` reports into. `null` in the browser,
1338
+ * where nothing needs collecting — the strings are already there.
1339
+ *
1340
+ * Mirrors `ServerQueryContext`: a server-supplied per-request object handed to
1341
+ * the tree by `createRoot`.
1342
+ */
1343
+ var DictionarySinkContext = createContext(null);
1344
+ //#endregion
1335
1345
  //#region client/createRoot.tsx
1336
1346
  function createRoot(RootLayout, options = {}) {
1337
1347
  return (props) => /* @__PURE__ */ jsx(ServerDataProvider, {
1338
1348
  value: props.data,
1339
1349
  children: /* @__PURE__ */ jsx(ServerQueryContext.Provider, {
1340
1350
  value: props.serverQueries ?? null,
1341
- children: /* @__PURE__ */ jsx(ClientRouter, {
1342
- RootLayout,
1343
- viewImportMap: props.viewImportMap,
1344
- viewModules: props.viewModules,
1345
- queryConfig: options.queryConfig
1351
+ children: /* @__PURE__ */ jsx(DictionarySinkContext.Provider, {
1352
+ value: props.dictionarySink ?? null,
1353
+ children: /* @__PURE__ */ jsx(ClientRouter, {
1354
+ RootLayout,
1355
+ viewImportMap: props.viewImportMap,
1356
+ viewModules: props.viewModules,
1357
+ queryConfig: options.queryConfig
1358
+ })
1346
1359
  })
1347
1360
  })
1348
1361
  });
@@ -1501,6 +1514,14 @@ function parseTranslation(template, params) {
1501
1514
  }
1502
1515
  //#endregion
1503
1516
  //#region client/useTranslator.ts
1517
+ /**
1518
+ * @deprecated Use `useDictionary(dict)` with a `defineDictionary` dictionary
1519
+ * declared next to the component. This resolves a dictionary by name through
1520
+ * the global `I18nDictionary` interface, which needs a `gemi.d.ts`
1521
+ * declaration, a central `app/i18n/index.ts`, and a hand-maintained `prefetch`
1522
+ * map naming every route's dictionaries — and it ships whatever that map says
1523
+ * whether the page reads it or not. Still supported; see `docs/i18n.md`.
1524
+ */
1504
1525
  function useTranslator(component) {
1505
1526
  const { i18n } = useRouteData();
1506
1527
  function parse(key, ...args) {
@@ -1519,27 +1540,217 @@ function useTranslator(component) {
1519
1540
  return parse;
1520
1541
  }
1521
1542
  //#endregion
1543
+ //#region client/useDictionary.ts
1544
+ /**
1545
+ * Read a dictionary declared with `defineDictionary`, next to the component
1546
+ * that uses it.
1547
+ *
1548
+ * ```tsx
1549
+ * const t = useDictionary(homeDict);
1550
+ * t("title", { name });
1551
+ * ```
1552
+ *
1553
+ * Keys and interpolation params come straight from the literal — there is no
1554
+ * name string to keep in sync and no `gemi.d.ts` augmentation.
1555
+ *
1556
+ * Normally this resolves without suspending: the server seeds the strings it
1557
+ * rendered with into the hydration payload, and the router warms a view's
1558
+ * dictionaries while it is already loading that view's chunks. It falls back to
1559
+ * suspending on the locale's chunk when neither happened — a dictionary inside
1560
+ * a `lazy()` subtree, or the first render after a locale switch.
1561
+ *
1562
+ * Replaces `useTranslator`, which is deprecated.
1563
+ */
1564
+ function useDictionary(dictionary) {
1565
+ const { i18n } = useRouteData();
1566
+ const sink = useContext(DictionarySinkContext);
1567
+ const locale = i18n?.currentLocale ?? dictionary.locales[0];
1568
+ setActiveLocale(locale);
1569
+ const pending = dictionary.loadForRender(locale);
1570
+ const strings = pending instanceof Promise ? use(pending) : pending;
1571
+ sink?.use(dictionary.id, locale, strings);
1572
+ function parse(key, ...args) {
1573
+ const template = strings[key];
1574
+ if (typeof template !== "string") {
1575
+ console.error(`Unresolved translation key:${key} locale:${locale} dictionary:${dictionary.id}`);
1576
+ return key;
1577
+ }
1578
+ const [params = {}] = args;
1579
+ return parseTranslation(template, params);
1580
+ }
1581
+ parse.jsx = (key, ...args) => {
1582
+ return parse(key, ...args);
1583
+ };
1584
+ return parse;
1585
+ }
1586
+ //#endregion
1587
+ //#region i18n/dictionaryShape.ts
1588
+ /**
1589
+ * Locales the dictionary declares, source language first.
1590
+ *
1591
+ * The order is meaningful: the first locale is the source language, and a key
1592
+ * missing from some other locale falls back along this list.
1593
+ *
1594
+ * `sourceLocale` pins that choice. Without it the source language is whichever
1595
+ * locale is seen first while walking the literal, which makes it an emergent
1596
+ * property of key order — adding a key at the top of a dictionary whose other
1597
+ * keys happen to lack `en-US` would silently re-point every fallback in it. Any
1598
+ * dictionary that is not uniformly translated should say which locale it is
1599
+ * authored in.
1600
+ */
1601
+ function dictionaryLocales(translations, sourceLocale) {
1602
+ const locales = [];
1603
+ const seen = /* @__PURE__ */ new Set();
1604
+ if (sourceLocale) {
1605
+ seen.add(sourceLocale);
1606
+ locales.push(sourceLocale);
1607
+ }
1608
+ for (const byLocale of Object.values(translations)) for (const locale of Object.keys(byLocale)) if (!seen.has(locale)) {
1609
+ seen.add(locale);
1610
+ locales.push(locale);
1611
+ }
1612
+ return locales;
1613
+ }
1614
+ /**
1615
+ * Flatten one locale out of a dictionary.
1616
+ *
1617
+ * A key with no string for `locale` falls back along the declared locale order
1618
+ * rather than vanishing, so a half-translated dictionary degrades one string at
1619
+ * a time instead of rendering the whole component as raw keys.
1620
+ */
1621
+ function localeStrings(translations, locale, fallbackOrder = dictionaryLocales(translations)) {
1622
+ const out = {};
1623
+ for (const [key, byLocale] of Object.entries(translations)) {
1624
+ let value = byLocale?.[locale];
1625
+ if (typeof value !== "string") for (const candidate of fallbackOrder) {
1626
+ const fallback = byLocale?.[candidate];
1627
+ if (typeof fallback === "string") {
1628
+ value = fallback;
1629
+ break;
1630
+ }
1631
+ }
1632
+ if (typeof value === "string") out[key] = value;
1633
+ }
1634
+ return out;
1635
+ }
1636
+ /**
1637
+ * Canonical serialization — key order in the source file must not change the
1638
+ * id, or an innocuous reordering would break the payload/registry match.
1639
+ */
1640
+ function canonicalizeDictionary(translations) {
1641
+ return `{${Object.keys(translations).sort().map((key) => {
1642
+ const byLocale = translations[key] ?? {};
1643
+ const inner = Object.keys(byLocale).sort().map((l) => JSON.stringify([l, byLocale[l]])).join(",");
1644
+ return `${JSON.stringify(key)}:[${inner}]`;
1645
+ }).join(",")}}`;
1646
+ }
1647
+ /**
1648
+ * FNV-1a, run twice with different offsets for a 64-bit-wide id. No crypto
1649
+ * import, and it has to work identically in the browser bundle, under Bun on
1650
+ * the server, and inside the Vite plugin.
1651
+ */
1652
+ function dictionaryId(translations) {
1653
+ const input = canonicalizeDictionary(translations);
1654
+ let a = 2166136261;
1655
+ let b = 16777619;
1656
+ for (let i = 0; i < input.length; i++) {
1657
+ const c = input.charCodeAt(i);
1658
+ a = Math.imul(a ^ c, 16777619);
1659
+ b = Math.imul(b ^ c, 2166136261);
1660
+ }
1661
+ const hex = (n) => (n >>> 0).toString(16).padStart(8, "0");
1662
+ return `d_${hex(a)}${hex(b)}`;
1663
+ }
1664
+ //#endregion
1665
+ //#region i18n/defineDictionary.ts
1666
+ function defineDictionary(translations, options = {}) {
1667
+ const locales = dictionaryLocales(translations, options.sourceLocale);
1668
+ return createHandle(dictionaryId(translations), locales, (locale) => localeStrings(translations, locale, locales));
1669
+ }
1670
+ function createHandle(id, locales, load) {
1671
+ const entry = {
1672
+ id,
1673
+ locales,
1674
+ load
1675
+ };
1676
+ registerDictionary(entry);
1677
+ const ensure = () => registerDictionary(entry);
1678
+ return {
1679
+ id,
1680
+ locales,
1681
+ load: (locale) => {
1682
+ ensure();
1683
+ return loadDictionary(id, locale);
1684
+ },
1685
+ loadForRender: (locale) => {
1686
+ ensure();
1687
+ return loadDictionaryForRender(id, locale);
1688
+ },
1689
+ get: (locale) => {
1690
+ ensure();
1691
+ const strings = loadDictionary(id, locale);
1692
+ if (strings instanceof Promise) {
1693
+ strings.catch(() => {});
1694
+ return;
1695
+ }
1696
+ return strings;
1697
+ }
1698
+ };
1699
+ }
1700
+ //#endregion
1522
1701
  //#region client/useLocale.ts
1523
- var setCookie = async (locale) => {
1702
+ var LOCALE_COOKIE = "i18n-locale";
1703
+ var LOCALE_COOKIE_MAX_AGE = 3600 * 24 * 365;
1704
+ /**
1705
+ * The active locale lives in two places: the URL segment `setLocale` navigates
1706
+ * to, and the `i18n-locale` cookie the server falls back to when the URL has no
1707
+ * segment — which is exactly the case for the default locale. Both have to be in
1708
+ * place *before* the navigation asks for route data, or `Translator.detectLocale`
1709
+ * answers the request with a redirect back to the locale the cookie still names.
1710
+ *
1711
+ * Hence a synchronous `document.cookie` write rather than an awaited one. The
1712
+ * previous implementation awaited `cookieStore.set()` and hung the navigation off
1713
+ * its `.then()`; that promise is reported to never settle on iOS Safari, so the
1714
+ * `.then()` never ran and changing the language became a silent no-op — no
1715
+ * rejection, nothing for an error reporter to pick up. A synchronous write cannot
1716
+ * hang and cannot fail asynchronously, so nothing is left to gate navigation on.
1717
+ */
1718
+ function persistLocale(locale) {
1719
+ if (typeof document === "undefined") return;
1524
1720
  try {
1525
- return await globalThis.cookieStore.set("i18n-locale", locale);
1526
- } catch (err) {
1527
- return await fetch(`/api/__gemi__/services/i18n/set-locale/${locale}`);
1528
- }
1529
- };
1721
+ document.cookie = [
1722
+ `${LOCALE_COOKIE}=${encodeURIComponent(locale)}`,
1723
+ `Max-Age=${LOCALE_COOKIE_MAX_AGE}`,
1724
+ "SameSite=Strict",
1725
+ "Path=/"
1726
+ ].join("; ");
1727
+ } catch {}
1728
+ }
1729
+ /**
1730
+ * `onLocaleChange` is a server-side hook, so it takes a request to fire it. The
1731
+ * switch must not wait on that round trip, nor be cancelled by one that fails —
1732
+ * including one that fails *synchronously*: `fetch` is absent in some old
1733
+ * WebViews, and an unguarded call would throw before the navigation ran, which
1734
+ * is the same silent no-op this hook exists to prevent through another door.
1735
+ */
1736
+ function notifyLocaleChange(locale) {
1737
+ try {
1738
+ fetch(`/api/__gemi__/services/i18n/set-locale/${encodeURIComponent(locale)}`).catch(() => {});
1739
+ } catch {}
1740
+ }
1530
1741
  function useLocale() {
1531
1742
  const { i18n } = useRouteData();
1532
1743
  const { pathname, search } = useLocation();
1533
1744
  const { replace } = useNavigate();
1534
1745
  const params = useParams();
1535
1746
  const setLocale = async (locale) => {
1747
+ persistLocale(locale);
1748
+ notifyLocaleChange(locale);
1536
1749
  const urlSearchParams = new URLSearchParams(search);
1537
- setCookie(locale).then(() => {
1538
- replace(pathname, {
1539
- locale,
1540
- search: Object.fromEntries(urlSearchParams.entries()),
1541
- params
1542
- });
1750
+ await replace(pathname, {
1751
+ locale,
1752
+ search: Object.fromEntries(urlSearchParams.entries()),
1753
+ params
1543
1754
  });
1544
1755
  };
1545
1756
  return [i18n.currentLocale, setLocale];
@@ -1587,6 +1798,6 @@ function useAppIdMissmatch() {
1587
1798
  return current !== next;
1588
1799
  }
1589
1800
  //#endregion
1590
- export { Form, FormError, FormFieldContainer, Head, Image, Link, OpenGraphImage, QueryError, QueryManagerProvider, Redirect, ValidationErrors, create, createRoot, init, useAppIdMissmatch, useBreadcrumbs, useBroadcast, useDelete, useForgotPassword, useFormData, useFormStatus, useIsNavigationPending, useLocale, useLocation, useMutate, useMutation, useMutationStatus, useNavigate, useNavigationProgress, useParams, usePatch, usePost, usePrefetch, usePut, useQuery, useResetPassword, useRoute, useRouteTransition, useSearchParams, useSignIn, useSignOut, useSignUp, useSubscription, useTheme, useTranslator, useUpload, useUser };
1801
+ export { Form, FormError, FormFieldContainer, Head, Image, Link, OpenGraphImage, QueryError, QueryManagerProvider, Redirect, ValidationErrors, create, createRoot, defineDictionary, init, useAppIdMissmatch, useBreadcrumbs, useBroadcast, useDelete, useDictionary, useForgotPassword, useFormData, useFormStatus, useIsNavigationPending, useLocale, useLocation, useMutate, useMutation, useMutationStatus, useNavigate, useNavigationProgress, useParams, usePatch, usePost, usePrefetch, usePut, useQuery, useResetPassword, useRoute, useRouteTransition, useSearchParams, useSignIn, useSignOut, useSignUp, useSubscription, useTheme, useTranslator, useUpload, useUser };
1591
1802
 
1592
1803
  //# sourceMappingURL=index.js.map