@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
@@ -31,15 +31,9 @@ import { useRouter } from '@tanstack/react-router'
31
31
 
32
32
  import { RolePermissions } from '@byline/admin/admin-roles/components/permissions'
33
33
  import { UpdateRole } from '@byline/admin/admin-roles/components/update'
34
- import {
35
- Button,
36
- CloseIcon,
37
- Drawer,
38
- IconButton,
39
- LocalDateTime,
40
- Modal,
41
- useToastManager,
42
- } from '@byline/ui/react'
34
+ import { LocalDateTime } from '@byline/admin/react'
35
+ import { useTranslation } from '@byline/i18n/react'
36
+ import { Button, CloseIcon, Drawer, IconButton, Modal, useToastManager } from '@byline/ui/react'
43
37
  import cx from 'classnames'
44
38
 
45
39
  import styles from './container.module.css'
@@ -58,12 +52,17 @@ interface PanelProps {
58
52
  onSuccess?: (role: AdminRoleResponse) => void
59
53
  }
60
54
 
61
- const panels: Record<ComponentKey, { title: string; component: React.ComponentType<PanelProps> }> =
62
- {
63
- update: { title: 'Role Details', component: UpdateRole },
64
- delete_role: { title: 'Delete Admin Role', component: DeleteRole },
65
- empty: { title: '', component: () => null },
66
- }
55
+ // Static structural template — panels' title strings are translated at
56
+ // render time below via `t`, so this map only holds the per-key component
57
+ // and i18n key, not the localised label itself.
58
+ const panelMeta: Record<
59
+ ComponentKey,
60
+ { titleKey: string | null; component: React.ComponentType<PanelProps> }
61
+ > = {
62
+ update: { titleKey: 'adminRoles.detail.panels.update', component: UpdateRole },
63
+ delete_role: { titleKey: 'adminRoles.detail.panels.delete', component: DeleteRole },
64
+ empty: { titleKey: null, component: () => null },
65
+ }
67
66
 
68
67
  interface RoleContainerProps {
69
68
  role: AdminRoleResponse
@@ -74,6 +73,7 @@ interface RoleContainerProps {
74
73
  export function RoleContainer({ role, registered, initialAbilities }: RoleContainerProps) {
75
74
  const router = useRouter()
76
75
  const toastManager = useToastManager()
76
+ const { t } = useTranslation('byline-admin')
77
77
  const [currentRole, setCurrentRole] = useState<AdminRoleResponse>(role)
78
78
  const [currentAbilities, setCurrentAbilities] = useState<string[]>(initialAbilities)
79
79
  const [current, setCurrent] = useState<ComponentKey>('empty')
@@ -105,34 +105,42 @@ export function RoleContainer({ role, registered, initialAbilities }: RoleContai
105
105
  setCurrentAbilities(response.abilities)
106
106
  void router.invalidate()
107
107
  toastManager.add({
108
- title: 'Permissions saved',
109
- description: `${response.abilities.length} abilities granted to ${currentRole.name}.`,
108
+ title: t('adminRoles.detail.permissionsSavedToast'),
109
+ description: t('adminRoles.detail.permissionsSavedDescription', {
110
+ count: response.abilities.length,
111
+ role: currentRole.name,
112
+ }),
110
113
  data: { intent: 'success' },
111
114
  })
112
115
  }
113
116
 
114
- const Panel = panels[current].component
117
+ const Panel = panelMeta[current].component
118
+ const panelTitleKey = panelMeta[current].titleKey
119
+ const panelTitle = panelTitleKey ? t(panelTitleKey) : ''
115
120
 
116
121
  return (
117
122
  <>
118
123
  <div className={cx('byline-role-detail-card', styles.card)}>
119
124
  <div className={cx('byline-role-detail-head', styles.head)}>
120
- <h2 className={cx('byline-role-detail-title', styles.title)}>Role Details</h2>
125
+ <h2 className={cx('byline-role-detail-title', styles.title)}>
126
+ {t('adminRoles.detail.title')}
127
+ </h2>
121
128
  <div className={cx('byline-role-detail-actions', styles.actions)}>
122
129
  <Button size="xs" intent="secondary" onClick={openDrawer('update')}>
123
- Edit Details
130
+ {t('adminRoles.detail.editDetailsButton')}
124
131
  </Button>
125
132
  <Button size="xs" intent="danger" onClick={openModal('delete_role')}>
126
- Delete Role
133
+ {t('adminRoles.detail.deleteButton')}
127
134
  </Button>
128
135
  </div>
129
136
  </div>
130
137
  <div className={cx('byline-role-detail-grid', styles.grid)}>
131
138
  <p className={cx('byline-role-detail-row', styles.row)}>
132
- <span className="muted">Name:</span> {currentRole.name}
139
+ <span className="muted">{t('adminRoles.detail.fields.name')}</span> {currentRole.name}
133
140
  </p>
134
141
  <p className={cx('byline-role-detail-row', styles.row)}>
135
- <span className="muted">Machine name:</span> {currentRole.machine_name}
142
+ <span className="muted">{t('adminRoles.detail.fields.machineName')}</span>{' '}
143
+ {currentRole.machine_name}
136
144
  </p>
137
145
  <p
138
146
  className={cx(
@@ -141,19 +149,21 @@ export function RoleContainer({ role, registered, initialAbilities }: RoleContai
141
149
  styles.gridFull
142
150
  )}
143
151
  >
144
- <span className="muted">Description:</span>{' '}
152
+ <span className="muted">{t('adminRoles.detail.fields.description')}</span>{' '}
145
153
  {currentRole.description ?? (
146
- <span className={cx('muted byline-role-detail-not-set', styles.notSet)}>Not set</span>
154
+ <span className={cx('muted byline-role-detail-not-set', styles.notSet)}>
155
+ {t('common.notSet')}
156
+ </span>
147
157
  )}
148
158
  </p>
149
159
  </div>
150
160
  <div className={cx('muted byline-role-detail-meta', styles.meta)}>
151
161
  <p className={cx('byline-role-detail-row', styles.row)}>
152
- <span className="font-bold">Created:&nbsp;</span>
162
+ <span className="font-bold">{t('adminRoles.detail.fields.created')}&nbsp;</span>
153
163
  <LocalDateTime value={currentRole.created_at} />
154
164
  </p>
155
165
  <p className={cx('byline-role-detail-row', styles.row)}>
156
- <span className="font-bold">Updated:&nbsp;</span>
166
+ <span className="font-bold">{t('adminRoles.detail.fields.updated')}&nbsp;</span>
157
167
  <LocalDateTime value={currentRole.updated_at} />
158
168
  </p>
159
169
  </div>
@@ -180,12 +190,12 @@ export function RoleContainer({ role, registered, initialAbilities }: RoleContai
180
190
  <button type="button" tabIndex={0} className="sr-only">
181
191
  no action
182
192
  </button>
183
- <IconButton aria-label="Close" size="sm" onClick={closeDrawer}>
193
+ <IconButton aria-label={t('common.actions.close')} size="sm" onClick={closeDrawer}>
184
194
  <CloseIcon width="14px" height="14px" svgClassName="white-icon stroke-white" />
185
195
  </IconButton>
186
196
  </Drawer.TopActions>
187
197
  <Drawer.Header>
188
- <h2>{panels[current].title}</h2>
198
+ <h2>{panelTitle}</h2>
189
199
  </Drawer.Header>
190
200
  <Drawer.Content>
191
201
  <div className={cx('byline-role-detail-drawer-content', styles.drawerContent)}>
@@ -198,8 +208,8 @@ export function RoleContainer({ role, registered, initialAbilities }: RoleContai
198
208
  <Modal isOpen={isModalOpen} onDismiss={closeModal} closeOnOverlayClick={false}>
199
209
  <Modal.Container className={cx('byline-role-detail-modal', styles.modal)}>
200
210
  <Modal.Header className={cx('byline-role-detail-modal-head', styles.modalHead)}>
201
- <h3 className="m-0">{panels[current].title}</h3>
202
- <IconButton aria-label="Close" size="sm" onClick={closeModal}>
211
+ <h3 className="m-0">{panelTitle}</h3>
212
+ <IconButton aria-label={t('common.actions.close')} size="sm" onClick={closeModal}>
203
213
  <CloseIcon width="14px" height="14px" svgClassName="white-icon" />
204
214
  </IconButton>
205
215
  </Modal.Header>
@@ -20,6 +20,7 @@
20
20
  import { useState } from 'react'
21
21
  import { useRouter } from '@tanstack/react-router'
22
22
 
23
+ import { useTranslation } from '@byline/i18n/react'
23
24
  import { Alert, Button, LoaderEllipsis, Modal } from '@byline/ui/react'
24
25
  import cx from 'classnames'
25
26
 
@@ -36,6 +37,7 @@ interface DeleteRoleProps {
36
37
  export function DeleteRole({ role, onClose }: DeleteRoleProps) {
37
38
  const navigate = useNavigate()
38
39
  const router = useRouter()
40
+ const { t } = useTranslation('byline-admin')
39
41
  const [error, setError] = useState<string | null>(null)
40
42
  const [pending, setPending] = useState(false)
41
43
 
@@ -54,13 +56,11 @@ export function DeleteRole({ role, onClose }: DeleteRoleProps) {
54
56
  } catch (err) {
55
57
  const code = getErrorCode(err)
56
58
  if (code === 'admin.roles.versionConflict') {
57
- setError(
58
- 'This role has been modified elsewhere since you opened this dialog. Close and reload before trying again.'
59
- )
59
+ setError(t('adminRoles.delete.errors.versionConflict'))
60
60
  } else if (code === 'admin.roles.notFound') {
61
- setError('This role has already been deleted.')
61
+ setError(t('adminRoles.delete.errors.notFound'))
62
62
  } else {
63
- setError('Could not delete this role. Please try again.')
63
+ setError(t('adminRoles.delete.errors.fallback'))
64
64
  }
65
65
  setPending(false)
66
66
  }
@@ -75,14 +75,13 @@ export function DeleteRole({ role, onClose }: DeleteRoleProps) {
75
75
  </Alert>
76
76
  ) : null}
77
77
  <p className={cx('byline-role-delete-row', styles.row)}>
78
- <span className="muted">Role:</span> {role.name}
78
+ <span className="muted">{t('adminRoles.delete.roleLabel')}</span> {role.name}
79
79
  </p>
80
80
  <p className={cx('byline-role-delete-row', styles.row)}>
81
- <span className="muted">Machine name:</span> {role.machine_name}
81
+ <span className="muted">{t('adminRoles.delete.machineLabel')}</span> {role.machine_name}
82
82
  </p>
83
83
  <p className={cx('byline-role-delete-warning', styles.warning)}>
84
- This will permanently delete the role. Any users assigned to it lose the role; any
85
- per-role ability grants are removed. The action cannot be undone.
84
+ {t('adminRoles.delete.warning')}
86
85
  </p>
87
86
  </div>
88
87
  <div className={cx('byline-role-delete-actions', styles.actions)}>
@@ -94,7 +93,7 @@ export function DeleteRole({ role, onClose }: DeleteRoleProps) {
94
93
  disabled={pending}
95
94
  className={cx('byline-role-delete-button', styles.button)}
96
95
  >
97
- Cancel
96
+ {t('common.actions.cancel')}
98
97
  </Button>
99
98
  <Button
100
99
  size="sm"
@@ -103,7 +102,7 @@ export function DeleteRole({ role, onClose }: DeleteRoleProps) {
103
102
  disabled={pending}
104
103
  className={cx('byline-role-delete-button', styles.button)}
105
104
  >
106
- {pending === true ? <LoaderEllipsis size={42} /> : 'Delete Role'}
105
+ {pending === true ? <LoaderEllipsis size={42} /> : t('adminRoles.delete.confirmButton')}
107
106
  </Button>
108
107
  </div>
109
108
  </Modal.Content>
@@ -26,6 +26,8 @@ import { type FormEvent, useEffect, useState } from 'react'
26
26
  import { useRouter } from '@tanstack/react-router'
27
27
 
28
28
  import { CreateAdminRole } from '@byline/admin/admin-roles/components/create'
29
+ import { LocalDateTime } from '@byline/admin/react'
30
+ import { useTranslation } from '@byline/i18n/react'
29
31
  import {
30
32
  Button,
31
33
  CloseIcon,
@@ -35,7 +37,6 @@ import {
35
37
  GripperVerticalIcon,
36
38
  IconButton,
37
39
  LoaderEllipsis,
38
- LocalDateTime,
39
40
  moveItem,
40
41
  PlusIcon,
41
42
  Section,
@@ -66,6 +67,7 @@ interface DraggableRowProps {
66
67
  }
67
68
 
68
69
  const DraggableRow: React.FC<DraggableRowProps> = ({ item, disabled }) => {
70
+ const { t } = useTranslation('byline-admin')
69
71
  const { attributes, isDragging, listeners, setNodeRef, transform, transition } = useSortable({
70
72
  id: item.id,
71
73
  disabled,
@@ -102,7 +104,9 @@ const DraggableRow: React.FC<DraggableRowProps> = ({ item, disabled }) => {
102
104
  <Table.Cell>{item.machine_name}</Table.Cell>
103
105
  <Table.Cell>
104
106
  {item.description ?? (
105
- <span className={cx('muted byline-roles-list-not-set', styles.notSet)}>Not set</span>
107
+ <span className={cx('muted byline-roles-list-not-set', styles.notSet)}>
108
+ {t('common.notSet')}
109
+ </span>
106
110
  )}
107
111
  </Table.Cell>
108
112
  <Table.Cell className={cx('byline-roles-list-cell-right', styles.cellRight)}>
@@ -129,6 +133,7 @@ function padRows(value: number) {
129
133
  export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
130
134
  const router = useRouter()
131
135
  const toastManager = useToastManager()
136
+ const { t } = useTranslation('byline-admin')
132
137
  const [items, setItems] = useState<AdminRoleResponse[]>(data.roles)
133
138
  const [orderChanged, setOrderChanged] = useState(false)
134
139
  const [isSaving, setIsSaving] = useState(false)
@@ -153,7 +158,7 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
153
158
  setIsCreateDrawerOpen(false)
154
159
  void router.invalidate()
155
160
  toastManager.add({
156
- title: 'Admin role created',
161
+ title: t('adminRoles.list.createdToastTitle'),
157
162
  description: created.name,
158
163
  data: { intent: 'success' },
159
164
  })
@@ -182,7 +187,7 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
182
187
  setOrderChanged(false)
183
188
  void router.invalidate()
184
189
  toastManager.add({
185
- title: 'Order saved',
190
+ title: t('adminRoles.list.orderSavedToast'),
186
191
  data: { intent: 'success' },
187
192
  })
188
193
  } catch (_err) {
@@ -190,8 +195,8 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
190
195
  setItems(previousItems)
191
196
  setOrderChanged(false)
192
197
  toastManager.add({
193
- title: 'Could not save the new order',
194
- description: 'Please try again.',
198
+ title: t('adminRoles.list.orderFailedToast'),
199
+ description: t('adminRoles.list.orderFailedDescription'),
195
200
  data: { intent: 'danger' },
196
201
  })
197
202
  } finally {
@@ -203,15 +208,19 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
203
208
  <Section>
204
209
  <Container>
205
210
  <div className={cx('byline-roles-list-head', styles.head)}>
206
- <h1 className={cx('byline-roles-list-title', styles.title)}>Admin Roles</h1>
211
+ <h1 className={cx('byline-roles-list-title', styles.title)}>
212
+ {t('adminRoles.list.title')}
213
+ </h1>
207
214
  <Stats total={data.roles.length} />
208
- <IconButton aria-label="Create New Admin Role" onClick={openCreateDrawer}>
215
+ <IconButton aria-label={t('adminRoles.list.createAriaLabel')} onClick={openCreateDrawer}>
209
216
  <PlusIcon height="18px" width="18px" svgClassName="stroke-white" />
210
217
  </IconButton>
211
218
  </div>
212
219
 
213
220
  {items.length === 0 ? (
214
- <div className={cx('byline-roles-list-empty', styles.empty)}>No admin roles found</div>
221
+ <div className={cx('byline-roles-list-empty', styles.empty)}>
222
+ {t('adminRoles.list.empty')}
223
+ </div>
215
224
  ) : (
216
225
  <DraggableSortable ids={items.map((item) => item.id)} onDragEnd={handleOnDragEnd}>
217
226
  <Table.Container className={cx('byline-roles-list-table-wrap', styles.tableWrap)}>
@@ -222,22 +231,22 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
222
231
  className={cx('byline-roles-list-col-drag', styles.colDrag)}
223
232
  />
224
233
  <Table.HeadingCell className={cx('byline-roles-list-col-name', styles.colName)}>
225
- Name
234
+ {t('adminRoles.list.columns.name')}
226
235
  </Table.HeadingCell>
227
236
  <Table.HeadingCell
228
237
  className={cx('byline-roles-list-col-machine', styles.colMachine)}
229
238
  >
230
- Machine Name
239
+ {t('adminRoles.list.columns.machineName')}
231
240
  </Table.HeadingCell>
232
241
  <Table.HeadingCell
233
242
  className={cx('byline-roles-list-col-description', styles.colDescription)}
234
243
  >
235
- Description
244
+ {t('adminRoles.list.columns.description')}
236
245
  </Table.HeadingCell>
237
246
  <Table.HeadingCell
238
247
  className={cx('byline-roles-list-col-created', styles.colCreated)}
239
248
  >
240
- Created
249
+ {t('adminRoles.list.columns.created')}
241
250
  </Table.HeadingCell>
242
251
  </Table.Row>
243
252
  </Table.Header>
@@ -264,7 +273,7 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
264
273
  {isSaving ? (
265
274
  <LoaderEllipsis size={30} color="#aaaaaa" />
266
275
  ) : (
267
- <span>Save Order</span>
276
+ <span>{t('adminRoles.list.saveOrder')}</span>
268
277
  )}
269
278
  </Button>
270
279
  </div>
@@ -287,12 +296,16 @@ export function AdminRolesListView({ data }: { data: AdminRoleListResponse }) {
287
296
  <button type="button" tabIndex={0} className="sr-only">
288
297
  no action
289
298
  </button>
290
- <IconButton aria-label="Close" size="sm" onClick={closeCreateDrawer}>
299
+ <IconButton
300
+ aria-label={t('common.actions.close')}
301
+ size="sm"
302
+ onClick={closeCreateDrawer}
303
+ >
291
304
  <CloseIcon width="14px" height="14px" svgClassName="white-icon stroke-white" />
292
305
  </IconButton>
293
306
  </Drawer.TopActions>
294
307
  <Drawer.Header>
295
- <h2>New Admin Role</h2>
308
+ <h2>{t('adminRoles.list.newDrawerTitle')}</h2>
296
309
  </Drawer.Header>
297
310
  <Drawer.Content>
298
311
  <div className={cx('byline-roles-list-drawer-scroll', styles.drawerScroll)}>