@byline/host-tanstack-start 2.5.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/dist/admin-shell/admin-roles/container.js +38 -24
  2. package/dist/admin-shell/admin-roles/delete.js +9 -7
  3. package/dist/admin-shell/admin-roles/list.js +20 -16
  4. package/dist/admin-shell/admin-users/container.js +79 -56
  5. package/dist/admin-shell/admin-users/delete.js +10 -8
  6. package/dist/admin-shell/admin-users/list.js +27 -18
  7. package/dist/admin-shell/chrome/admin-app-bar.js +5 -2
  8. package/dist/admin-shell/chrome/breadcrumbs/breadcrumbs.js +3 -1
  9. package/dist/admin-shell/chrome/dashboard.js +13 -11
  10. package/dist/admin-shell/chrome/hamburger.js +3 -1
  11. package/dist/admin-shell/chrome/menu-drawer.js +7 -5
  12. package/dist/admin-shell/chrome/preview-toggle.js +5 -3
  13. package/dist/admin-shell/chrome/route-error.d.ts +3 -2
  14. package/dist/admin-shell/chrome/route-error.js +29 -22
  15. package/dist/admin-shell/chrome/sign-in-page.d.ts +16 -4
  16. package/dist/admin-shell/chrome/sign-in-page.js +38 -13
  17. package/dist/admin-shell/chrome/sign-in-page.module.js +1 -0
  18. package/dist/admin-shell/chrome/sign-in-page_module.css +8 -1
  19. package/dist/admin-shell/collections/api.js +6 -5
  20. package/dist/admin-shell/collections/create.js +12 -4
  21. package/dist/admin-shell/collections/edit.js +112 -37
  22. package/dist/admin-shell/collections/history.js +17 -12
  23. package/dist/admin-shell/collections/list.js +18 -13
  24. package/dist/admin-shell/collections/preview-link.d.ts +1 -10
  25. package/dist/admin-shell/collections/preview-link.js +9 -11
  26. package/dist/admin-shell/collections/resolve-preview-url.d.ts +34 -0
  27. package/dist/admin-shell/collections/resolve-preview-url.js +17 -0
  28. package/dist/admin-shell/collections/restore-version-modal.js +13 -14
  29. package/dist/admin-shell/collections/tanstack-navigation-guard.d.ts +1 -1
  30. package/dist/admin-shell/collections/view-menu.js +7 -5
  31. package/dist/i18n/index.d.ts +19 -0
  32. package/dist/i18n/index.js +4 -0
  33. package/dist/i18n/locale-cookie.d.ts +17 -0
  34. package/dist/i18n/locale-cookie.js +26 -0
  35. package/dist/i18n/locale-definitions.d.ts +29 -0
  36. package/dist/i18n/locale-definitions.js +27 -0
  37. package/dist/i18n/resolve-locale.d.ts +20 -0
  38. package/dist/i18n/resolve-locale.js +43 -0
  39. package/dist/i18n/server-translator.d.ts +33 -0
  40. package/dist/i18n/server-translator.js +19 -0
  41. package/dist/integrations/byline-admin-services.js +2 -0
  42. package/dist/integrations/byline-field-services.d.ts +3 -3
  43. package/dist/routes/create-admin-account-route.js +6 -3
  44. package/dist/routes/create-admin-dashboard-route.js +3 -1
  45. package/dist/routes/create-admin-layout-route.js +48 -25
  46. package/dist/routes/create-admin-permissions-route.js +4 -2
  47. package/dist/routes/create-admin-role-edit-route.js +5 -3
  48. package/dist/routes/create-admin-roles-list-route.js +4 -2
  49. package/dist/routes/create-admin-user-edit-route.js +5 -3
  50. package/dist/routes/create-admin-users-list-route.js +4 -2
  51. package/dist/routes/create-collection-api-route.js +5 -3
  52. package/dist/routes/create-collection-create-route.js +4 -2
  53. package/dist/routes/create-collection-edit-route.js +4 -2
  54. package/dist/routes/create-collection-history-route.js +5 -3
  55. package/dist/routes/create-collection-list-route.js +11 -5
  56. package/dist/routes/create-sign-in-route.js +10 -1
  57. package/dist/server-fns/admin-account/change-password.d.ts +1 -0
  58. package/dist/server-fns/admin-account/get.d.ts +1 -0
  59. package/dist/server-fns/admin-account/update.d.ts +1 -0
  60. package/dist/server-fns/admin-users/create.d.ts +1 -0
  61. package/dist/server-fns/admin-users/get.d.ts +1 -0
  62. package/dist/server-fns/admin-users/list.d.ts +1 -0
  63. package/dist/server-fns/admin-users/set-password.d.ts +1 -0
  64. package/dist/server-fns/admin-users/update.d.ts +1 -0
  65. package/dist/server-fns/auth/sign-in.js +18 -0
  66. package/dist/server-fns/i18n/get-active-locale.d.ts +8 -0
  67. package/dist/server-fns/i18n/get-active-locale.js +6 -0
  68. package/dist/server-fns/i18n/index.d.ts +10 -0
  69. package/dist/server-fns/i18n/index.js +2 -0
  70. package/dist/server-fns/i18n/set-locale.d.ts +25 -0
  71. package/dist/server-fns/i18n/set-locale.js +42 -0
  72. package/package.json +16 -7
  73. package/src/admin-shell/admin-roles/container.tsx +41 -31
  74. package/src/admin-shell/admin-roles/delete.tsx +10 -11
  75. package/src/admin-shell/admin-roles/list.tsx +29 -16
  76. package/src/admin-shell/admin-users/container.tsx +77 -50
  77. package/src/admin-shell/admin-users/delete.tsx +11 -12
  78. package/src/admin-shell/admin-users/list.tsx +39 -18
  79. package/src/admin-shell/chrome/admin-app-bar.tsx +5 -2
  80. package/src/admin-shell/chrome/breadcrumbs/breadcrumbs.tsx +3 -1
  81. package/src/admin-shell/chrome/dashboard.tsx +9 -3
  82. package/src/admin-shell/chrome/hamburger.tsx +3 -1
  83. package/src/admin-shell/chrome/menu-drawer.tsx +7 -5
  84. package/src/admin-shell/chrome/preview-toggle.tsx +6 -4
  85. package/src/admin-shell/chrome/route-error.tsx +39 -26
  86. package/src/admin-shell/chrome/sign-in-page.module.css +10 -1
  87. package/src/admin-shell/chrome/sign-in-page.tsx +46 -12
  88. package/src/admin-shell/collections/api.tsx +5 -1
  89. package/src/admin-shell/collections/create.tsx +10 -4
  90. package/src/admin-shell/collections/edit.tsx +79 -72
  91. package/src/admin-shell/collections/history.tsx +18 -12
  92. package/src/admin-shell/collections/list.tsx +25 -14
  93. package/src/admin-shell/collections/preview-link.tsx +20 -33
  94. package/src/admin-shell/collections/resolve-preview-url.test.node.ts +167 -0
  95. package/src/admin-shell/collections/resolve-preview-url.ts +67 -0
  96. package/src/admin-shell/collections/restore-version-modal.tsx +11 -12
  97. package/src/admin-shell/collections/tanstack-navigation-guard.ts +1 -1
  98. package/src/admin-shell/collections/view-menu.tsx +9 -5
  99. package/src/i18n/index.ts +26 -0
  100. package/src/i18n/locale-cookie.ts +68 -0
  101. package/src/i18n/locale-definitions.ts +48 -0
  102. package/src/i18n/resolve-locale.ts +96 -0
  103. package/src/i18n/server-translator.ts +60 -0
  104. package/src/integrations/byline-admin-services.ts +2 -0
  105. package/src/integrations/byline-field-services.ts +7 -3
  106. package/src/routes/create-admin-account-route.tsx +6 -4
  107. package/src/routes/create-admin-dashboard-route.tsx +5 -1
  108. package/src/routes/create-admin-layout-route.tsx +53 -20
  109. package/src/routes/create-admin-permissions-route.tsx +4 -2
  110. package/src/routes/create-admin-role-edit-route.tsx +5 -3
  111. package/src/routes/create-admin-roles-list-route.tsx +5 -2
  112. package/src/routes/create-admin-user-edit-route.tsx +5 -3
  113. package/src/routes/create-admin-users-list-route.tsx +4 -2
  114. package/src/routes/create-collection-api-route.tsx +5 -3
  115. package/src/routes/create-collection-create-route.tsx +7 -2
  116. package/src/routes/create-collection-edit-route.tsx +4 -2
  117. package/src/routes/create-collection-history-route.tsx +5 -3
  118. package/src/routes/create-collection-list-route.tsx +8 -10
  119. package/src/routes/create-sign-in-route.tsx +14 -1
  120. package/src/server-fns/auth/sign-in.ts +45 -0
  121. package/src/server-fns/i18n/get-active-locale.ts +26 -0
  122. package/src/server-fns/i18n/index.ts +11 -0
  123. package/src/server-fns/i18n/set-locale.ts +103 -0
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
+ import { useTranslation } from "@byline/i18n/react";
4
5
  import { Dropdown, EllipsisIcon } from "@byline/ui/react";
5
6
  import classnames from "classnames";
6
7
  import { Link } from "../loose-router.js";
@@ -191,6 +192,7 @@ function ChevronIcon({ isLeaf = false }) {
191
192
  });
192
193
  }
193
194
  function OverflowDropdown({ items }) {
195
+ const { t } = useTranslation('byline-admin');
194
196
  return /*#__PURE__*/ jsxs("li", {
195
197
  className: classnames('byline-breadcrumbs-item', breadcrumbs_module.item),
196
198
  children: [
@@ -198,7 +200,7 @@ function OverflowDropdown({ items }) {
198
200
  /*#__PURE__*/ jsxs(Dropdown.Root, {
199
201
  children: [
200
202
  /*#__PURE__*/ jsx(Dropdown.Trigger, {
201
- "aria-label": "Show hidden breadcrumbs",
203
+ "aria-label": t('chrome.breadcrumbs.showHiddenAriaLabel'),
202
204
  className: classnames('byline-breadcrumbs-overflow-trigger', breadcrumbs_module.overflowTrigger),
203
205
  children: /*#__PURE__*/ jsx(EllipsisIcon, {
204
206
  className: classnames('byline-breadcrumbs-overflow-icon', breadcrumbs_module.overflowIcon)
@@ -1,5 +1,6 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { getClientConfig, getWorkflowStatuses } from "@byline/core";
3
+ import { useTranslation } from "@byline/i18n/react";
3
4
  import { Card, Container, Section } from "@byline/ui/react";
4
5
  import classnames from "classnames";
5
6
  import dashboard_module from "./dashboard.module.js";
@@ -50,6 +51,7 @@ function StatTile({ ws, count, collectionPath }) {
50
51
  }
51
52
  function AdminDashboard({ statsMap }) {
52
53
  const config = getClientConfig();
54
+ const { t } = useTranslation('byline-admin');
53
55
  return /*#__PURE__*/ jsx(Section, {
54
56
  children: /*#__PURE__*/ jsx(Container, {
55
57
  children: /*#__PURE__*/ jsx("div", {
@@ -77,18 +79,19 @@ function AdminDashboard({ statsMap }) {
77
79
  className: classnames('byline-dashboard-title-text', dashboard_module.titleText),
78
80
  children: collection.labels.plural
79
81
  }),
80
- /*#__PURE__*/ jsxs("span", {
82
+ /*#__PURE__*/ jsx("span", {
81
83
  className: classnames('muted byline-dashboard-title-meta', dashboard_module.titleMeta),
82
- children: [
83
- total,
84
- " total"
85
- ]
84
+ children: t('dashboard.totalCount', {
85
+ count: total
86
+ })
86
87
  })
87
88
  ]
88
89
  }),
89
90
  /*#__PURE__*/ jsx(Card.Description, {
90
91
  className: "muted",
91
- children: `${collection.labels.plural} collection`
92
+ children: t("dashboard.collectionDescription", {
93
+ label: collection.labels.plural
94
+ })
92
95
  })
93
96
  ]
94
97
  })
@@ -111,11 +114,10 @@ function AdminDashboard({ statsMap }) {
111
114
  collection: collection.path
112
115
  },
113
116
  className: classnames('byline-dashboard-empty-link', dashboard_module.emptyLink),
114
- children: /*#__PURE__*/ jsxs("p", {
115
- children: [
116
- collection.labels.plural,
117
- " collection"
118
- ]
117
+ children: /*#__PURE__*/ jsx("p", {
118
+ children: t("dashboard.collectionDescription", {
119
+ label: collection.labels.plural
120
+ })
119
121
  })
120
122
  })
121
123
  })
@@ -1,10 +1,12 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
+ import { useTranslation } from "@byline/i18n/react";
3
4
  import classnames from "classnames";
4
5
  import hamburger_module from "./hamburger.module.js";
5
6
  import { useAdminMenu } from "./menu-provider.js";
6
7
  function Hamburger({ className, color = 'bg-white before:bg-white after:bg-white', activeBorderColor: _activeBorderColor, ...other }) {
7
8
  const { toggleDrawer } = useAdminMenu();
9
+ const { t } = useTranslation('byline-admin');
8
10
  const drawerOpen = false;
9
11
  const handleClick = (event)=>{
10
12
  if (null != event) event.stopPropagation();
@@ -14,7 +16,7 @@ function Hamburger({ className, color = 'bg-white before:bg-white after:bg-white
14
16
  onClick: handleClick,
15
17
  className: classnames('byline-admin-hamburger', hamburger_module.button, `component--hamburger ${drawerOpen ? 'is_active' : ''}`, className),
16
18
  tabIndex: 0,
17
- "aria-label": "Open admin menu",
19
+ "aria-label": t('chrome.menu.openAriaLabel'),
18
20
  "aria-controls": "admin-menu",
19
21
  "aria-haspopup": "true",
20
22
  ...other,
@@ -3,6 +3,7 @@ import { useRouterState } from "@tanstack/react-router";
3
3
  import { ADMIN_PERMISSIONS_ABILITIES } from "@byline/admin/admin-permissions";
4
4
  import { ADMIN_ROLES_ABILITIES } from "@byline/admin/admin-roles";
5
5
  import { ADMIN_USERS_ABILITIES } from "@byline/admin/admin-users";
6
+ import { useTranslation } from "@byline/i18n/react";
6
7
  import { HomeIcon, RolesIcon, SettingsSlidersIcon, UserIcon, UsersIcon } from "@byline/ui/react";
7
8
  import classnames from "classnames";
8
9
  import { useSwipeable } from "react-swipeable";
@@ -41,6 +42,7 @@ function AdminMenuDrawer() {
41
42
  select: (s)=>s.location.pathname
42
43
  });
43
44
  const { mobile, drawerOpen, closeDrawer } = useAdminMenu();
45
+ const { t } = useTranslation('byline-admin');
44
46
  const { has } = useAbilities();
45
47
  const canReadUsers = has(ADMIN_USERS_ABILITIES.read);
46
48
  const canReadRoles = has(ADMIN_ROLES_ABILITIES.read);
@@ -75,7 +77,7 @@ function AdminMenuDrawer() {
75
77
  children: [
76
78
  /*#__PURE__*/ jsx(MenuItem, {
77
79
  to: "/admin",
78
- label: "Dashboard",
80
+ label: t('chrome.menu.dashboard'),
79
81
  icon: /*#__PURE__*/ jsx(HomeIcon, {
80
82
  width: "20px",
81
83
  height: "20px"
@@ -90,7 +92,7 @@ function AdminMenuDrawer() {
90
92
  }),
91
93
  canReadUsers && /*#__PURE__*/ jsx(MenuItem, {
92
94
  to: "/admin/users",
93
- label: "Admin Users",
95
+ label: t('chrome.menu.adminUsers'),
94
96
  icon: /*#__PURE__*/ jsx(UsersIcon, {
95
97
  width: "20px",
96
98
  height: "20px"
@@ -100,7 +102,7 @@ function AdminMenuDrawer() {
100
102
  }),
101
103
  canReadRoles && /*#__PURE__*/ jsx(MenuItem, {
102
104
  to: "/admin/roles",
103
- label: "Admin Roles",
105
+ label: t('chrome.menu.adminRoles'),
104
106
  icon: /*#__PURE__*/ jsx(RolesIcon, {
105
107
  width: "20px",
106
108
  height: "20px"
@@ -110,7 +112,7 @@ function AdminMenuDrawer() {
110
112
  }),
111
113
  canReadPermissions && /*#__PURE__*/ jsx(MenuItem, {
112
114
  to: "/admin/permissions",
113
- label: "Permissions",
115
+ label: t('chrome.menu.permissions'),
114
116
  icon: /*#__PURE__*/ jsx(SettingsSlidersIcon, {
115
117
  width: "20px",
116
118
  height: "20px"
@@ -128,7 +130,7 @@ function AdminMenuDrawer() {
128
130
  }),
129
131
  /*#__PURE__*/ jsx(MenuItem, {
130
132
  to: "/admin/account",
131
- label: "Account",
133
+ label: t('chrome.account'),
132
134
  icon: /*#__PURE__*/ jsx(UserIcon, {}),
133
135
  pathname: pathname,
134
136
  compact: compact
@@ -1,9 +1,11 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
+ import { useTranslation } from "@byline/i18n/react";
3
4
  import { EyeClosedIcon, EyeOpenIcon } from "@byline/ui/react";
4
5
  import classnames from "classnames";
5
6
  import { disablePreviewModeFn, enablePreviewModeFn, getPreviewStateFn } from "../../server-fns/preview/index.js";
6
7
  function PreviewToggle({ compact }) {
8
+ const { t } = useTranslation('byline-admin');
7
9
  const [preview, setPreview] = useState(null);
8
10
  const [busy, setBusy] = useState(false);
9
11
  useEffect(()=>{
@@ -40,7 +42,7 @@ function PreviewToggle({ compact }) {
40
42
  }
41
43
  };
42
44
  if (null == preview) return null;
43
- const label = preview ? 'Preview ON' : 'Preview OFF';
45
+ const label = preview ? t('chrome.preview.on') : t('chrome.preview.off');
44
46
  const icon = preview ? /*#__PURE__*/ jsx(EyeOpenIcon, {
45
47
  width: "20px",
46
48
  height: "20px"
@@ -57,8 +59,8 @@ function PreviewToggle({ compact }) {
57
59
  type: "button",
58
60
  onClick: handleToggle,
59
61
  disabled: busy,
60
- "aria-label": preview ? 'Disable preview mode' : 'Enable preview mode',
61
- title: preview ? 'Drafts are visible on the public site' : 'Public site shows published only',
62
+ "aria-label": preview ? t('chrome.preview.disableAriaLabel') : t('chrome.preview.enableAriaLabel'),
63
+ title: preview ? t('chrome.preview.onTitle') : t('chrome.preview.offTitle'),
62
64
  children: [
63
65
  /*#__PURE__*/ jsx("span", {
64
66
  className: "icon",
@@ -15,7 +15,8 @@ import type { ErrorComponentProps, NotFoundRouteProps } from '@tanstack/react-ro
15
15
  export declare function RouteError({ error, reset }: ErrorComponentProps): import("react").JSX.Element;
16
16
  export declare function RouteNotFound(_props: NotFoundRouteProps): import("react").JSX.Element;
17
17
  /**
18
- * Minimal fallback for when providers may be broken. Used at the root
19
- * route, where wrapping in Container/Section may itself be unsafe.
18
+ * Minimal fallback for when providers may be broken used at the root
19
+ * route where the i18n provider itself may not be mounted. Stays in
20
+ * English on purpose.
20
21
  */
21
22
  export declare function RootError({ error, reset }: ErrorComponentProps): import("react").JSX.Element;
@@ -1,30 +1,32 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useRouter } from "@tanstack/react-router";
3
3
  import { BylineError, ErrorCodes } from "@byline/core";
4
+ import { useTranslation } from "@byline/i18n/react";
4
5
  import { Alert, Button, Container, Section } from "@byline/ui/react";
5
6
  import classnames from "classnames";
6
7
  import route_error_module from "./route-error.module.js";
7
- const ERROR_TITLES = {
8
- [ErrorCodes.NOT_FOUND]: 'Not Found',
9
- [ErrorCodes.VALIDATION]: 'Validation Error',
10
- [ErrorCodes.CONFLICT]: 'Conflict',
11
- [ErrorCodes.INVALID_TRANSITION]: 'Invalid Transition',
12
- [ErrorCodes.PATCH_FAILED]: 'Update Failed',
13
- [ErrorCodes.DATABASE]: 'Database Error',
14
- [ErrorCodes.STORAGE]: 'Storage Error',
15
- [ErrorCodes.UNHANDLED]: 'Unexpected Error'
8
+ const ERROR_TITLE_KEYS = {
9
+ [ErrorCodes.NOT_FOUND]: 'routeError.titles.notFound',
10
+ [ErrorCodes.VALIDATION]: 'routeError.titles.validation',
11
+ [ErrorCodes.CONFLICT]: 'routeError.titles.conflict',
12
+ [ErrorCodes.INVALID_TRANSITION]: 'routeError.titles.invalidTransition',
13
+ [ErrorCodes.PATCH_FAILED]: 'routeError.titles.patchFailed',
14
+ [ErrorCodes.DATABASE]: 'routeError.titles.database',
15
+ [ErrorCodes.STORAGE]: 'routeError.titles.storage',
16
+ [ErrorCodes.UNHANDLED]: 'routeError.titles.unhandled'
16
17
  };
17
- function getErrorTitle(error) {
18
- if (error instanceof BylineError) return ERROR_TITLES[error.code] ?? 'Unexpected Error';
19
- return 'Unexpected Error';
18
+ function getErrorTitle(error, t) {
19
+ if (error instanceof BylineError) return t(ERROR_TITLE_KEYS[error.code] ?? 'routeError.titles.unhandled');
20
+ return t('routeError.titles.unhandled');
20
21
  }
21
- function getErrorMessage(error) {
22
+ function getErrorMessage(error, t) {
22
23
  if (error instanceof BylineError) return error.message;
23
24
  if (error instanceof Error) return error.message;
24
- return 'An unexpected error occurred. Please try again.';
25
+ return t('routeError.defaultMessage');
25
26
  }
26
27
  function RouteError({ error, reset }) {
27
28
  const router = useRouter();
29
+ const { t } = useTranslation('byline-admin');
28
30
  return /*#__PURE__*/ jsx(Section, {
29
31
  className: classnames('byline-route-error', route_error_module.section),
30
32
  children: /*#__PURE__*/ jsx(Container, {
@@ -33,11 +35,11 @@ function RouteError({ error, reset }) {
33
35
  intent: "danger",
34
36
  icon: true,
35
37
  close: false,
36
- title: getErrorTitle(error),
38
+ title: getErrorTitle(error, t),
37
39
  children: [
38
40
  /*#__PURE__*/ jsx("p", {
39
41
  className: classnames('byline-route-error-message', route_error_module.message),
40
- children: getErrorMessage(error)
42
+ children: getErrorMessage(error, t)
41
43
  }),
42
44
  /*#__PURE__*/ jsxs("div", {
43
45
  className: classnames('byline-route-error-actions', route_error_module.actions),
@@ -50,12 +52,12 @@ function RouteError({ error, reset }) {
50
52
  reset();
51
53
  router.invalidate();
52
54
  },
53
- children: "Try again"
55
+ children: t('common.actions.tryAgain')
54
56
  }),
55
57
  /*#__PURE__*/ jsx("a", {
56
58
  href: "/",
57
59
  className: classnames('byline-route-error-link', route_error_module.link),
58
- children: "Go to homepage"
60
+ children: t('common.actions.goToHomepage')
59
61
  })
60
62
  ]
61
63
  })
@@ -65,6 +67,7 @@ function RouteError({ error, reset }) {
65
67
  });
66
68
  }
67
69
  function RouteNotFound(_props) {
70
+ const { t } = useTranslation('byline-admin');
68
71
  return /*#__PURE__*/ jsx(Section, {
69
72
  className: classnames('byline-route-error', route_error_module.section),
70
73
  children: /*#__PURE__*/ jsx(Container, {
@@ -73,18 +76,18 @@ function RouteNotFound(_props) {
73
76
  intent: "warning",
74
77
  icon: true,
75
78
  close: false,
76
- title: "Page Not Found",
79
+ title: t('routeError.notFound.title'),
77
80
  children: [
78
81
  /*#__PURE__*/ jsx("p", {
79
82
  className: classnames('byline-route-error-message', route_error_module.message),
80
- children: "The page you are looking for does not exist or has been moved."
83
+ children: t('routeError.notFound.message')
81
84
  }),
82
85
  /*#__PURE__*/ jsx("div", {
83
86
  className: classnames('byline-route-error-actions', route_error_module.actions),
84
87
  children: /*#__PURE__*/ jsx("a", {
85
88
  href: "/",
86
89
  className: classnames('byline-route-error-link', route_error_module.link),
87
- children: "Go to homepage"
90
+ children: t('common.actions.goToHomepage')
88
91
  })
89
92
  })
90
93
  ]
@@ -93,6 +96,10 @@ function RouteNotFound(_props) {
93
96
  });
94
97
  }
95
98
  function RootError({ error, reset }) {
99
+ function rootMessage(err) {
100
+ if (err instanceof Error) return err.message;
101
+ return 'An unexpected error occurred. Please try again.';
102
+ }
96
103
  return /*#__PURE__*/ jsx("div", {
97
104
  className: classnames('byline-root-error', route_error_module.rootRoot),
98
105
  children: /*#__PURE__*/ jsxs("div", {
@@ -104,7 +111,7 @@ function RootError({ error, reset }) {
104
111
  }),
105
112
  /*#__PURE__*/ jsx("p", {
106
113
  className: classnames('byline-root-error-detail', route_error_module.rootDetail),
107
- children: getErrorMessage(error)
114
+ children: rootMessage(error)
108
115
  }),
109
116
  /*#__PURE__*/ jsx("button", {
110
117
  type: "button",
@@ -5,19 +5,31 @@
5
5
  *
6
6
  * Copyright (c) Infonomic Company Limited
7
7
  */
8
+ import type { LocaleCode } from '@byline/i18n';
8
9
  interface SignInPageProps {
9
10
  callbackUrl?: string;
11
+ activeLocale: LocaleCode;
10
12
  }
11
13
  /**
12
14
  * Sign-in page chrome — rendered outside the authenticated admin
13
15
  * layout (no app bar, breadcrumbs, or menu drawer). Wraps the
14
- * `SignInForm` from `@byline/ui` in the admin services provider so
16
+ * `SignInForm` from `@byline/admin` in the admin services provider so
15
17
  * the form can call `signIn` via the typed contract.
16
18
  *
19
+ * Mounts its own `<I18nProvider>` because the layout-level provider
20
+ * (the one that wraps the authenticated admin) doesn't apply here.
21
+ * `<LanguageMenu>` lights up automatically when two or more interface
22
+ * locales are configured. On change, the menu calls
23
+ * `setInterfaceLocaleFn` which writes the cookie unconditionally and
24
+ * skips the DB write on the pre-auth path (the user has no admin
25
+ * session yet). After sign-in succeeds, the `adminSignIn` server fn
26
+ * reconciles the cookie locale into the user's
27
+ * `admin_users.preferred_locale` so the pre-auth choice becomes
28
+ * sticky across devices from day one.
29
+ *
17
30
  * Threads the configured `serverURL` into the `SignInForm` as `homeUrl` so
18
31
  * the form's action row can render a plain "Home" link beside the submit
19
- * button. After admin sign-out users land back here; the link is what lets
20
- * them get back to the public site without typing the URL.
32
+ * button.
21
33
  */
22
- export declare function SignInPage({ callbackUrl }: SignInPageProps): import("react").JSX.Element;
34
+ export declare function SignInPage({ callbackUrl, activeLocale }: SignInPageProps): import("react").JSX.Element;
23
35
  export {};
@@ -1,22 +1,47 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { SignInForm } from "@byline/admin/auth/components/sign-in-form";
3
3
  import { BylineAdminServicesProvider } from "@byline/admin/services";
4
4
  import { getClientConfig } from "@byline/core";
5
+ import { I18nProvider, LanguageMenu } from "@byline/i18n/react";
5
6
  import classnames from "classnames";
7
+ import { buildLocaleDefinitions } from "../../i18n/locale-definitions.js";
6
8
  import { bylineAdminServices } from "../../integrations/byline-admin-services.js";
9
+ import { setInterfaceLocaleFn } from "../../server-fns/i18n/index.js";
7
10
  import sign_in_page_module from "./sign-in-page.module.js";
8
- function SignInPage({ callbackUrl }) {
9
- const { serverURL } = getClientConfig();
10
- return /*#__PURE__*/ jsx(BylineAdminServicesProvider, {
11
- services: bylineAdminServices,
12
- children: /*#__PURE__*/ jsx("main", {
13
- className: classnames('byline-sign-in-page', sign_in_page_module.main),
14
- children: /*#__PURE__*/ jsx("div", {
15
- className: classnames('byline-sign-in-page-inner', sign_in_page_module.inner),
16
- children: /*#__PURE__*/ jsx(SignInForm, {
17
- callbackUrl: callbackUrl,
18
- homeUrl: serverURL
19
- })
11
+ function SignInPage({ callbackUrl, activeLocale }) {
12
+ const { i18n, serverURL } = getClientConfig();
13
+ const localeDefinitions = buildLocaleDefinitions(i18n.interface.locales, i18n.interface.localeDefinitions);
14
+ const handleSetLocale = async (next)=>{
15
+ await setInterfaceLocaleFn({
16
+ data: {
17
+ locale: next
18
+ }
19
+ });
20
+ window.location.reload();
21
+ };
22
+ return /*#__PURE__*/ jsx(I18nProvider, {
23
+ bundle: i18n.translations ?? {},
24
+ activeLocale: activeLocale,
25
+ defaultLocale: i18n.interface.defaultLocale,
26
+ localeDefinitions: localeDefinitions,
27
+ setLocale: handleSetLocale,
28
+ children: /*#__PURE__*/ jsx(BylineAdminServicesProvider, {
29
+ services: bylineAdminServices,
30
+ children: /*#__PURE__*/ jsxs("main", {
31
+ className: classnames('byline-sign-in-page', sign_in_page_module.main),
32
+ children: [
33
+ /*#__PURE__*/ jsx("div", {
34
+ className: classnames('byline-sign-in-page-bar', sign_in_page_module.bar),
35
+ children: /*#__PURE__*/ jsx(LanguageMenu, {})
36
+ }),
37
+ /*#__PURE__*/ jsx("div", {
38
+ className: classnames('byline-sign-in-page-inner', sign_in_page_module.inner),
39
+ children: /*#__PURE__*/ jsx(SignInForm, {
40
+ callbackUrl: callbackUrl,
41
+ homeUrl: serverURL
42
+ })
43
+ })
44
+ ]
20
45
  })
21
46
  })
22
47
  });
@@ -1,6 +1,7 @@
1
1
  import "./sign-in-page_module.css";
2
2
  const sign_in_page_module = {
3
3
  main: "main-Mz7TWj",
4
+ bar: "bar-uO4D8B",
4
5
  inner: "inner-iPyHJh"
5
6
  };
6
7
  export default sign_in_page_module;
@@ -1,11 +1,18 @@
1
1
  :is(.main-Mz7TWj, .byline-sign-in-page) {
2
2
  flex-direction: column;
3
3
  flex: 1;
4
- align-items: center;
4
+ align-items: stretch;
5
5
  padding: 1.5rem;
6
6
  display: flex;
7
7
  }
8
8
 
9
+ :is(.bar-uO4D8B, .byline-sign-in-page-bar) {
10
+ justify-content: flex-end;
11
+ align-items: center;
12
+ min-height: 1.75rem;
13
+ display: flex;
14
+ }
15
+
9
16
  :is(.inner-iPyHJh, .byline-sign-in-page-inner) {
10
17
  flex-direction: column;
11
18
  align-items: center;
@@ -1,4 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useTranslation } from "@byline/i18n/react";
2
3
  import { Container, Section } from "@byline/ui/react";
3
4
  import classnames from "classnames";
4
5
  import { JsonView, allExpanded, darkStyles } from "react-json-view-lite";
@@ -7,6 +8,7 @@ import { ViewMenu } from "./view-menu.js";
7
8
  import "react-json-view-lite/dist/index.css";
8
9
  const ApiView = ({ collectionDefinition, initialData, locale, depth, contentLocales, defaultContentLocale })=>{
9
10
  const { labels, path } = collectionDefinition;
11
+ const { t } = useTranslation('byline-admin');
10
12
  return /*#__PURE__*/ jsx(Section, {
11
13
  className: classnames('byline-api-section', api_module.section),
12
14
  children: /*#__PURE__*/ jsxs(Container, {
@@ -15,12 +17,11 @@ const ApiView = ({ collectionDefinition, initialData, locale, depth, contentLoca
15
17
  /*#__PURE__*/ jsxs("div", {
16
18
  className: classnames('byline-api-head', api_module.head),
17
19
  children: [
18
- /*#__PURE__*/ jsxs("h2", {
20
+ /*#__PURE__*/ jsx("h2", {
19
21
  className: classnames('byline-api-title', api_module.title),
20
- children: [
21
- labels.singular,
22
- " API"
23
- ]
22
+ children: t('collections.api.title', {
23
+ label: labels.singular
24
+ })
24
25
  }),
25
26
  /*#__PURE__*/ jsx(ViewMenu, {
26
27
  collection: path,
@@ -1,11 +1,14 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
- import { Container, FormRenderer, Section, useToastManager } from "@byline/ui/react";
3
+ import { FormRenderer } from "@byline/admin/react";
4
+ import { useTranslation } from "@byline/i18n/react";
5
+ import { Container, Section, useToastManager } from "@byline/ui/react";
4
6
  import { createCollectionDocument } from "../../server-fns/collections/index.js";
5
7
  import { useNavigate } from "../chrome/loose-router.js";
6
8
  import { useTanStackNavigationGuard } from "./tanstack-navigation-guard.js";
7
9
  const CreateView = ({ collectionDefinition, adminConfig, initialData })=>{
8
10
  const toastManager = useToastManager();
11
+ const { t } = useTranslation('byline-admin');
9
12
  const [_createState, setCreateState] = useState({
10
13
  status: 'idle',
11
14
  message: ''
@@ -34,9 +37,14 @@ const CreateView = ({ collectionDefinition, adminConfig, initialData })=>{
34
37
  });
35
38
  } catch (err) {
36
39
  console.error(err);
40
+ const description = t("collections.create.errorToastDescription", {
41
+ label: labels.singular.toLowerCase()
42
+ });
37
43
  toastManager.add({
38
- title: `${labels.singular} Creation`,
39
- description: `An error occurred while creating ${labels.singular.toLowerCase()}`,
44
+ title: t('collections.create.errorToastTitle', {
45
+ label: labels.singular
46
+ }),
47
+ description,
40
48
  data: {
41
49
  intent: 'danger',
42
50
  iconType: 'danger',
@@ -46,7 +54,7 @@ const CreateView = ({ collectionDefinition, adminConfig, initialData })=>{
46
54
  });
47
55
  setCreateState({
48
56
  status: 'failed',
49
- message: `An error occurred while creating ${labels.singular.toLowerCase()}`
57
+ message: description
50
58
  });
51
59
  }
52
60
  };