@protobase/ui 0.25.2 → 0.25.3

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 (255) hide show
  1. package/dist/account/account-pages.js +3 -2
  2. package/dist/account/account-security-page.js +9 -4
  3. package/dist/account/backup-codes.js +7 -6
  4. package/dist/account/messages.js +214 -0
  5. package/dist/account/passkeys-section.js +23 -22
  6. package/dist/account/password-dialog.js +3 -2
  7. package/dist/account/sign-in-policy-form.js +11 -10
  8. package/dist/account/sign-in-policy-labels.js +30 -29
  9. package/dist/account/sign-in-policy-page.js +11 -6
  10. package/dist/account/sign-in-providers-section.js +6 -5
  11. package/dist/account/staff-sign-in-log.js +11 -10
  12. package/dist/account/totp-qr.js +2 -1
  13. package/dist/account/two-factor-section.js +24 -23
  14. package/dist/account/two-factor-setup.js +18 -17
  15. package/dist/action-card/action-card.js +2 -1
  16. package/dist/action-card/messages.js +8 -0
  17. package/dist/activity-chart/activity-chart.js +3 -2
  18. package/dist/activity-chart/messages.js +14 -0
  19. package/dist/app/app.d.ts +1 -1
  20. package/dist/app/app.js +20 -21
  21. package/dist/app/assistant-shell.js +2 -1
  22. package/dist/app/batch-failure.js +2 -1
  23. package/dist/app/breadcrumb-for.js +4 -3
  24. package/dist/app/charts/chart-groups.js +3 -2
  25. package/dist/app/charts/chart-view.js +3 -2
  26. package/dist/app/charts/group-bars.js +2 -1
  27. package/dist/app/charts/messages.js +26 -0
  28. package/dist/app/charts/period-chart.js +3 -2
  29. package/dist/app/charts/split-points.js +2 -1
  30. package/dist/app/comments/comment-composer.js +19 -18
  31. package/dist/app/comments/comments-section.js +4 -3
  32. package/dist/app/comments/messages.js +26 -0
  33. package/dist/app/create/create-page.js +11 -18
  34. package/dist/app/custom-section.js +4 -6
  35. package/dist/app/displays/board-column.js +6 -5
  36. package/dist/app/displays/board-columns.js +3 -2
  37. package/dist/app/displays/board-display.js +13 -15
  38. package/dist/app/displays/calendar-controls.js +3 -2
  39. package/dist/app/displays/calendar-display.js +12 -17
  40. package/dist/app/displays/card-carousel.js +4 -3
  41. package/dist/app/displays/cards-display.js +2 -1
  42. package/dist/app/displays/custom-display.js +4 -6
  43. package/dist/app/displays/display-frame.js +3 -2
  44. package/dist/app/displays/list-cards.js +5 -8
  45. package/dist/app/displays/list-displays.js +3 -3
  46. package/dist/app/displays/map-display.js +15 -14
  47. package/dist/app/displays/messages.js +128 -2
  48. package/dist/app/displays/period-controls.js +4 -3
  49. package/dist/app/displays/record-card.js +7 -6
  50. package/dist/app/displays/timeline-display.js +17 -26
  51. package/dist/app/displays/timeline-range.js +2 -1
  52. package/dist/app/displays/use-board-move.js +2 -2
  53. package/dist/app/displays/use-calendar-move.js +2 -1
  54. package/dist/app/document-title.js +2 -1
  55. package/dist/app/export/builder-port.js +2 -1
  56. package/dist/app/export/export-dialog.js +36 -40
  57. package/dist/app/export/export-worker.js +2 -0
  58. package/dist/app/export/messages.js +78 -0
  59. package/dist/app/export/run-export.js +5 -2
  60. package/dist/app/export/sink.js +4 -3
  61. package/dist/app/export/use-export-flow.js +4 -3
  62. package/dist/app/field-editor.js +4 -3
  63. package/dist/app/field-types/messages.js +8 -0
  64. package/dist/app/field-types/widget-part.js +2 -1
  65. package/dist/app/file-field.js +11 -14
  66. package/dist/app/gallery/gallery-section.js +4 -3
  67. package/dist/app/gallery/lightbox.js +5 -4
  68. package/dist/app/gallery/messages.js +30 -0
  69. package/dist/app/gallery/photo-details.js +3 -2
  70. package/dist/app/hand-order/hand-sorted-list.js +3 -6
  71. package/dist/app/hand-order/messages.js +4 -2
  72. package/dist/app/history/describe-change.js +3 -8
  73. package/dist/app/history/messages.js +32 -0
  74. package/dist/app/import/convert.js +20 -19
  75. package/dist/app/import/failed-rows.js +3 -2
  76. package/dist/app/import/import-button.js +2 -1
  77. package/dist/app/import/import-check-step.js +19 -35
  78. package/dist/app/import/import-dialog.js +13 -17
  79. package/dist/app/import/import-file-step.js +5 -9
  80. package/dist/app/import/import-mapping-step.js +32 -35
  81. package/dist/app/import/import-result-step.js +13 -12
  82. package/dist/app/import/messages.js +200 -0
  83. package/dist/app/import/parse-worker.js +2 -0
  84. package/dist/app/import/prepare-rows.js +5 -4
  85. package/dist/app/import/sheet-cell.js +2 -1
  86. package/dist/app/import/sheet-file.js +3 -2
  87. package/dist/app/import/sheet-source.js +7 -3
  88. package/dist/app/import/xlsx-reader.js +4 -3
  89. package/dist/app/import/xlsx-xml.js +2 -1
  90. package/dist/app/import/zip-reader.js +4 -3
  91. package/dist/app/list-edit/use-list-edits.js +1 -1
  92. package/dist/app/list-group-chart.js +2 -1
  93. package/dist/app/list-page.js +1 -1
  94. package/dist/app/map/map-layer-switch.js +3 -2
  95. package/dist/app/map/messages.js +14 -0
  96. package/dist/app/messages.js +116 -2
  97. package/dist/app/meta-gate.js +1 -1
  98. package/dist/app/nav-from-meta.js +11 -10
  99. package/dist/app/pages/action-inputs/action-inputs-dialog.js +3 -2
  100. package/dist/app/pages/action-inputs/input-answers.js +6 -5
  101. package/dist/app/pages/blocks/card-row.js +3 -2
  102. package/dist/app/pages/blocks/modal-form.js +5 -4
  103. package/dist/app/pages/blocks/record-card.js +3 -2
  104. package/dist/app/pages/blocks/stat.js +2 -1
  105. package/dist/app/pages/composed-page.js +6 -8
  106. package/dist/app/pages/confirm-action.js +2 -1
  107. package/dist/app/pages/custom-boundary.js +4 -2
  108. package/dist/app/pages/messages.js +64 -0
  109. package/dist/app/pages/render-node.js +5 -7
  110. package/dist/app/pages/use-run-action.js +11 -10
  111. package/dist/app/record-page.js +1 -1
  112. package/dist/app/record-row/messages.js +26 -0
  113. package/dist/app/record-row/record-row-body.js +12 -7
  114. package/dist/app/record-row/record-row.js +4 -3
  115. package/dist/app/record-row/saved-record-row.js +3 -2
  116. package/dist/app/related-dots/dots-summary.js +2 -1
  117. package/dist/app/related-dots/messages.js +8 -0
  118. package/dist/app/relation-picker.js +9 -8
  119. package/dist/app/router.js +5 -4
  120. package/dist/app/runtime/messages.js +58 -0
  121. package/dist/app/runtime/runtime-status.js +10 -23
  122. package/dist/app/runtime/runtime-update-dialog.js +7 -6
  123. package/dist/app/runtime/runtime-update.js +4 -3
  124. package/dist/app/saved/favorite-button.js +2 -1
  125. package/dist/app/saved/messages.js +22 -0
  126. package/dist/app/saved/saved-list.js +4 -7
  127. package/dist/app/saved/use-favorite.js +3 -2
  128. package/dist/app/search/messages.js +6 -2
  129. package/dist/app/search/navigation-hits.js +9 -7
  130. package/dist/app/searches/filter-chip-list.js +2 -1
  131. package/dist/app/searches/messages.js +96 -0
  132. package/dist/app/searches/save-search-button.js +5 -4
  133. package/dist/app/searches/saved-search-rows.js +3 -2
  134. package/dist/app/searches/saved-search-section.js +6 -5
  135. package/dist/app/searches/saved-search.js +4 -3
  136. package/dist/app/searches/saved-searches.js +15 -25
  137. package/dist/app/searches/search-controls.js +5 -4
  138. package/dist/app/searches/search-diff.js +4 -2
  139. package/dist/app/searches/search-name-dialog.js +4 -3
  140. package/dist/app/searches/update-search-dialog.js +15 -30
  141. package/dist/app/searches/use-save-search.js +8 -7
  142. package/dist/app/searches/use-search-row.js +4 -3
  143. package/dist/app/sensitive-field.js +5 -4
  144. package/dist/app/source-notice.js +13 -8
  145. package/dist/app/staff-banner.js +12 -19
  146. package/dist/app-shell/global-search.js +2 -2
  147. package/dist/app-shell/messages.js +4 -2
  148. package/dist/assistant-dock/assistant-dock.js +5 -5
  149. package/dist/assistant-dock/messages.js +26 -0
  150. package/dist/assistant-dock/use-assistant.js +2 -1
  151. package/dist/assistant-dock/use-backend-data.js +2 -1
  152. package/dist/assistant-dock/widget-view.js +3 -2
  153. package/dist/auth/auth-gate.js +10 -5
  154. package/dist/auth/auth-locale.js +14 -0
  155. package/dist/auth/auth-messages.js +122 -43
  156. package/dist/auth/auth-provider.js +6 -1
  157. package/dist/auth/code-form.js +2 -1
  158. package/dist/auth/email-code-form.js +11 -13
  159. package/dist/auth/email-code-page.js +2 -1
  160. package/dist/auth/first-run-page.js +6 -5
  161. package/dist/auth/forgot-password-form.js +14 -16
  162. package/dist/auth/forgot-password-page.js +2 -1
  163. package/dist/auth/messages.js +200 -0
  164. package/dist/auth/provider-sign-in-page.js +5 -5
  165. package/dist/auth/resend-code-button.js +2 -1
  166. package/dist/auth/reset-password-form.js +11 -10
  167. package/dist/auth/reset-password-page.js +4 -3
  168. package/dist/auth/setup-required-form.js +7 -9
  169. package/dist/auth/setup-required-page.js +7 -2
  170. package/dist/auth/sign-in-form.js +15 -18
  171. package/dist/auth/sign-in-prompt.js +4 -3
  172. package/dist/auth/sign-up-code-form.js +11 -13
  173. package/dist/auth/sign-up-details-form.js +14 -21
  174. package/dist/auth/sign-up-email-form.js +8 -7
  175. package/dist/auth/sign-up-page.js +2 -1
  176. package/dist/auth/staff-sign-in-form.js +14 -17
  177. package/dist/auth/two-factor-form.js +17 -16
  178. package/dist/auth/user-to-shell.js +2 -1
  179. package/dist/chat/composer.js +8 -7
  180. package/dist/chat/messages.js +14 -0
  181. package/dist/compact-table/compact-table.js +4 -8
  182. package/dist/compact-table/messages.js +18 -0
  183. package/dist/data/meta-data.d.ts +1 -1
  184. package/dist/data/use-update-record.js +1 -1
  185. package/dist/inline-child-table/inline-child-table.js +12 -12
  186. package/dist/inline-child-table/line-row.js +10 -9
  187. package/dist/inline-child-table/messages.js +52 -0
  188. package/dist/inline-child-table/totals-footer.js +5 -8
  189. package/dist/invitations/invite-form.js +3 -2
  190. package/dist/invitations/link-notice.js +6 -4
  191. package/dist/invitations/messages.js +24 -0
  192. package/dist/invitations/pending-invitation-row.js +4 -3
  193. package/dist/lists/messages.js +8 -0
  194. package/dist/lists/paged-search-list.js +2 -1
  195. package/dist/locale/slotted.js +14 -0
  196. package/dist/markdown/markdown-editor.js +6 -5
  197. package/dist/markdown/messages.js +16 -0
  198. package/dist/organizations/all-organizations.js +6 -5
  199. package/dist/organizations/app-roles-picker.js +2 -1
  200. package/dist/organizations/invitation-page.js +39 -49
  201. package/dist/organizations/invitations-page.js +11 -10
  202. package/dist/organizations/members-page.js +15 -10
  203. package/dist/organizations/messages.js +180 -0
  204. package/dist/organizations/organization-page.js +27 -26
  205. package/dist/organizations/organization-paths.js +16 -13
  206. package/dist/organizations/organization-row.js +3 -2
  207. package/dist/organizations/organizations-page.js +17 -16
  208. package/dist/organizations/use-organizations.js +2 -1
  209. package/dist/package.js +1 -1
  210. package/dist/plugins/before-sign-in.js +6 -1
  211. package/dist/plugins/load-plugin.d.ts +1 -1
  212. package/dist/plugins/load-plugin.js +3 -2
  213. package/dist/plugins/messages.js +36 -0
  214. package/dist/plugins/plugin-gate.js +6 -1
  215. package/dist/plugins/plugin-manifest.js +8 -7
  216. package/dist/plugins/plugin-notice.js +8 -12
  217. package/dist/primitives/messages.js +16 -0
  218. package/dist/primitives/sheet.js +2 -1
  219. package/dist/primitives/spinner.js +2 -1
  220. package/dist/primitives/token.js +2 -1
  221. package/dist/record-view/messages.js +4 -2
  222. package/dist/record-view/record-tabs.js +2 -1
  223. package/dist/roles/messages.js +14 -0
  224. package/dist/roles/use-active-role.js +3 -2
  225. package/dist/shell/assets/app-CW3U56yM.js +69 -0
  226. package/dist/shell/assets/cn-Bi0ZEjD9.js +1 -0
  227. package/dist/shell/assets/export-worker-ClACk00b.js +2 -0
  228. package/dist/shell/assets/{index-xY0Mvv6V.js → index-B7cIjCuz.js} +2 -2
  229. package/dist/shell/assets/maplibre-CVG5L9FD.js +814 -0
  230. package/dist/shell/assets/{markdown-content-ukDTCu6u.js → markdown-content-CtGUP4W6.js} +1 -1
  231. package/dist/shell/assets/parse-worker-UhbwEjS0.js +5 -0
  232. package/dist/shell/assets/preload-helper-BX9CcZkY.js +1 -0
  233. package/dist/shell/assets/{record-map-BJmYZ7kQ.js → record-map-Cw3_NcUl.js} +1 -1
  234. package/dist/shell/assets/records-map-D4f3ZeDL.js +1 -0
  235. package/dist/shell/assets/shared-protobase-ui-CB_i50NP.js +1 -0
  236. package/dist/shell/index.html +5 -3
  237. package/dist/shell/protobase.shell.json +1 -1
  238. package/dist/shell/protobase.sw.js +2 -2
  239. package/dist/side-panel/messages.js +8 -0
  240. package/dist/side-panel/side-panel.js +2 -1
  241. package/dist/toasts/messages.js +8 -0
  242. package/dist/toasts/toast.js +2 -1
  243. package/dist/users/app-invitations.js +5 -4
  244. package/dist/users/create-user-form.js +9 -8
  245. package/dist/users/messages.js +52 -0
  246. package/dist/users/use-user-roles.js +2 -1
  247. package/dist/users/user-list.js +6 -5
  248. package/dist/users/user-row.js +5 -4
  249. package/package.json +4 -4
  250. package/dist/shell/assets/app-C-OLrsRR.js +0 -69
  251. package/dist/shell/assets/export-worker-Bz57Pf5g.js +0 -2
  252. package/dist/shell/assets/maplibre-Dov6nhPX.js +0 -814
  253. package/dist/shell/assets/parse-worker-BtcY0dQw.js +0 -5
  254. package/dist/shell/assets/records-map-C1_gDKHR.js +0 -1
  255. package/dist/shell/assets/shared-protobase-ui-CFYJAbMR.js +0 -1
@@ -1,9 +1,11 @@
1
+ import { slotted } from "../../locale/slotted.js";
1
2
  import { Problem } from "../pages/problem.js";
2
3
  import { CustomBoundary } from "../pages/custom-boundary.js";
4
+ import { text } from "./messages.js";
3
5
  import { useProjectUi } from "../pages/project-ui.js";
4
6
  import { ListDisplayProvider } from "./display-context.js";
5
7
  import { unmarkFieldRefs } from "@protobase/schema/internal";
6
- import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { jsx } from "react/jsx-runtime";
7
9
  //#region src/app/displays/custom-display.tsx
8
10
  /**
9
11
  * A display the project draws: the component registered under its name gets the display's props, field references
@@ -12,11 +14,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
12
14
  const CustomDisplay = ({ display, list }) => {
13
15
  const { components } = useProjectUi();
14
16
  const Component = components?.[display.component];
15
- if (!Component) return /* @__PURE__ */ jsxs(Problem, { children: [
16
- "No component is registered as ",
17
- display.component,
18
- ". Export it from protobase.ui.tsx, or load the plugin that provides it."
19
- ] });
17
+ if (!Component) return /* @__PURE__ */ jsx(Problem, { children: slotted(text("noComponent"), display.component) });
20
18
  return /* @__PURE__ */ jsx(ListDisplayProvider, {
21
19
  value: list,
22
20
  children: /* @__PURE__ */ jsx("div", {
@@ -1,5 +1,6 @@
1
1
  import { formatTag } from "../../locale/active-locale.js";
2
2
  import { Button } from "../../primitives/button.js";
3
+ import { text } from "./messages.js";
3
4
  import { ErrorBanner } from "../error-banner.js";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region src/app/displays/display-frame.tsx
@@ -7,7 +8,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
7
8
  const DisplayState = ({ list, empty, loading, children }) => /* @__PURE__ */ jsx("div", {
8
9
  className: "min-h-0 flex-1 overflow-y-auto",
9
10
  children: list.loading ? loading : list.error ? /* @__PURE__ */ jsx(ErrorBanner, {
10
- title: "Could not load rows",
11
+ title: text("couldNotLoadRows"),
11
12
  error: list.error
12
13
  }) : list.rows.length === 0 ? /* @__PURE__ */ jsx("p", {
13
14
  className: "py-8 text-center text-muted-foreground",
@@ -24,7 +25,7 @@ const DisplayFooter = ({ list }) => /* @__PURE__ */ jsxs("div", {
24
25
  ] }), list.more && /* @__PURE__ */ jsx(Button, {
25
26
  size: "sm",
26
27
  onClick: list.loadMore,
27
- children: "Show more"
28
+ children: text("showMore")
28
29
  })]
29
30
  });
30
31
  //#endregion
@@ -1,10 +1,11 @@
1
1
  import { Skeleton } from "../../primitives/skeleton.js";
2
2
  import { humanize } from "../../live/naming.js";
3
+ import { text } from "./messages.js";
3
4
  import { displayRow } from "./list-displays.js";
4
5
  import { ErrorBanner } from "../error-banner.js";
5
6
  import { RecordCard } from "./record-card.js";
6
7
  import { VirtualCards } from "./virtual-cards.js";
7
- import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { jsx } from "react/jsx-runtime";
8
9
  //#region src/app/displays/list-cards.tsx
9
10
  const grid = "grid grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] gap-3";
10
11
  const pictureHeight = (width) => width * .75;
@@ -21,16 +22,12 @@ const ListCards = ({ model, view, display, list, empty }) => {
21
22
  children: Array.from({ length: 6 }, (_, index) => /* @__PURE__ */ jsx(Skeleton, { className: "h-24" }, index))
22
23
  });
23
24
  if (list.error) return /* @__PURE__ */ jsx(ErrorBanner, {
24
- title: "Could not load rows",
25
+ title: text("couldNotLoadRows"),
25
26
  error: list.error
26
27
  });
27
- if (!list.source || list.source.total === 0) return empty ?? /* @__PURE__ */ jsxs("p", {
28
+ if (!list.source || list.source.total === 0) return empty ?? /* @__PURE__ */ jsx("p", {
28
29
  className: "py-8 text-center text-muted-foreground",
29
- children: [
30
- "No ",
31
- plural.toLowerCase(),
32
- " match."
33
- ]
30
+ children: text("noneMatch", plural.toLowerCase())
34
31
  });
35
32
  return /* @__PURE__ */ jsx(VirtualCards, {
36
33
  source: list.source,
@@ -4,8 +4,8 @@ import { listColumnNames } from "../../live/columns-from-model.js";
4
4
  import { displayValue } from "../../live/display-value.js";
5
5
  import { photosKey } from "../../live/row-photos.js";
6
6
  import { filledFields } from "../filled-fields.js";
7
- import { boardCard } from "./board-columns.js";
8
7
  import { text } from "./messages.js";
8
+ import { boardCard } from "./board-columns.js";
9
9
  import { encodeKey, tableDisplay } from "@protobase/schema/internal";
10
10
  //#region src/app/displays/list-displays.ts
11
11
  const displaysOf = (view) => view?.list?.displays ?? [];
@@ -36,7 +36,7 @@ const phoneRows = (model, view) => {
36
36
  return {
37
37
  kind: "cards",
38
38
  name: rowsDisplay,
39
- label: "List",
39
+ label: text("list"),
40
40
  icon: "list",
41
41
  title,
42
42
  ...badge !== void 0 && { badge },
@@ -81,7 +81,7 @@ const listDisplayChoices = (model, view, xs) => {
81
81
  const choices = displayChoices(view);
82
82
  return xs && phoneRows(model, view) ? [...choices, {
83
83
  name: rowsDisplay,
84
- label: "List",
84
+ label: text("list"),
85
85
  icon: "list"
86
86
  }] : choices;
87
87
  };
@@ -1,8 +1,9 @@
1
- import { cn } from "../../lib/cn.js";
2
1
  import { formatTag } from "../../locale/active-locale.js";
2
+ import { cn } from "../../lib/cn.js";
3
3
  import { Button } from "../../primitives/button.js";
4
4
  import { Problem } from "../pages/problem.js";
5
5
  import { humanize } from "../../live/naming.js";
6
+ import { text } from "./messages.js";
6
7
  import { mapCards } from "./list-displays.js";
7
8
  import { useAdminMeta } from "../meta-gate.js";
8
9
  import { ErrorBanner } from "../error-banner.js";
@@ -54,15 +55,15 @@ const MapDisplay = ({ model, view, display, filter, orderBy, fields, at, onMove,
54
55
  const approximate = new Set(points.filter((point) => point.approximate).map((point) => point.key));
55
56
  const markerLabel = (keys) => {
56
57
  const near = keys.filter((key) => approximate.has(key)).length;
57
- if (keys.length === 1) return near === 1 ? `Show the ${singular}, at an approximate position` : `Show the ${singular}`;
58
- if (near === 0) return `Show ${keys.length} ${plural}`;
59
- return near === keys.length ? `Show ${keys.length} ${plural}, at approximate positions` : `Show ${keys.length} ${plural}, ${near} at approximate positions`;
58
+ if (keys.length === 1) return near === 1 ? text("showOneApproximate", singular) : text("showOne", singular);
59
+ if (near === 0) return text("showMany", keys.length, plural);
60
+ return near === keys.length ? text("showManyApproximate", keys.length, plural) : text("showManySomeApproximate", keys.length, plural, near);
60
61
  };
61
- const bucketLabel = (count) => `Zoom in on ${count.toLocaleString(formatTag())} ${count === 1 ? singular : plural}`;
62
+ const bucketLabel = (count) => text("zoomIn", count.toLocaleString(formatTag()), count === 1 ? singular : plural);
62
63
  const overlay = useRef(null);
63
64
  const [covered, setCovered] = useState(0);
64
65
  useLayoutEffect(() => setCovered(overlay.current?.offsetHeight ?? 0), [row?.key]);
65
- if (!style) return /* @__PURE__ */ jsx(Problem, { children: "The map display needs a map style: set PROTOBASE_MAP_STYLE_URL." });
66
+ if (!style) return /* @__PURE__ */ jsx(Problem, { children: text("needsStyle") });
66
67
  const empty = loaded?.total === 0;
67
68
  return /* @__PURE__ */ jsxs("div", {
68
69
  className: cn("flex h-full min-h-[36rem] flex-1 flex-col sm:min-h-[28rem]", flush && "max-md:-mx-5 max-md:-mb-4 max-md:min-h-0"),
@@ -97,7 +98,7 @@ const MapDisplay = ({ model, view, display, filter, orderBy, fields, at, onMove,
97
98
  records.error && /* @__PURE__ */ jsx("div", {
98
99
  className: "absolute inset-x-3 top-3 z-10",
99
100
  children: /* @__PURE__ */ jsx(ErrorBanner, {
100
- title: "Could not load rows",
101
+ title: text("couldNotLoadRows"),
101
102
  error: records.error
102
103
  })
103
104
  }),
@@ -106,10 +107,10 @@ const MapDisplay = ({ model, view, display, filter, orderBy, fields, at, onMove,
106
107
  children: /* @__PURE__ */ jsxs("p", {
107
108
  className: "pointer-events-auto flex items-center gap-3 rounded-full border border-border bg-background px-4 py-1.5 text-muted-foreground shadow",
108
109
  role: "status",
109
- children: [fitting ? `No ${plural} match.` : `No ${plural} in this part of the map.`, !fitting && /* @__PURE__ */ jsx(Button, {
110
+ children: [fitting ? text("noneMatch", plural) : text("noneHere", plural), !fitting && /* @__PURE__ */ jsx(Button, {
110
111
  size: "sm",
111
112
  onClick: () => setFitting(true),
112
- children: "Show all"
113
+ children: text("showAll")
113
114
  })]
114
115
  })
115
116
  }),
@@ -119,7 +120,7 @@ const MapDisplay = ({ model, view, display, filter, orderBy, fields, at, onMove,
119
120
  children: /* @__PURE__ */ jsxs("div", {
120
121
  className: "pointer-events-auto flex w-full max-w-[16rem] flex-col gap-2 sm:max-w-xs",
121
122
  role: "group",
122
- "aria-label": `Chosen ${singular}`,
123
+ "aria-label": text("chosen", singular),
123
124
  children: [/* @__PURE__ */ jsxs("div", {
124
125
  className: "flex items-center justify-end gap-1.5",
125
126
  children: [
@@ -128,12 +129,12 @@ const MapDisplay = ({ model, view, display, filter, orderBy, fields, at, onMove,
128
129
  children: [/* @__PURE__ */ jsx(CircleDashed, {
129
130
  className: "size-3.5",
130
131
  "aria-hidden": true
131
- }), "Approximate position"]
132
+ }), text("approximatePosition")]
132
133
  }),
133
134
  selection.keys.length > 1 && /* @__PURE__ */ jsxs(Fragment$1, { children: [
134
135
  /* @__PURE__ */ jsx("button", {
135
136
  type: "button",
136
- "aria-label": "Previous",
137
+ "aria-label": text("previous"),
137
138
  className: arrow,
138
139
  onClick: () => setChosen(stepSelection(selection, -1)),
139
140
  children: /* @__PURE__ */ jsx(ChevronLeft, {
@@ -152,7 +153,7 @@ const MapDisplay = ({ model, view, display, filter, orderBy, fields, at, onMove,
152
153
  }),
153
154
  /* @__PURE__ */ jsx("button", {
154
155
  type: "button",
155
- "aria-label": "Next",
156
+ "aria-label": text("next"),
156
157
  className: arrow,
157
158
  onClick: () => setChosen(stepSelection(selection, 1)),
158
159
  children: /* @__PURE__ */ jsx(ChevronRight, {
@@ -163,7 +164,7 @@ const MapDisplay = ({ model, view, display, filter, orderBy, fields, at, onMove,
163
164
  ] }),
164
165
  /* @__PURE__ */ jsx("button", {
165
166
  type: "button",
166
- "aria-label": "Close",
167
+ "aria-label": text("close"),
167
168
  className: arrow,
168
169
  onClick: () => setChosen(void 0),
169
170
  children: /* @__PURE__ */ jsx(X, {
@@ -11,7 +11,62 @@ const text = defineMessages({
11
11
  orderChanged: "Order changed",
12
12
  stayedIn: (column) => `Saved, still in ${column}`,
13
13
  undo: "Undo",
14
- couldNotUndo: "Could not undo"
14
+ couldNotUndo: "Could not undo",
15
+ couldNotLoadRows: "Could not load rows",
16
+ noPlural: (plural) => `No ${plural}`,
17
+ noValue: (label) => `No ${label.toLowerCase()}`,
18
+ somethingWrong: "Something went wrong",
19
+ showMore: "Show more",
20
+ noDrop: "No board drop is registered as {}. Give it in boardDrops in protobase.ui.tsx, or load the plugin that provides it.",
21
+ noComponent: "No component is registered as {}. Export it from protobase.ui.tsx, or load the plugin that provides it.",
22
+ pickedUp: (title) => `Picked up ${title}.`,
23
+ isOver: (title, over) => `${title} is over ${over}.`,
24
+ putBack: (title) => `${title} was put back.`,
25
+ wasMovedTo: (title, to) => `${title} was moved to ${to}.`,
26
+ cancelled: (title) => `Moving ${title} was cancelled.`,
27
+ startsOn: (title, day) => `${title} starts on ${day}.`,
28
+ noColumn: "no column",
29
+ noDay: "no day",
30
+ placeOf: (column, place, count) => `${column}, place ${place} of ${count}`,
31
+ place: (column, place) => `${column}, place ${place}`,
32
+ boardAcross: "To move a card to another column, press Space, move it with the left and right arrow keys, and press Space again to drop it there. Escape puts it back.",
33
+ boardAnywhere: "To move a card, press Space, move it with the up and down arrow keys within its column and the left and right arrow keys to another column, and press Space again to drop it there. Escape puts it back.",
34
+ boardWithin: "To move a card, press Space, move it with the up and down arrow keys within its column, and press Space again to drop it there. Escape puts it back.",
35
+ calendarInstructions: "To move an event to another day, press Space, move it a day with the left and right arrow keys or a week with the up and down arrow keys, and press Space again to drop it there. Escape puts it back.",
36
+ timelineInstructions: "To move a bar to other days, press Space, move it a day with the left and right arrow keys, and press Space again to drop it there. Escape puts it back.",
37
+ week: "Week",
38
+ month: "Month",
39
+ quarter: "Quarter",
40
+ calendarScale: "Calendar scale",
41
+ timelineScale: "Timeline scale",
42
+ previousPeriod: (unit) => `Previous ${unit}`,
43
+ nextPeriod: (unit) => `Next ${unit}`,
44
+ today: "Today",
45
+ capped: (limit, unit) => `Showing the first ${limit} records of this ${unit}. Narrow the filter to see the rest.`,
46
+ nothingIn: (unit) => `Nothing in this ${unit}.`,
47
+ photoOf: (index, count) => `Photo ${index} of ${count}`,
48
+ noneMatch: (plural) => `No ${plural} match.`,
49
+ list: "List",
50
+ showOneApproximate: (singular) => `Show the ${singular}, at an approximate position`,
51
+ showOne: (singular) => `Show the ${singular}`,
52
+ showMany: (count, plural) => `Show ${count} ${plural}`,
53
+ showManyApproximate: (count, plural) => `Show ${count} ${plural}, at approximate positions`,
54
+ showManySomeApproximate: (count, plural, near) => `Show ${count} ${plural}, ${near} at approximate positions`,
55
+ zoomIn: (count, noun) => `Zoom in on ${count} ${noun}`,
56
+ needsStyle: "The map display needs a map style: set PROTOBASE_MAP_STYLE_URL.",
57
+ noneHere: (plural) => `No ${plural} in this part of the map.`,
58
+ showAll: "Show all",
59
+ chosen: (singular) => `Chosen ${singular}`,
60
+ approximatePosition: "Approximate position",
61
+ previous: "Previous",
62
+ next: "Next",
63
+ close: "Close",
64
+ features: "Features",
65
+ couldNotReorder: "Could not change the order",
66
+ couldNotMoveTo: (to) => `Could not move it to ${to}`,
67
+ moreHidden: (count) => `+${count} more`,
68
+ previousPhoto: "Previous photo",
69
+ nextPhoto: "Next photo"
15
70
  },
16
71
  nl: {
17
72
  table: "Tabel",
@@ -23,7 +78,78 @@ const text = defineMessages({
23
78
  orderChanged: "Volgorde gewijzigd",
24
79
  stayedIn: (column) => `Opgeslagen, nog in ${column}`,
25
80
  undo: "Ongedaan maken",
26
- couldNotUndo: "Kon niet ongedaan maken"
81
+ couldNotUndo: "Kon niet ongedaan maken",
82
+ couldNotLoadRows: "Kon de rijen niet laden",
83
+ noPlural: (plural) => `Geen ${plural}`,
84
+ noValue: (label) => `Geen ${label.toLowerCase()}`,
85
+ somethingWrong: "Er ging iets mis",
86
+ showMore: "Meer tonen",
87
+ noDrop: "Er is geen bordactie geregistreerd als {}. Geef die in boardDrops in protobase.ui.tsx, of laad de plug-in die haar levert.",
88
+ noComponent: "Er is geen component geregistreerd als {}. Exporteer die uit protobase.ui.tsx, of laad de plug-in die haar levert.",
89
+ pickedUp: (title) => `${title} opgepakt.`,
90
+ isOver: (title, over) => `${title} is boven ${over}.`,
91
+ putBack: (title) => `${title} is teruggezet.`,
92
+ wasMovedTo: (title, to) => `${title} is verplaatst naar ${to}.`,
93
+ cancelled: (title) => `Verplaatsen van ${title} is geannuleerd.`,
94
+ startsOn: (title, day) => `${title} begint op ${day}.`,
95
+ noColumn: "geen kolom",
96
+ noDay: "geen dag",
97
+ placeOf: (column, place, count) => `${column}, plaats ${place} van ${count}`,
98
+ place: (column, place) => `${column}, plaats ${place}`,
99
+ boardAcross: "Druk op Spatie om een kaart naar een andere kolom te verplaatsen, verplaats haar met de pijltjestoetsen links en rechts, en druk nogmaals op Spatie om haar daar neer te zetten. Escape zet haar terug.",
100
+ boardAnywhere: "Druk op Spatie om een kaart te verplaatsen, verplaats haar met de pijltjestoetsen omhoog en omlaag binnen haar kolom en met links en rechts naar een andere kolom, en druk nogmaals op Spatie om haar daar neer te zetten. Escape zet haar terug.",
101
+ boardWithin: "Druk op Spatie om een kaart te verplaatsen, verplaats haar met de pijltjestoetsen omhoog en omlaag binnen haar kolom, en druk nogmaals op Spatie om haar daar neer te zetten. Escape zet haar terug.",
102
+ calendarInstructions: "Druk op Spatie om een gebeurtenis naar een andere dag te verplaatsen, verplaats haar een dag met de pijltjestoetsen links en rechts of een week met omhoog en omlaag, en druk nogmaals op Spatie om haar daar neer te zetten. Escape zet haar terug.",
103
+ timelineInstructions: "Druk op Spatie om een balk naar andere dagen te verplaatsen, verplaats hem een dag met de pijltjestoetsen links en rechts, en druk nogmaals op Spatie om hem daar neer te zetten. Escape zet hem terug.",
104
+ week: "Week",
105
+ month: "Maand",
106
+ quarter: "Kwartaal",
107
+ calendarScale: "Schaal van de kalender",
108
+ timelineScale: "Schaal van de tijdlijn",
109
+ previousPeriod: (unit) => ({
110
+ week: "Vorige week",
111
+ month: "Vorige maand",
112
+ quarter: "Vorig kwartaal"
113
+ })[unit],
114
+ nextPeriod: (unit) => ({
115
+ week: "Volgende week",
116
+ month: "Volgende maand",
117
+ quarter: "Volgend kwartaal"
118
+ })[unit],
119
+ today: "Vandaag",
120
+ capped: (limit, unit) => `De eerste ${limit} records van ${{
121
+ week: "deze week",
122
+ month: "deze maand",
123
+ quarter: "dit kwartaal"
124
+ }[unit]} worden getoond. Verfijn het filter om de rest te zien.`,
125
+ nothingIn: (unit) => `Niets in ${{
126
+ week: "deze week",
127
+ month: "deze maand",
128
+ quarter: "dit kwartaal"
129
+ }[unit]}.`,
130
+ photoOf: (index, count) => `Foto ${index} van ${count}`,
131
+ noneMatch: (plural) => `Geen ${plural} gevonden.`,
132
+ list: "Lijst",
133
+ showOneApproximate: (singular) => `${singular} tonen, op een geschatte plek`,
134
+ showOne: (singular) => `${singular} tonen`,
135
+ showMany: (count, plural) => `${count} ${plural} tonen`,
136
+ showManyApproximate: (count, plural) => `${count} ${plural} tonen, op geschatte plekken`,
137
+ showManySomeApproximate: (count, plural, near) => `${count} ${plural} tonen, ${near} op geschatte plekken`,
138
+ zoomIn: (count, noun) => `Inzoomen op ${count} ${noun}`,
139
+ needsStyle: "De kaartweergave heeft een kaartstijl nodig: stel PROTOBASE_MAP_STYLE_URL in.",
140
+ noneHere: (plural) => `Geen ${plural} in dit deel van de kaart.`,
141
+ showAll: "Alles tonen",
142
+ chosen: (singular) => `Gekozen ${singular}`,
143
+ approximatePosition: "Geschatte plek",
144
+ previous: "Vorige",
145
+ next: "Volgende",
146
+ close: "Sluiten",
147
+ features: "Kenmerken",
148
+ couldNotReorder: "Kon de volgorde niet wijzigen",
149
+ couldNotMoveTo: (to) => `Kon het niet naar ${to} verplaatsen`,
150
+ moreHidden: (count) => `+${count} meer`,
151
+ previousPhoto: "Vorige foto",
152
+ nextPhoto: "Volgende foto"
27
153
  }
28
154
  });
29
155
  //#endregion
@@ -1,5 +1,6 @@
1
1
  import { segmentedClass } from "../../primitives/segmented.js";
2
2
  import { buttonClass } from "../../primitives/button.js";
3
+ import { text } from "./messages.js";
3
4
  import { AppLink } from "../use-app-address.js";
4
5
  import { Fragment } from "react";
5
6
  import { ChevronLeft, ChevronRight } from "lucide-react";
@@ -38,9 +39,9 @@ const PeriodControls = ({ heading, unit, previous, today, next, scales, scalesLa
38
39
  children: [/* @__PURE__ */ jsxs("div", {
39
40
  className: "flex items-center gap-1",
40
41
  children: [
41
- control(previous, square, `Previous ${unit}`, /* @__PURE__ */ jsx(ChevronLeft, { className: "size-3.5" })),
42
- control(today, square, "Today", "Today"),
43
- control(next, square, `Next ${unit}`, /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5" }))
42
+ control(previous, square, text("previousPeriod", unit), /* @__PURE__ */ jsx(ChevronLeft, { className: "size-3.5" })),
43
+ control(today, square, text("today"), text("today")),
44
+ control(next, square, text("nextPeriod", unit), /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5" }))
44
45
  ]
45
46
  }), /* @__PURE__ */ jsx("span", {
46
47
  role: "group",
@@ -5,6 +5,7 @@ import { markdownExcerpt } from "../../markdown/markdown-excerpt.js";
5
5
  import { isMarkdown } from "../../markdown/markdown-hint.js";
6
6
  import { recordKey } from "../../live/model-helpers.js";
7
7
  import { displayValue } from "../../live/display-value.js";
8
+ import { text } from "./messages.js";
8
9
  import { amountParts, cardFields, filledAmount, filledMeta } from "./list-displays.js";
9
10
  import { AppLink } from "../use-app-address.js";
10
11
  import { useProjectUi } from "../pages/project-ui.js";
@@ -41,7 +42,7 @@ const MetaValue = ({ icon, children }) => {
41
42
  const RecordCard = ({ model, view, display, row, swipe = true, mark }) => {
42
43
  const { image, title, subtitle, amount, badge, meta, footer, flags } = cardFields(model, view, display);
43
44
  const label = (name) => view?.fields[name]?.label ?? humanize(name);
44
- const text = (name) => {
45
+ const text$1 = (name) => {
45
46
  const field = model.fields[name];
46
47
  if (!field) return "";
47
48
  const value = row.record[name];
@@ -59,8 +60,8 @@ const RecordCard = ({ model, view, display, row, swipe = true, mark }) => {
59
60
  part: "display",
60
61
  field,
61
62
  value: row.record[name],
62
- fallback: text(name)
63
- }) : text(name);
63
+ fallback: text$1(name)
64
+ }) : text$1(name);
64
65
  };
65
66
  const subtitleValue = (name) => {
66
67
  const field = model.fields[name];
@@ -79,7 +80,7 @@ const RecordCard = ({ model, view, display, row, swipe = true, mark }) => {
79
80
  return /* @__PURE__ */ jsx(ValueBadge, {
80
81
  value,
81
82
  hints,
82
- children: text(name)
83
+ children: text$1(name)
83
84
  });
84
85
  };
85
86
  const amountValue = (name) => {
@@ -114,7 +115,7 @@ const RecordCard = ({ model, view, display, row, swipe = true, mark }) => {
114
115
  }), badge !== void 0 && status !== null && status !== void 0 && /* @__PURE__ */ jsx(ValueBadge, {
115
116
  value: status,
116
117
  hints: view?.fields[badge],
117
- children: text(badge)
118
+ children: text$1(badge)
118
119
  })]
119
120
  }),
120
121
  subtitle !== void 0 && /* @__PURE__ */ jsx("span", {
@@ -140,7 +141,7 @@ const RecordCard = ({ model, view, display, row, swipe = true, mark }) => {
140
141
  }),
141
142
  raised.length > 0 && /* @__PURE__ */ jsx("ul", {
142
143
  className: "flex flex-wrap gap-1",
143
- "aria-label": "Features",
144
+ "aria-label": text("features"),
144
145
  children: raised.map((name) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Badge, {
145
146
  dot: false,
146
147
  children: label(name)
@@ -2,6 +2,7 @@ import { Skeleton } from "../../primitives/skeleton.js";
2
2
  import { dayIn, viewerZone } from "../../format/zone.js";
3
3
  import { formatDate } from "../../format/date.js";
4
4
  import { humanize } from "../../live/naming.js";
5
+ import { text } from "./messages.js";
5
6
  import { usePermissions } from "../meta-gate.js";
6
7
  import { ErrorBanner } from "../error-banner.js";
7
8
  import { can, rowAllows } from "../permissions.js";
@@ -17,18 +18,18 @@ import { useRef, useState } from "react";
17
18
  import { jsx, jsxs } from "react/jsx-runtime";
18
19
  import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, useSensor, useSensors } from "@dnd-kit/core";
19
20
  //#region src/app/displays/timeline-display.tsx
20
- const scales = [
21
+ const scales = () => [
21
22
  {
22
23
  scale: "week",
23
- label: "Week"
24
+ label: text("week")
24
25
  },
25
26
  {
26
27
  scale: "month",
27
- label: "Month"
28
+ label: text("month")
28
29
  },
29
30
  {
30
31
  scale: "quarter",
31
- label: "Quarter"
32
+ label: text("quarter")
32
33
  }
33
34
  ];
34
35
  /**
@@ -90,11 +91,11 @@ const TimelineDisplay = ({ model, view, display, fields, filter, at, linkTo, now
90
91
  const title = (picked) => eventTitle(model, view, display, picked.row);
91
92
  const startText = (picked) => formatDate(Date.parse(`${addDays(picked.day, shift.current)}T00:00:00Z`));
92
93
  const announcements = {
93
- onDragStart: ({ active: picked }) => `Picked up ${title(picked.data.current)}.`,
94
- onDragMove: ({ active: picked }) => `${title(picked.data.current)} starts on ${startText(picked.data.current)}.`,
94
+ onDragStart: ({ active: picked }) => text("pickedUp", title(picked.data.current)),
95
+ onDragMove: ({ active: picked }) => text("startsOn", title(picked.data.current), startText(picked.data.current)),
95
96
  onDragOver: () => void 0,
96
- onDragEnd: ({ active: picked }) => shift.current === 0 ? `${title(picked.data.current)} was put back.` : `${title(picked.data.current)} was moved to ${startText(picked.data.current)}.`,
97
- onDragCancel: ({ active: picked }) => `Moving ${title(picked.data.current)} was cancelled.`
97
+ onDragEnd: ({ active: picked }) => shift.current === 0 ? text("putBack", title(picked.data.current)) : text("wasMovedTo", title(picked.data.current), startText(picked.data.current)),
98
+ onDragCancel: ({ active: picked }) => text("cancelled", title(picked.data.current))
98
99
  };
99
100
  const release = () => {
100
101
  setActive(void 0);
@@ -127,28 +128,22 @@ const TimelineDisplay = ({ model, view, display, fields, filter, at, linkTo, now
127
128
  day: today
128
129
  }, now),
129
130
  next: stepTimeline(shown, 1),
130
- scales: scales.map(({ scale, label }) => ({
131
+ scales: scales().map(({ scale, label }) => ({
131
132
  view: scaledTimeline(shown, scale, now),
132
133
  label,
133
134
  current: shown.scale === scale
134
135
  })),
135
- scalesLabel: "Timeline scale",
136
+ scalesLabel: text("timelineScale"),
136
137
  linkTo,
137
138
  onView: setLocal
138
139
  }),
139
140
  list.error && /* @__PURE__ */ jsx(ErrorBanner, {
140
- title: "Could not load rows",
141
+ title: text("couldNotLoadRows"),
141
142
  error: list.error
142
143
  }),
143
- list.capped && /* @__PURE__ */ jsxs("p", {
144
+ list.capped && /* @__PURE__ */ jsx("p", {
144
145
  className: "text-xs text-muted-foreground",
145
- children: [
146
- "Showing the first ",
147
- 500,
148
- " records of this ",
149
- shown.scale,
150
- ". Narrow the filter to see the rest."
151
- ]
146
+ children: text("capped", 500, shown.scale)
152
147
  }),
153
148
  /* @__PURE__ */ jsxs(DndContext, {
154
149
  sensors,
@@ -159,7 +154,7 @@ const TimelineDisplay = ({ model, view, display, fields, filter, at, linkTo, now
159
154
  onDragCancel: release,
160
155
  accessibility: {
161
156
  announcements,
162
- screenReaderInstructions: { draggable: "To move a bar to other days, press Space, move it a day with the left and right arrow keys, and press Space again to drop it there. Escape puts it back." }
157
+ screenReaderInstructions: { draggable: text("timelineInstructions") }
163
158
  },
164
159
  children: [/* @__PURE__ */ jsxs("div", {
165
160
  className: "overflow-hidden rounded-lg border border-border",
@@ -181,13 +176,9 @@ const TimelineDisplay = ({ model, view, display, fields, filter, at, linkTo, now
181
176
  className: "relative flex flex-col gap-2 p-2",
182
177
  children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-4" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-4" })]
183
178
  }),
184
- empty && /* @__PURE__ */ jsxs("p", {
179
+ empty && /* @__PURE__ */ jsx("p", {
185
180
  className: "relative px-2 py-3 text-xs text-muted-foreground",
186
- children: [
187
- "Nothing in this ",
188
- shown.scale,
189
- "."
190
- ]
181
+ children: text("nothingIn", shown.scale)
191
182
  }),
192
183
  !list.loading && lanes.map((lane) => /* @__PURE__ */ jsxs("section", {
193
184
  "aria-label": lane.label,
@@ -2,6 +2,7 @@ import { dayIn, viewerZone } from "../../format/zone.js";
2
2
  import { formatDayRange, formatMonth, formatMonthName, formatMonthRange, formatWeekday } from "../../format/date.js";
3
3
  import { humanize } from "../../live/naming.js";
4
4
  import { displayValue } from "../../live/display-value.js";
5
+ import { text } from "./messages.js";
5
6
  import { addDays, monday, monthOf, recordDays } from "./calendar-range.js";
6
7
  //#region src/app/displays/timeline-range.ts
7
8
  const dayMs = 864e5;
@@ -114,7 +115,7 @@ const timelineLanes = (rows, model, view, display) => {
114
115
  const value = row.record[group];
115
116
  const empty = value === null || value === void 0 || value === "";
116
117
  const key = empty ? noValue : `value:${String(value)}`;
117
- const label = empty ? `No ${(hints?.label ?? humanize(group)).toLowerCase()}` : row.labels[group] ?? displayValue(field, value, hints);
118
+ const label = empty ? text("noValue", hints?.label ?? humanize(group)) : row.labels[group] ?? displayValue(field, value, hints);
118
119
  const known = lanes.get(key) ?? {
119
120
  value: empty ? void 0 : value,
120
121
  lane: {
@@ -1,8 +1,8 @@
1
1
  import { useClient } from "../../data/api-provider.js";
2
2
  import { useToast } from "../../toasts/toast-provider.js";
3
3
  import { recordKey } from "../../live/model-helpers.js";
4
- import { refusalReason } from "./board-columns.js";
5
4
  import { text } from "./messages.js";
5
+ import { refusalReason } from "./board-columns.js";
6
6
  import { useRefreshResource } from "../pages/use-layout-data.js";
7
7
  import { dropWrite } from "./board-drop.js";
8
8
  import { boardWrites, placeOps } from "./board-place.js";
@@ -115,7 +115,7 @@ const useBoardMove = ({ model, by, rank, drop, labelOf }) => {
115
115
  },
116
116
  onError: (error, { row, to }) => {
117
117
  settle(row.key);
118
- const title = (row.record[by] ?? null) === to.value ? "Could not change the order" : `Could not move it to ${to.label}`;
118
+ const title = (row.record[by] ?? null) === to.value ? text("couldNotReorder") : text("couldNotMoveTo", to.label);
119
119
  toast.show({
120
120
  state: "error",
121
121
  title,
@@ -2,6 +2,7 @@ import { formatDate } from "../../format/date.js";
2
2
  import { useClient } from "../../data/api-provider.js";
3
3
  import { useToast } from "../../toasts/toast-provider.js";
4
4
  import { recordKey } from "../../live/model-helpers.js";
5
+ import { text } from "./messages.js";
5
6
  import { refusalReason } from "./board-columns.js";
6
7
  import { useRefreshResource } from "../pages/use-layout-data.js";
7
8
  import { movedPatch } from "./calendar-range.js";
@@ -44,7 +45,7 @@ const useCalendarMove = (model, display) => {
44
45
  settle(row.key);
45
46
  toast.show({
46
47
  state: "error",
47
- title: `Could not move it to ${formatDate(Date.parse(`${to}T00:00:00Z`))}`,
48
+ title: text("couldNotMoveTo", formatDate(Date.parse(`${to}T00:00:00Z`))),
48
49
  description: refusalReason(error)
49
50
  });
50
51
  },
@@ -1,3 +1,4 @@
1
+ import { text } from "./create/messages.js";
1
2
  import { useEffect } from "react";
2
3
  //#region src/app/document-title.ts
3
4
  /** What a tab names, most specific first: the record and its list, the new record and its list, the list, or the page. */
@@ -7,7 +8,7 @@ const titleParts = ({ address, page, accountPage, resourceLabel, singular, recor
7
8
  if (!address || address.kind === "page") return [];
8
9
  const list = resourceLabel ? [resourceLabel] : [];
9
10
  if (address.kind === "list") return list;
10
- if (address.kind === "create") return [...singular ? [`New ${singular.toLowerCase()}`] : [], ...list];
11
+ if (address.kind === "create") return [...singular ? [text("title", singular)] : [], ...list];
11
12
  const record = recordTitle ?? (recordLoading ? void 0 : address.key);
12
13
  return [...record ? [record] : [], ...list];
13
14
  };
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import { createExportBuilder } from "./builder.js";
2
3
  //#region src/app/export/builder-port.ts
3
4
  const joined = (chunks) => {
@@ -36,7 +37,7 @@ const createWorkerPort = () => {
36
37
  worker.onmessage = (event) => waiting.shift()?.resolve(event.data.bytes);
37
38
  worker.onerror = (event) => {
38
39
  event.preventDefault();
39
- const error = /* @__PURE__ */ new Error(`The export could not be built: ${event.message}`);
40
+ const error = new Error(text("couldNotBuild", event.message));
40
41
  for (const entry of waiting.splice(0)) entry.reject(error);
41
42
  };
42
43
  return {