@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,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import { Spinner } from "../primitives/spinner.js";
2
3
  import { PageHeader } from "../app-shell/page-header.js";
3
4
  import { authMessage } from "../auth/auth-messages.js";
@@ -13,7 +14,7 @@ const StaffSignIns = ({ operator }) => {
13
14
  const [signIns, setSignIns] = useState();
14
15
  const [error, setError] = useState();
15
16
  useEffect(() => {
16
- session.staff.log().then(setSignIns, (failure) => setError(failure instanceof AuthError ? authMessage(failure) : "Could not read the staff sign-ins"));
17
+ session.staff.log().then(setSignIns, (failure) => setError(failure instanceof AuthError ? authMessage(failure) : text("couldNotReadStaffSignIns")));
17
18
  }, [session]);
18
19
  return /* @__PURE__ */ jsx(StaffSignInLog, {
19
20
  operator,
@@ -32,7 +33,7 @@ const SignInPolicyPage = () => {
32
33
  const [error, setError] = useState();
33
34
  const [notice, setNotice] = useState();
34
35
  useEffect(() => {
35
- session.signInPolicy.read().then(setState, (failure) => setError(failure instanceof AuthError ? authMessage(failure) : "Could not read the sign-in policy"));
36
+ session.signInPolicy.read().then(setState, (failure) => setError(failure instanceof AuthError ? authMessage(failure) : text("couldNotReadPolicy")));
36
37
  }, [session]);
37
38
  const save = async (policy) => {
38
39
  setBusy(true);
@@ -40,7 +41,7 @@ const SignInPolicyPage = () => {
40
41
  setNotice(void 0);
41
42
  try {
42
43
  setState(await session.signInPolicy.save(policy));
43
- setNotice("Saved. It applies to every sign-in from now on.");
44
+ setNotice(text("policySaved"));
44
45
  } catch (failure) {
45
46
  if (!(failure instanceof AuthError)) throw failure;
46
47
  setError(authMessage(failure));
@@ -50,8 +51,8 @@ const SignInPolicyPage = () => {
50
51
  return /* @__PURE__ */ jsxs("div", {
51
52
  className: "mx-auto flex w-full max-w-3xl flex-col gap-4 px-4 py-6 md:px-6",
52
53
  children: [/* @__PURE__ */ jsx(PageHeader, {
53
- title: "Sign-in policy",
54
- subtitle: "How people sign in to this app. Signed-in people keep their session, and are asked for what is newly required within 15 minutes."
54
+ title: text("signInPolicy"),
55
+ subtitle: text("policySubtitle")
55
56
  }), state ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(SignInPolicyForm, {
56
57
  state,
57
58
  busy,
@@ -64,7 +65,11 @@ const SignInPolicyPage = () => {
64
65
  children: error
65
66
  }) : /* @__PURE__ */ jsxs("div", {
66
67
  className: "flex items-center gap-2 text-muted-foreground",
67
- children: [/* @__PURE__ */ jsx(Spinner, {}), " Loading"]
68
+ children: [
69
+ /* @__PURE__ */ jsx(Spinner, {}),
70
+ " ",
71
+ text("loading")
72
+ ]
68
73
  })]
69
74
  });
70
75
  };
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import { Badge } from "../primitives/badge.js";
2
3
  import { authMessage } from "../auth/auth-messages.js";
3
4
  import { Button } from "../primitives/button.js";
@@ -23,8 +24,8 @@ const SignInProvidersSection = ({ providers, linked, onConnect, error: returned
23
24
  }
24
25
  };
25
26
  return /* @__PURE__ */ jsxs(AccountSection, {
26
- title: "Connected accounts",
27
- description: "Sign in with these instead of your password. Connecting one asks you to sign in there; its address may differ from yours here.",
27
+ title: text("connectedAccounts"),
28
+ description: text("connectedAccountsDescription"),
28
29
  children: [/* @__PURE__ */ jsx(SectionError, { message: error }), /* @__PURE__ */ jsx("ul", {
29
30
  className: "divide-y rounded-md border",
30
31
  children: providers.map((provider) => /* @__PURE__ */ jsxs("li", {
@@ -37,13 +38,13 @@ const SignInProvidersSection = ({ providers, linked, onConnect, error: returned
37
38
  }),
38
39
  linked.includes(provider.id) ? /* @__PURE__ */ jsx(Badge, {
39
40
  tone: "green",
40
- children: "Connected"
41
- }) : /* @__PURE__ */ jsxs(Button, {
41
+ children: text("connected")
42
+ }) : /* @__PURE__ */ jsx(Button, {
42
43
  size: "sm",
43
44
  loading: busy === provider.id,
44
45
  disabled: busy !== void 0,
45
46
  onClick: () => void connect(provider.id),
46
- children: ["Connect ", provider.name]
47
+ children: text("connect", provider.name)
47
48
  })
48
49
  ]
49
50
  }, provider.id))
@@ -1,27 +1,28 @@
1
+ import { text } from "./messages.js";
1
2
  import { Badge } from "../primitives/badge.js";
2
3
  import { formatDateTime } from "../format/date.js";
3
4
  import { AccountSection, SectionError } from "./account-section.js";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region src/account/staff-sign-in-log.tsx
6
- const stateOf = (entry, now) => entry.endedAt ? /* @__PURE__ */ jsxs(Badge, {
7
+ const stateOf = (entry, now) => entry.endedAt ? /* @__PURE__ */ jsx(Badge, {
7
8
  tone: "neutral",
8
- children: ["Stopped ", formatDateTime(Date.parse(entry.endedAt))]
9
- }) : Date.parse(entry.expiresAt) <= now ? /* @__PURE__ */ jsxs(Badge, {
9
+ children: text("stopped", formatDateTime(Date.parse(entry.endedAt)))
10
+ }) : Date.parse(entry.expiresAt) <= now ? /* @__PURE__ */ jsx(Badge, {
10
11
  tone: "neutral",
11
- children: ["Ended ", formatDateTime(Date.parse(entry.expiresAt))]
12
- }) : /* @__PURE__ */ jsxs(Badge, {
12
+ children: text("ended", formatDateTime(Date.parse(entry.expiresAt)))
13
+ }) : /* @__PURE__ */ jsx(Badge, {
13
14
  tone: "amber",
14
- children: ["Signed in until ", formatDateTime(Date.parse(entry.expiresAt))]
15
+ children: text("signedInUntil", formatDateTime(Date.parse(entry.expiresAt)))
15
16
  });
16
17
  /** The app's log of staff sign-ins, for admins: who signed in as whom, why, and when. */
17
18
  const StaffSignInLog = ({ signIns, operator, error, now = Date.now() }) => /* @__PURE__ */ jsxs(AccountSection, {
18
- title: "Staff sign-ins",
19
- description: `Each time staff of ${operator} signed in as someone here, newest first.`,
19
+ title: text("staffSignIns"),
20
+ description: text("staffSignInsDescription", operator),
20
21
  children: [
21
22
  /* @__PURE__ */ jsx(SectionError, { message: error }),
22
23
  signIns && signIns.length === 0 && /* @__PURE__ */ jsx("p", {
23
24
  className: "text-muted-foreground",
24
- children: "No staff has signed in as anyone yet."
25
+ children: text("noStaffSignIns")
25
26
  }),
26
27
  signIns && signIns.length > 0 && /* @__PURE__ */ jsx("ul", {
27
28
  className: "divide-y rounded-md border",
@@ -37,7 +38,7 @@ const StaffSignInLog = ({ signIns, operator, error, now = Date.now() }) => /* @_
37
38
  }),
38
39
  /* @__PURE__ */ jsx("span", {
39
40
  className: "text-muted-foreground",
40
- children: "as"
41
+ children: text("as")
41
42
  }),
42
43
  /* @__PURE__ */ jsx("span", {
43
44
  className: "font-medium break-all",
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import { useMemo } from "react";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
4
  import { encode } from "uqr";
@@ -18,7 +19,7 @@ const TotpQr = ({ uri, className }) => {
18
19
  return /* @__PURE__ */ jsxs("svg", {
19
20
  viewBox: `0 0 ${size} ${size}`,
20
21
  role: "img",
21
- "aria-label": "QR code for your authenticator app",
22
+ "aria-label": text("qrCode"),
22
23
  shapeRendering: "crispEdges",
23
24
  className,
24
25
  children: [/* @__PURE__ */ jsx("rect", {
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import { Badge } from "../primitives/badge.js";
2
3
  import { Button } from "../primitives/button.js";
3
4
  import { Dialog } from "../primitives/dialog.js";
@@ -9,9 +10,9 @@ import { useState } from "react";
9
10
  import { jsx, jsxs } from "react/jsx-runtime";
10
11
  //#region src/account/two-factor-section.tsx
11
12
  const offDescriptions = {
12
- allowed: "Ask for a second step after your password or an emailed sign-in code: a code from an authenticator app, or one emailed to you. A passkey needs no second step.",
13
- required: "This app requires two-factor authentication for every account. Turn it on to keep using the app.",
14
- forbidden: "Your admin turned two-factor authentication off for this app."
13
+ allowed: "twoFactorAllowed",
14
+ required: "twoFactorRequired",
15
+ forbidden: "twoFactorForbidden"
15
16
  };
16
17
  const TwoFactorSection = (props) => {
17
18
  const { rule, enabled, authenticatorApp, mail, needsPassword, onTurnOff, onNewBackupCodes, onChanged } = props;
@@ -19,14 +20,14 @@ const TwoFactorSection = (props) => {
19
20
  const close = () => setOpen(void 0);
20
21
  const status = enabled ? /* @__PURE__ */ jsx(Badge, {
21
22
  tone: "green",
22
- children: "On"
23
+ children: text("on")
23
24
  }) : rule === "required" ? /* @__PURE__ */ jsx(Badge, {
24
25
  tone: "amber",
25
- children: "Required"
26
- }) : /* @__PURE__ */ jsx(Badge, { children: "Off" });
27
- const description = !enabled ? offDescriptions[rule] : authenticatorApp ? `Signing in with a password or an emailed sign-in code also asks for a code from your authenticator app${mail ? ", or one emailed to you" : ""}. Backup codes work when you do not have the app.` : "Signing in with a password or an emailed sign-in code also asks for a code emailed to you.";
26
+ children: text("required")
27
+ }) : /* @__PURE__ */ jsx(Badge, { children: text("off") });
28
+ const description = !enabled ? text(offDescriptions[rule]) : authenticatorApp ? text(mail ? "twoFactorOnWithAppOrMail" : "twoFactorOnWithApp") : text("twoFactorOnWithMail");
28
29
  if (open?.kind === "setup") return /* @__PURE__ */ jsx(AccountSection, {
29
- title: "Two-factor authentication",
30
+ title: text("twoFactor"),
30
31
  status,
31
32
  description,
32
33
  children: /* @__PURE__ */ jsx("div", {
@@ -46,7 +47,7 @@ const TwoFactorSection = (props) => {
46
47
  })
47
48
  });
48
49
  return /* @__PURE__ */ jsxs(AccountSection, {
49
- title: "Two-factor authentication",
50
+ title: text("twoFactor"),
50
51
  status,
51
52
  description,
52
53
  children: [
@@ -59,32 +60,32 @@ const TwoFactorSection = (props) => {
59
60
  kind: "setup",
60
61
  appOnly: false
61
62
  }),
62
- children: "Turn on"
63
+ children: text("turnOn")
63
64
  }),
64
65
  enabled && !authenticatorApp && rule !== "forbidden" && /* @__PURE__ */ jsx(Button, {
65
66
  onClick: () => setOpen({
66
67
  kind: "setup",
67
68
  appOnly: true
68
69
  }),
69
- children: "Add an authenticator app"
70
+ children: text("addAuthenticator")
70
71
  }),
71
72
  enabled && authenticatorApp && /* @__PURE__ */ jsx(Button, {
72
73
  onClick: () => setOpen({ kind: "new-codes" }),
73
- children: "New backup codes"
74
+ children: text("newBackupCodes")
74
75
  }),
75
76
  enabled && /* @__PURE__ */ jsx(Button, {
76
77
  variant: "danger",
77
78
  disabled: rule === "required",
78
- title: rule === "required" ? "This app requires two-factor authentication." : void 0,
79
+ title: rule === "required" ? text("twoFactorIsRequired") : void 0,
79
80
  onClick: () => setOpen({ kind: "turn-off" }),
80
- children: "Turn off"
81
+ children: text("turnOff")
81
82
  })
82
83
  ]
83
84
  }),
84
85
  open?.kind === "turn-off" && /* @__PURE__ */ jsx(PasswordDialog, {
85
- title: "Turn off two-factor authentication?",
86
- description: "Signing in then needs only your password or an emailed code. Your backup codes stop working.",
87
- confirmLabel: "Turn off",
86
+ title: text("turnOffTitle"),
87
+ description: text("turnOffDescription"),
88
+ confirmLabel: text("turnOff"),
88
89
  danger: true,
89
90
  needsPassword,
90
91
  onClose: close,
@@ -95,9 +96,9 @@ const TwoFactorSection = (props) => {
95
96
  }
96
97
  }),
97
98
  open?.kind === "new-codes" && /* @__PURE__ */ jsx(PasswordDialog, {
98
- title: "Make new backup codes?",
99
- description: "Your current backup codes stop working, and you get ten new ones.",
100
- confirmLabel: "Make new codes",
99
+ title: text("newCodesTitle"),
100
+ description: text("newCodesDescription"),
101
+ confirmLabel: text("makeNewCodes"),
101
102
  needsPassword,
102
103
  onClose: close,
103
104
  onConfirm: async (password) => setOpen({
@@ -106,13 +107,13 @@ const TwoFactorSection = (props) => {
106
107
  })
107
108
  }),
108
109
  open?.kind === "codes" && /* @__PURE__ */ jsx(Dialog, {
109
- title: "Your new backup codes",
110
- description: "Keep them somewhere safe: each one signs you in once if you lose your phone. They are not shown again.",
110
+ title: text("yourNewCodes"),
111
+ description: text("keepCodesSafe"),
111
112
  onClose: close,
112
113
  actions: /* @__PURE__ */ jsx(Button, {
113
114
  variant: "primary",
114
115
  onClick: close,
115
- children: "I saved my backup codes"
116
+ children: text("savedCodes")
116
117
  }),
117
118
  children: /* @__PURE__ */ jsx(BackupCodes, { codes: open.codes })
118
119
  })
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import { cn } from "../lib/cn.js";
2
3
  import { Input } from "../primitives/input.js";
3
4
  import { authMessage } from "../auth/auth-messages.js";
@@ -9,14 +10,14 @@ import { useState } from "react";
9
10
  import { AuthError } from "@protobase/client";
10
11
  import { jsx, jsxs } from "react/jsx-runtime";
11
12
  //#region src/account/two-factor-setup.tsx
12
- const choices = [{
13
+ const choices = () => [{
13
14
  value: "app",
14
- label: "Authenticator app",
15
- description: "A code from an app such as Google Authenticator, Microsoft Authenticator or 1Password. Comes with backup codes."
15
+ label: text("authenticatorApp"),
16
+ description: text("authenticatorAppDescription")
16
17
  }, {
17
18
  value: "email",
18
- label: "Emailed code",
19
- description: "A code mailed to your address each time you sign in with a password or an emailed sign-in code."
19
+ label: text("emailedCode"),
20
+ description: text("emailedCodeDescription")
20
21
  }];
21
22
  /** Turns on two-factor authentication: choose the app or emailed codes, confirm the password, scan, and keep the backup codes. */
22
23
  const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfirmApp, onEmailedCodes, onDone, onCancel }) => {
@@ -26,7 +27,7 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
26
27
  const [code, setCode] = useState("");
27
28
  const [busy, setBusy] = useState(false);
28
29
  const [error, setError] = useState();
29
- const offered = offerEmailedCodes ? choices : choices.filter((option) => option.value === "app");
30
+ const offered = offerEmailedCodes ? choices() : choices().filter((option) => option.value === "app");
30
31
  const attempt = async (action) => {
31
32
  setBusy(true);
32
33
  setError(void 0);
@@ -66,14 +67,14 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
66
67
  children: [
67
68
  /* @__PURE__ */ jsx("p", {
68
69
  className: "text-muted-foreground",
69
- children: "Two-factor authentication is on. Keep these backup codes somewhere safe: each one signs you in once if you lose your phone. They are not shown again."
70
+ children: text("twoFactorIsOn")
70
71
  }),
71
72
  /* @__PURE__ */ jsx(BackupCodes, { codes: step.codes }),
72
73
  /* @__PURE__ */ jsx(Button, {
73
74
  variant: "primary",
74
75
  onClick: onDone,
75
76
  className: "min-h-10",
76
- children: "I saved my backup codes"
77
+ children: text("savedCodes")
77
78
  })
78
79
  ]
79
80
  });
@@ -86,7 +87,7 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
86
87
  children: [
87
88
  /* @__PURE__ */ jsx("p", {
88
89
  className: "text-muted-foreground",
89
- children: "Scan this code with your authenticator app, then enter the 6-digit code it shows."
90
+ children: text("scanCode")
90
91
  }),
91
92
  /* @__PURE__ */ jsxs("div", {
92
93
  className: "flex flex-col items-center gap-2",
@@ -95,7 +96,7 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
95
96
  className: "size-44 rounded-md border"
96
97
  }), /* @__PURE__ */ jsxs("p", {
97
98
  className: "text-center text-xs text-muted-foreground",
98
- children: ["Can't scan it? Enter this key in the app:", /* @__PURE__ */ jsx("span", {
99
+ children: [text("cannotScan"), /* @__PURE__ */ jsx("span", {
99
100
  className: "mt-1 block break-all font-mono text-body text-foreground",
100
101
  children: totpKey(step.setup.totpURI)
101
102
  })]
@@ -103,7 +104,7 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
103
104
  }),
104
105
  /* @__PURE__ */ jsxs("label", {
105
106
  className: "flex flex-col gap-1.5 font-medium",
106
- children: ["Code from the app", /* @__PURE__ */ jsx(OtpInput, {
107
+ children: [text("codeFromApp"), /* @__PURE__ */ jsx(OtpInput, {
107
108
  name: "code",
108
109
  required: true,
109
110
  autoFocus: true,
@@ -119,13 +120,13 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
119
120
  type: "submit",
120
121
  loading: busy,
121
122
  className: "min-h-10",
122
- children: "Turn on"
123
+ children: text("turnOn")
123
124
  }),
124
125
  onCancel && /* @__PURE__ */ jsx(Button, {
125
126
  variant: "ghost",
126
127
  onClick: onCancel,
127
128
  className: "min-h-10",
128
- children: "Cancel"
129
+ children: text("cancel")
129
130
  })
130
131
  ]
131
132
  });
@@ -138,7 +139,7 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
138
139
  children: [
139
140
  /* @__PURE__ */ jsx("div", {
140
141
  role: "radiogroup",
141
- "aria-label": "Second step",
142
+ "aria-label": text("secondStep"),
142
143
  className: "flex flex-col gap-2",
143
144
  children: offered.map((option) => /* @__PURE__ */ jsxs("button", {
144
145
  type: "button",
@@ -157,7 +158,7 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
157
158
  }),
158
159
  needsPassword && /* @__PURE__ */ jsxs("label", {
159
160
  className: "flex flex-col gap-1.5 font-medium",
160
- children: ["Your password", /* @__PURE__ */ jsx(Input, {
161
+ children: [text("yourPassword"), /* @__PURE__ */ jsx(Input, {
161
162
  type: "password",
162
163
  name: "password",
163
164
  autoComplete: "current-password",
@@ -174,13 +175,13 @@ const TwoFactorSetup = ({ offerEmailedCodes, needsPassword, onStartApp, onConfir
174
175
  type: "submit",
175
176
  loading: busy,
176
177
  className: "min-h-10",
177
- children: "Continue"
178
+ children: text("continue")
178
179
  }),
179
180
  onCancel && /* @__PURE__ */ jsx(Button, {
180
181
  variant: "ghost",
181
182
  onClick: onCancel,
182
183
  className: "min-h-10",
183
- children: "Cancel"
184
+ children: text("cancel")
184
185
  })
185
186
  ]
186
187
  });
@@ -1,6 +1,7 @@
1
1
  import { cn } from "../lib/cn.js";
2
2
  import { Button } from "../primitives/button.js";
3
3
  import { Dialog } from "../primitives/dialog.js";
4
+ import { text } from "./messages.js";
4
5
  import { useState } from "react";
5
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
7
  //#region src/action-card/action-card.tsx
@@ -76,7 +77,7 @@ const ActionCard = ({ title, tone = "neutral", badge, note, actions = [], onActi
76
77
  onClose: () => setConfirming(void 0),
77
78
  actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
78
79
  onClick: () => setConfirming(void 0),
79
- children: "Cancel"
80
+ children: text("cancel")
80
81
  }), /* @__PURE__ */ jsx(Button, {
81
82
  variant: confirming.style === "danger" ? "danger" : "primary",
82
83
  onClick: () => {
@@ -0,0 +1,8 @@
1
+ import { defineMessages } from "../locale/messages.js";
2
+ //#region src/action-card/messages.ts
3
+ const text = defineMessages({
4
+ en: { cancel: "Cancel" },
5
+ nl: { cancel: "Annuleren" }
6
+ });
7
+ //#endregion
8
+ export { text };
@@ -6,6 +6,7 @@ import { formatDayShort } from "../format/date.js";
6
6
  import { activitySeries } from "../mocks/activity.js";
7
7
  import { halfOverHalfDelta, totalCount } from "./activity-math.js";
8
8
  import { ActivityTooltip } from "./activity-tooltip.js";
9
+ import { text } from "./messages.js";
9
10
  import { useState } from "react";
10
11
  import { jsx, jsxs } from "react/jsx-runtime";
11
12
  import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
@@ -54,10 +55,10 @@ const ActivityChart = ({ title = "Orders created", noun = "orders", defaultGranu
54
55
  onChange: setGranularity,
55
56
  options: [{
56
57
  value: "day",
57
- label: "Day"
58
+ label: text("day")
58
59
  }, {
59
60
  value: "week",
60
- label: "Week"
61
+ label: text("week")
61
62
  }]
62
63
  })]
63
64
  }), /* @__PURE__ */ jsx("div", {
@@ -0,0 +1,14 @@
1
+ import { defineMessages } from "../locale/messages.js";
2
+ //#region src/activity-chart/messages.ts
3
+ const text = defineMessages({
4
+ en: {
5
+ day: "Day",
6
+ week: "Week"
7
+ },
8
+ nl: {
9
+ day: "Dag",
10
+ week: "Week"
11
+ }
12
+ });
13
+ //#endregion
14
+ export { text };
package/dist/app/app.d.ts CHANGED
@@ -2,8 +2,8 @@ import { SidebarMode } from "../app-shell/sidebar-mode.js";
2
2
  import "../app-shell/index.js";
3
3
  import { ProjectUi } from "./pages/project-ui.js";
4
4
  import { PluginLoader } from "../plugins/load-plugin.js";
5
- import { AssistantClient, AuthSession, Client, RuntimeClient } from "@protobase/client";
6
5
  import { Locale } from "@protobase/schema/internal";
6
+ import { AssistantClient, AuthSession, Client, RuntimeClient } from "@protobase/client";
7
7
  //#region src/app/app.d.ts
8
8
  export type AppProps = {
9
9
  /** Where `/api/v1` lives. Defaults to the current origin. */
package/dist/app/app.js CHANGED
@@ -1,18 +1,21 @@
1
- import { accountMenuItems } from "../account/account-pages.js";
2
1
  import { setFallbackLocale } from "../locale/active-locale.js";
2
+ import { accountMenuItems } from "../account/account-pages.js";
3
3
  import { AppShell } from "../app-shell/app-shell.js";
4
4
  import { AuthProvider, useAuth } from "../auth/auth-provider.js";
5
5
  import { AccountSecurityPage } from "../account/account-security-page.js";
6
6
  import { SignInPolicyPage } from "../account/sign-in-policy-page.js";
7
7
  import { ApiProvider } from "../data/api-provider.js";
8
+ import { text } from "./messages.js";
8
9
  import { Router, useRouter } from "./router.js";
10
+ import { slotted } from "../locale/slotted.js";
9
11
  import { useSignInAddress } from "../auth/use-sign-in-address.js";
10
- import { managesOrganization, organizationMenuItems, organizationPageTitles } from "../organizations/organization-paths.js";
12
+ import { managesOrganization, organizationMenuItems, organizationPageTitle } from "../organizations/organization-paths.js";
11
13
  import { startErrorReporting } from "./error-reporting.js";
12
14
  import { CustomBoundary } from "./pages/custom-boundary.js";
13
15
  import { PluginSourceProvider } from "../plugins/plugin-source.js";
14
16
  import { AuthGate } from "../auth/auth-gate.js";
15
17
  import { isAdmin, userToShell } from "../auth/user-to-shell.js";
18
+ import { AuthLocale } from "../auth/auth-locale.js";
16
19
  import { sourceStatusOf } from "../data/with-sources.js";
17
20
  import { useLiveUpdates } from "../data/use-live-updates.js";
18
21
  import { useOpenedRecord } from "../data/use-record.js";
@@ -137,8 +140,8 @@ const Routes = ({ workspace, sidebarMode, assistant, runtime }) => {
137
140
  const organizations = useOrganizations(Boolean(organizationSettings && user));
138
141
  const current = organizations.current;
139
142
  const outsideOrganizations = Boolean(organizationSettings) && current !== void 0 && !current.organization;
140
- const organizationPage = organizationSettings && user ? organizationPageTitles[path] : void 0;
141
- const accountPage = !user ? void 0 : path === "/-/account" ? "Sign-in & security" : path === "/-/sign-in-policy" ? "Sign-in policy" : organizationPage;
143
+ const organizationPage = organizationSettings && user ? organizationPageTitle(path) : void 0;
144
+ const accountPage = !user ? void 0 : path === "/-/account" ? text("signInSecurity") : path === "/-/sign-in-policy" ? text("signInPolicy") : organizationPage;
142
145
  const resourceLabel = view?.names?.plural ?? (resource && humanize(resource));
143
146
  const breadcrumb = accountPage ? [accountPage] : breadcrumbFor({
144
147
  basePath,
@@ -160,31 +163,27 @@ const Routes = ({ workspace, sidebarMode, assistant, runtime }) => {
160
163
  recordLoading: titleLoading
161
164
  }), meta.appName));
162
165
  const content = user && path === "/-/account" ? /* @__PURE__ */ jsx(AccountSecurityPage, { email: user.email }) : user && path === "/-/sign-in-policy" ? admin ? /* @__PURE__ */ jsx(SignInPolicyPage, {}) : /* @__PURE__ */ jsx(Notice, {
163
- title: "Admins only",
164
- children: "Only an admin can change how people sign in."
166
+ title: text("adminsOnly"),
167
+ children: text("onlyAdminPolicy")
165
168
  }) : organizationPage && path === "/-/organization" ? /* @__PURE__ */ jsx(OrganizationPage, {
166
169
  current,
167
170
  basePath,
168
171
  onChanged: organizations.reload
169
172
  }) : organizationPage && (path === "/-/organization/members" || path === "/-/organization/invitations") ? !managesOrganization(current) ? /* @__PURE__ */ jsx(Notice, {
170
- title: "Owners and admins only",
171
- children: "Only the organization's owners and admins manage its members."
173
+ title: text("ownersOnly"),
174
+ children: text("onlyOwners")
172
175
  }) : path === "/-/organization/members" ? /* @__PURE__ */ jsx(MembersPage, { current }) : /* @__PURE__ */ jsx(InvitationsPage, { current }) : organizationPage && path === "/-/organizations" || outsideOrganizations ? /* @__PURE__ */ jsx(OrganizationsPage, {
173
176
  state: organizations,
174
177
  basePath
175
178
  }) : !address ? path === "/" ? /* @__PURE__ */ jsx(Notice, {
176
- title: "Choose a resource",
177
- children: "Pick one from the sidebar."
179
+ title: text("chooseResource"),
180
+ children: text("pickFromSidebar")
178
181
  }) : /* @__PURE__ */ jsx(Notice, {
179
- title: "Not found",
180
- children: "There is nothing at this address."
181
- }) : address.kind === "page" ? page ? /* @__PURE__ */ jsx(ComposedPage, { name: page.name }, page.name) : /* @__PURE__ */ jsxs(Notice, {
182
- title: "Not found",
183
- children: [
184
- "There is no page called ",
185
- address.page,
186
- "."
187
- ]
182
+ title: text("notFound"),
183
+ children: text("nothingHere")
184
+ }) : address.kind === "page" ? page ? /* @__PURE__ */ jsx(ComposedPage, { name: page.name }, page.name) : /* @__PURE__ */ jsx(Notice, {
185
+ title: text("notFound"),
186
+ children: slotted(text("noPage"), address.page)
188
187
  }) : drawnFrom && drawnFrom.state !== "ready" ? /* @__PURE__ */ jsx(SourceNotice, { status: drawnFrom }) : address.kind === "create" ? /* @__PURE__ */ jsx(CreateRoute, {
189
188
  resource: address.resource,
190
189
  values: address.values
@@ -315,7 +314,7 @@ const App = ({ auth, workspace, basePath, initialUrl, pluginLoader, locale, ...r
315
314
  initialUrl,
316
315
  children: /* @__PURE__ */ jsx(PluginSourceProvider, {
317
316
  ...pluginLoader && { loader: pluginLoader },
318
- children: /* @__PURE__ */ jsx(PublicFormGate, {
317
+ children: /* @__PURE__ */ jsx(AuthLocale, { children: /* @__PURE__ */ jsx(PublicFormGate, {
319
318
  baseUrl: rest.baseUrl,
320
319
  client: rest.client,
321
320
  ui: rest.ui,
@@ -326,7 +325,7 @@ const App = ({ auth, workspace, basePath, initialUrl, pluginLoader, locale, ...r
326
325
  ...rest
327
326
  })
328
327
  })
329
- })
328
+ }) })
330
329
  })
331
330
  })
332
331
  }) });
@@ -1,4 +1,5 @@
1
1
  import { Button } from "../primitives/button.js";
2
+ import { text } from "./messages.js";
2
3
  import { AssistantDock } from "../assistant-dock/assistant-dock.js";
3
4
  import { useAssistant } from "../assistant-dock/use-assistant.js";
4
5
  import { useAssistantClient } from "../assistant-dock/use-assistant-client.js";
@@ -14,7 +15,7 @@ const AssistantButton = ({ open, onToggle }) => /* @__PURE__ */ jsxs(Button, {
14
15
  className: "max-md:size-9 max-md:p-0",
15
16
  children: [/* @__PURE__ */ jsx(Sparkles, { className: "size-3.5" }), /* @__PURE__ */ jsx("span", {
16
17
  className: "max-md:sr-only",
17
- children: "Assistant"
18
+ children: text("assistant")
18
19
  })]
19
20
  });
20
21
  const ConnectedDock = ({ client, page, onClose }) => {
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import "@protobase/client";
2
3
  //#region src/app/batch-failure.ts
3
4
  const label = (op) => {
@@ -8,7 +9,7 @@ const label = (op) => {
8
9
  const describeBatchFailure = (error, ops) => {
9
10
  const index = error.operation;
10
11
  const op = index === void 0 ? void 0 : ops[index];
11
- return op ? `Operation ${index + 1} (${label(op)}) failed: ${error.message} Nothing was saved.` : `${error.message} Nothing was saved.`;
12
+ return op ? text("operationFailed", index + 1, label(op), error.message) : text("nothingSaved", error.message);
12
13
  };
13
14
  /** The same error with the failing operation named in its message, keeping its class so a 412 stays a 412. */
14
15
  const nameFailingOperation = (error, ops) => {
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  import { appPath } from "@protobase/schema";
2
3
  //#region src/app/breadcrumb-for.ts
3
4
  /** Group, then the page or resource list, then the record (or "New"): each with a page of its own links to it. */
@@ -10,7 +11,7 @@ const breadcrumbFor = ({ basePath, address, group, page, resourceLabel, recordTi
10
11
  page: page.name
11
12
  }, basePath)
12
13
  }];
13
- if (!address || address.kind === "page") return ["Admin"];
14
+ if (!address || address.kind === "page") return [text("admin")];
14
15
  const resource = resourceLabel ? [{
15
16
  label: resourceLabel,
16
17
  href: appPath({
@@ -22,10 +23,10 @@ const breadcrumbFor = ({ basePath, address, group, page, resourceLabel, recordTi
22
23
  if (address.kind === "list") return [...groupCrumb, ...resource];
23
24
  const href = appPath(address, basePath);
24
25
  const record = address.kind === "create" ? {
25
- label: "New",
26
+ label: text("new"),
26
27
  href
27
28
  } : recordTitle === void 0 && recordLoading ? {
28
- label: "Loading record",
29
+ label: text("loadingRecord"),
29
30
  href,
30
31
  loading: true
31
32
  } : {
@@ -1,4 +1,5 @@
1
1
  import { formatTag } from "../../locale/active-locale.js";
2
+ import { text } from "./messages.js";
2
3
  import { createWhere, enumLabel, printFilter } from "@protobase/schema";
3
4
  //#region src/app/charts/chart-groups.ts
4
5
  const where$1 = createWhere();
@@ -12,9 +13,9 @@ const colorOf = (field, hints, value, index) => {
12
13
  return slot(index);
13
14
  };
14
15
  const labelOf = (field, hints, group) => {
15
- if (group.value === null) return "Not set";
16
+ if (group.value === null) return text("notSet");
16
17
  if (field.type === "enum") return enumLabel(String(group.value), hints?.valueLabels);
17
- if (field.type === "boolean") return group.value ? "Yes" : "No";
18
+ if (field.type === "boolean") return group.value ? text("yes") : text("no");
18
19
  return group.label ?? String(group.value);
19
20
  };
20
21
  /** The records of one group: the chart's own filter and the group's value. */