@meith/theme-clubhouse 0.7.0 → 0.8.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.
@@ -1,18 +1,27 @@
1
- import { Card, CardRows, Empty, EmptyAction, EmptyDescription, EmptyTitle, cn } from '@meith/ui'
2
- import type { ForumDisplayModel } from '@meith/theme-kit'
1
+ import type { ForumDisplayModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
3
+ import { Card, CardRows, cn, Empty, EmptyAction, EmptyDescription, EmptyTitle } from '@meith/ui'
3
4
 
4
5
  import {
5
6
  BUTTON,
6
7
  ColumnHeads,
7
8
  HEADING,
9
+ isEmptyRegion,
8
10
  MICRO,
9
11
  NUMERIC,
10
12
  PAGE_BODY,
11
13
  PageHead,
12
- isEmptyRegion,
13
14
  } from '../shared'
14
15
 
15
- export function ForumDisplay({ forum, newThreadHref, markReadAction, regions }: ForumDisplayModel) {
16
+ export function ForumDisplay({
17
+ forum,
18
+ newThreadHref,
19
+ markReadAction,
20
+ regions,
21
+ copy,
22
+ }: ForumDisplayModel & { copy: SlotCopy }) {
23
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.forumDisplay.${key}`)
24
+
16
25
  return (
17
26
  <div className={PAGE_BODY}>
18
27
  <PageHead
@@ -27,7 +36,7 @@ export function ForumDisplay({ forum, newThreadHref, markReadAction, regions }:
27
36
  'bg-secondary text-secondary-foreground hover:bg-secondary/80',
28
37
  )}
29
38
  >
30
- Mark read
39
+ {c('markRead')}
31
40
  </button>
32
41
  </form>
33
42
  )}
@@ -36,7 +45,7 @@ export function ForumDisplay({ forum, newThreadHref, markReadAction, regions }:
36
45
  href={newThreadHref}
37
46
  className={cn(BUTTON, 'bg-primary text-primary-foreground hover:bg-primary-hover')}
38
47
  >
39
- New thread
48
+ {c('newThread')}
40
49
  </a>
41
50
  )}
42
51
  </>
@@ -46,8 +55,7 @@ export function ForumDisplay({ forum, newThreadHref, markReadAction, regions }:
46
55
  <p className="mt-0.5 flex flex-wrap items-baseline gap-x-2 text-xs text-muted-foreground">
47
56
  {forum.type !== 'link' && (
48
57
  <span className={`${MICRO} ${NUMERIC}`}>
49
- {forum.threadCount.toLocaleString('en')} threads ·{' '}
50
- {forum.postCount.toLocaleString('en')} posts
58
+ {forum.threadCount.label} {c('threads')} · {forum.postCount.label} {c('posts')}
51
59
  </span>
52
60
  )}
53
61
  {forum.description !== null && <span>{forum.description}</span>}
@@ -67,11 +75,9 @@ export function ForumDisplay({ forum, newThreadHref, markReadAction, regions }:
67
75
  <Card>
68
76
  {isEmptyRegion(regions.threads) ? (
69
77
  <Empty>
70
- <EmptyTitle>No threads here yet</EmptyTitle>
78
+ <EmptyTitle>{c('noThreadsYet')}</EmptyTitle>
71
79
  <EmptyDescription>
72
- {newThreadHref === null
73
- ? 'Nothing has been posted in this forum.'
74
- : 'Nothing has been posted in this forum. Yours would be the first.'}
80
+ {newThreadHref === null ? c('emptyNoThread') : c('emptyNoThreadFirst')}
75
81
  </EmptyDescription>
76
82
  {newThreadHref !== null && (
77
83
  <EmptyAction>
@@ -82,14 +88,18 @@ export function ForumDisplay({ forum, newThreadHref, markReadAction, regions }:
82
88
  'bg-primary text-primary-foreground hover:bg-primary-hover',
83
89
  )}
84
90
  >
85
- Start the first thread
91
+ {c('startFirstThread')}
86
92
  </a>
87
93
  </EmptyAction>
88
94
  )}
89
95
  </Empty>
90
96
  ) : (
91
97
  <>
92
- <ColumnHeads first="Thread" counts={['Replies', 'Views']} last="Latest" />
98
+ <ColumnHeads
99
+ first={c('thread')}
100
+ counts={[c('replies'), c('views')]}
101
+ last={c('latest')}
102
+ />
93
103
  <CardRows>{regions.threads}</CardRows>
94
104
  </>
95
105
  )}
@@ -1,8 +1,10 @@
1
- import type { ForumRowSlotModel } from '@meith/theme-kit'
1
+ import type { ForumRowSlotModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
2
3
 
3
4
  import { CHIP, HEADING, LINK, MICRO, ReadMark, Stamp, TABLE_ROW, Tally, UserRef } from '../shared'
4
5
 
5
- export function ForumRow({ forum }: ForumRowSlotModel) {
6
+ export function ForumRow({ forum, copy }: ForumRowSlotModel & { copy: SlotCopy }) {
7
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.forumRow.${key}`)
6
8
  const isLink = forum.type === 'link'
7
9
 
8
10
  return (
@@ -19,8 +21,8 @@ export function ForumRow({ forum }: ForumRowSlotModel) {
19
21
  >
20
22
  {forum.title}
21
23
  </a>
22
- {forum.isUnread && <span className="sr-only"> (new posts)</span>}
23
- {isLink && <span className={`${MICRO} ml-2`}>Link</span>}
24
+ {forum.isUnread && <span className="sr-only"> {c('newPosts')}</span>}
25
+ {isLink && <span className={`${MICRO} ml-2`}>{c('link')}</span>}
24
26
 
25
27
  {forum.description !== null && (
26
28
  <p className="mt-0.5 text-xs text-muted-foreground">{forum.description}</p>
@@ -40,19 +42,19 @@ export function ForumRow({ forum }: ForumRowSlotModel) {
40
42
  {!isLink && (
41
43
  <>
42
44
  <span className="col-start-2 md:col-start-3 md:block md:text-right">
43
- <Tally value={forum.threadCount} label="threads" />
45
+ <Tally value={forum.threadCount} label={c('threads')} />
44
46
  <span className="ms-3 md:hidden">
45
- <Tally value={forum.postCount} label="posts" />
47
+ <Tally value={forum.postCount} label={c('posts')} />
46
48
  </span>
47
49
  </span>
48
50
 
49
51
  <span className="hidden md:block md:text-right">
50
- <Tally value={forum.postCount} label="posts" />
52
+ <Tally value={forum.postCount} label={c('posts')} />
51
53
  </span>
52
54
 
53
55
  <div className="col-start-2 min-w-0 text-xs text-muted-foreground md:col-start-5">
54
56
  {forum.lastPost === null ? (
55
- <span className={MICRO}>No posts yet</span>
57
+ <span className={MICRO}>{c('noPostsYet')}</span>
56
58
  ) : (
57
59
  <>
58
60
  <a
@@ -1,4 +1,5 @@
1
- import type { HeaderModel } from '@meith/theme-kit'
1
+ import type { HeaderModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
2
3
 
3
4
  import { ClubRule, Crest, HEADING, PAGE, TAB } from '../shared'
4
5
 
@@ -33,7 +34,16 @@ function BoardMark({ boardTitle, logo }: Pick<HeaderModel, 'boardTitle' | 'logo'
33
34
  )
34
35
  }
35
36
 
36
- export function Header({ boardTitle, homeHref, navigation, logo, children }: HeaderModel) {
37
+ export function Header({
38
+ boardTitle,
39
+ homeHref,
40
+ navigation,
41
+ logo,
42
+ children,
43
+ copy,
44
+ }: HeaderModel & { copy: SlotCopy }) {
45
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.header.${key}`)
46
+
37
47
  return (
38
48
  <header className="bg-card">
39
49
  <div className={`${PAGE} flex flex-wrap items-center justify-between gap-x-6 gap-y-3 py-3`}>
@@ -49,7 +59,7 @@ export function Header({ boardTitle, homeHref, navigation, logo, children }: Hea
49
59
  <ClubRule />
50
60
 
51
61
  {navigation.length > 0 && (
52
- <nav aria-label="Board sections" className="border-b border-border bg-surface">
62
+ <nav aria-label={c('boardSections')} className="border-b border-border bg-surface">
53
63
  <div className={PAGE}>
54
64
  <ul className="-mx-4 flex items-stretch overflow-x-auto px-4 sm:-mx-6 sm:px-6">
55
65
  {navigation.map((item) => (
@@ -1,25 +1,28 @@
1
+ import type { LatestPostsModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Card, CardContent, Empty, EmptyDescription, EmptyTitle } from '@meith/ui'
2
- import type { LatestPostsModel } from '@meith/theme-kit'
3
4
 
4
5
  import { LINK, MICRO, MUTED_LINK, PanelHead, Stamp, UserRef } from '../shared'
5
6
 
6
- export function LatestPosts({ posts, capturedAt }: LatestPostsModel) {
7
+ export function LatestPosts({ posts, capturedAt, copy }: LatestPostsModel & { copy: SlotCopy }) {
8
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.latestPosts.${key}`)
9
+
7
10
  return (
8
11
  <Card aria-labelledby="latest-posts-heading">
9
12
  <PanelHead
10
13
  id="latest-posts-heading"
11
- title="Latest posts"
14
+ title={c('title')}
12
15
  aside={
13
16
  <span className={MICRO}>
14
- As of <Stamp at={capturedAt} />
17
+ {c('asOf')} <Stamp at={capturedAt} />
15
18
  </span>
16
19
  }
17
20
  />
18
21
 
19
22
  {posts.length === 0 ? (
20
23
  <Empty className="py-5">
21
- <EmptyTitle>Nothing said yet</EmptyTitle>
22
- <EmptyDescription>The newest posts you can see will appear here.</EmptyDescription>
24
+ <EmptyTitle>{c('nothingSaidYet')}</EmptyTitle>
25
+ <EmptyDescription>{c('newestPostsEmpty')}</EmptyDescription>
23
26
  </Empty>
24
27
  ) : (
25
28
  <CardContent className="px-0 py-0">
@@ -39,7 +42,7 @@ export function LatestPosts({ posts, capturedAt }: LatestPostsModel) {
39
42
 
40
43
  <p className="truncate text-xs text-muted-foreground">
41
44
  <UserRef user={post.author} className="font-medium" />
42
- {' in '}
45
+ {` ${c('in')} `}
43
46
  <a href={post.forum.href} className={MUTED_LINK}>
44
47
  {post.forum.label}
45
48
  </a>
@@ -1,25 +1,32 @@
1
+ import type { LatestThreadsModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Card, CardContent, Empty, EmptyDescription, EmptyTitle } from '@meith/ui'
2
- import type { LatestThreadsModel } from '@meith/theme-kit'
3
4
 
4
5
  import { LINK, MICRO, MUTED_LINK, NUMERIC, PanelHead, Stamp, UserRef } from '../shared'
5
6
 
6
- export function LatestThreads({ threads, capturedAt }: LatestThreadsModel) {
7
+ export function LatestThreads({
8
+ threads,
9
+ capturedAt,
10
+ copy,
11
+ }: LatestThreadsModel & { copy: SlotCopy }) {
12
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.latestThreads.${key}`)
13
+
7
14
  return (
8
15
  <Card aria-labelledby="latest-threads-heading">
9
16
  <PanelHead
10
17
  id="latest-threads-heading"
11
- title="Latest threads"
18
+ title={c('title')}
12
19
  aside={
13
20
  <span className={MICRO}>
14
- As of <Stamp at={capturedAt} />
21
+ {c('asOf')} <Stamp at={capturedAt} />
15
22
  </span>
16
23
  }
17
24
  />
18
25
 
19
26
  {threads.length === 0 ? (
20
27
  <Empty className="py-5">
21
- <EmptyTitle>Nothing started yet</EmptyTitle>
22
- <EmptyDescription>The newest threads you can see will appear here.</EmptyDescription>
28
+ <EmptyTitle>{c('nothingStartedYet')}</EmptyTitle>
29
+ <EmptyDescription>{c('newestThreadsEmpty')}</EmptyDescription>
23
30
  </Empty>
24
31
  ) : (
25
32
  <CardContent className="px-0 py-0">
@@ -34,13 +41,13 @@ export function LatestThreads({ threads, capturedAt }: LatestThreadsModel) {
34
41
  {thread.title}
35
42
  </a>
36
43
  <span className={`shrink-0 text-xs text-muted-foreground ${NUMERIC}`}>
37
- {thread.replyCount.toLocaleString('en')}
44
+ {thread.replyCount.label}
38
45
  </span>
39
46
  </div>
40
47
 
41
48
  <p className="truncate text-xs text-muted-foreground">
42
49
  <UserRef user={thread.author} className="font-medium" />
43
- {' in '}
50
+ {` ${c('in')} `}
44
51
  <a href={thread.forum.href} className={MUTED_LINK}>
45
52
  {thread.forum.label}
46
53
  </a>
@@ -1,5 +1,6 @@
1
+ import type { MemberProfileModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Avatar, Card, CardContent, cn } from '@meith/ui'
2
- import type { MemberProfileModel } from '@meith/theme-kit'
3
4
 
4
5
  import { BUTTON, ClubBar, HEADING, MICRO, NUMERIC, PAGE_BODY, PanelHead, Stamp } from '../shared'
5
6
 
@@ -14,7 +15,10 @@ export function MemberProfile({
14
15
  fields,
15
16
  actions,
16
17
  regions,
17
- }: MemberProfileModel) {
18
+ copy,
19
+ }: MemberProfileModel & { copy: SlotCopy }) {
20
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.memberProfile.${key}`)
21
+
18
22
  return (
19
23
  <div className={PAGE_BODY}>
20
24
  <Card className="flex items-stretch">
@@ -40,7 +44,7 @@ export function MemberProfile({
40
44
 
41
45
  {actions.length > 0 && (
42
46
  <nav
43
- aria-label="Member actions"
47
+ aria-label={c('memberActions')}
44
48
  className="flex shrink-0 flex-wrap items-center gap-2"
45
49
  >
46
50
  {actions.map((action, index) => (
@@ -63,21 +67,19 @@ export function MemberProfile({
63
67
 
64
68
  <dl className="flex flex-wrap gap-x-6 gap-y-1 border-t-2 border-t-secondary bg-surface px-4 py-2.5 text-xs">
65
69
  <div className="flex items-baseline gap-1.5">
66
- <dt className={MICRO}>Posts</dt>
67
- <dd className={`${NUMERIC} font-semibold text-foreground`}>
68
- {postCount.toLocaleString('en')}
69
- </dd>
70
+ <dt className={MICRO}>{c('posts')}</dt>
71
+ <dd className={`${NUMERIC} font-semibold text-foreground`}>{postCount.label}</dd>
70
72
  </div>
71
73
  <div className="flex items-baseline gap-1.5">
72
- <dt className={MICRO}>Joined</dt>
74
+ <dt className={MICRO}>{c('joined')}</dt>
73
75
  <dd className="font-semibold text-foreground">
74
76
  <Stamp at={joinedAt} />
75
77
  </dd>
76
78
  </div>
77
79
  <div className="flex items-baseline gap-1.5">
78
- <dt className={MICRO}>Last visit</dt>
80
+ <dt className={MICRO}>{c('lastVisit')}</dt>
79
81
  <dd className="font-semibold text-foreground">
80
- {lastVisitAt === null ? 'Never' : <Stamp at={lastVisitAt} />}
82
+ {lastVisitAt === null ? c('never') : <Stamp at={lastVisitAt} />}
81
83
  </dd>
82
84
  </div>
83
85
  </dl>
@@ -86,7 +88,7 @@ export function MemberProfile({
86
88
 
87
89
  {fields.length > 0 && (
88
90
  <Card aria-labelledby="profile-fields-heading">
89
- <PanelHead id="profile-fields-heading" title="About" />
91
+ <PanelHead id="profile-fields-heading" title={c('about')} />
90
92
  <CardContent className="px-4 py-3">
91
93
  <dl className="grid gap-x-6 gap-y-2.5 sm:grid-cols-2">
92
94
  {fields.map((field) => (
@@ -102,7 +104,7 @@ export function MemberProfile({
102
104
 
103
105
  {signatureHtml !== null && (
104
106
  <Card aria-labelledby="profile-signature-heading">
105
- <PanelHead id="profile-signature-heading" title="Signature" />
107
+ <PanelHead id="profile-signature-heading" title={c('signature')} />
106
108
  <CardContent className="px-4 py-3">
107
109
  <div
108
110
  className="prose-md text-sm text-muted-foreground"
@@ -1,12 +1,15 @@
1
- import type { NavigationModel } from '@meith/theme-kit'
1
+ import type { NavigationModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
2
3
 
3
4
  import { MICRO, MUTED_LINK, PAGE } from '../shared'
4
5
 
5
- export function Navigation({ items }: NavigationModel) {
6
+ export function Navigation({ items, copy }: NavigationModel & { copy: SlotCopy }) {
6
7
  if (items.length === 0) return null
7
8
 
9
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.navigation.${key}`)
10
+
8
11
  return (
9
- <nav aria-label="Breadcrumb" className="border-b border-border bg-card">
12
+ <nav aria-label={c('breadcrumb')} className="border-b border-border bg-card">
10
13
  <ol
11
14
  className={`${PAGE} flex items-center gap-2 overflow-x-auto py-2 whitespace-nowrap ${MICRO}`}
12
15
  >
@@ -1,25 +1,28 @@
1
+ import type { NoticeModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { Alert, AlertDescription, AlertTitle } from '@meith/ui'
2
- import type { NoticeModel } from '@meith/theme-kit'
3
4
 
4
5
  import { MICRO, MUTED_LINK } from '../shared'
5
6
 
6
- const KIND_LABELS: Record<NoticeModel['kind'], string> = {
7
- info: 'Notice',
8
- success: 'Done',
9
- warning: 'Warning',
10
- error: 'Error',
11
- }
7
+ export function Notice({ kind, message, dismissHref, copy }: NoticeModel & { copy: SlotCopy }) {
8
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.notice.${key}`)
9
+
10
+ const kindLabels: Record<NoticeModel['kind'], string> = {
11
+ info: c('kindInfo'),
12
+ success: c('kindSuccess'),
13
+ warning: c('kindWarning'),
14
+ error: c('kindError'),
15
+ }
12
16
 
13
- export function Notice({ kind, message, dismissHref }: NoticeModel) {
14
17
  return (
15
18
  <Alert tone={kind}>
16
19
  <AlertDescription>
17
- <AlertTitle className={MICRO}>{KIND_LABELS[kind]}</AlertTitle> {message}
20
+ <AlertTitle className={MICRO}>{kindLabels[kind]}</AlertTitle> {message}
18
21
  </AlertDescription>
19
22
 
20
23
  {dismissHref !== null && (
21
24
  <a href={dismissHref} className={`shrink-0 text-xs ${MUTED_LINK}`}>
22
- Dismiss
25
+ {c('dismiss')}
23
26
  </a>
24
27
  )}
25
28
  </Alert>
@@ -1,5 +1,6 @@
1
+ import type { PaginationModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
1
3
  import { cn } from '@meith/ui'
2
- import type { PaginationModel } from '@meith/theme-kit'
3
4
 
4
5
  import { BUTTON, MICRO, NUMERIC } from '../shared'
5
6
 
@@ -10,21 +11,24 @@ export function Pagination({
10
11
  pages,
11
12
  previousHref,
12
13
  nextHref,
13
- }: PaginationModel) {
14
+ copy,
15
+ }: PaginationModel & { copy: SlotCopy }) {
14
16
  if (pageCount <= 1 && previousHref === null && nextHref === null) return null
15
17
 
18
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.pagination.${key}`)
19
+
16
20
  const step = cn(BUTTON, 'min-w-20 justify-center border border-border bg-card hover:bg-accent')
17
21
  const stepDisabled = cn(step, 'pointer-events-none opacity-40')
18
22
 
19
23
  return (
20
- <nav aria-label="Pagination" className="flex flex-wrap items-center justify-between gap-3">
24
+ <nav aria-label={c('pagination')} className="flex flex-wrap items-center justify-between gap-3">
21
25
  {previousHref === null ? (
22
26
  <span className={stepDisabled} aria-hidden="true">
23
- Previous
27
+ {c('previous')}
24
28
  </span>
25
29
  ) : (
26
30
  <a href={previousHref} rel="prev" className={step}>
27
- Previous
31
+ {c('previous')}
28
32
  </a>
29
33
  )}
30
34
 
@@ -43,7 +47,7 @@ export function Pagination({
43
47
  <a
44
48
  href={entry.href}
45
49
  aria-current={entry.isCurrent ? 'page' : undefined}
46
- aria-label={`Page ${entry.page}`}
50
+ aria-label={`${c('page')} ${entry.page}`}
47
51
  className={cn(
48
52
  BUTTON,
49
53
  'min-w-8 justify-center px-2.5',
@@ -61,18 +65,20 @@ export function Pagination({
61
65
 
62
66
  <li className={`ml-2 whitespace-nowrap ${MICRO}`}>
63
67
  <span className={NUMERIC}>
64
- {pageCountIsExact ? `Page ${page} of ${pageCount}` : `Page ${page}`}
68
+ {pageCountIsExact
69
+ ? `${c('page')} ${page} ${c('of')} ${pageCount}`
70
+ : `${c('page')} ${page}`}
65
71
  </span>
66
72
  </li>
67
73
  </ol>
68
74
 
69
75
  {nextHref === null ? (
70
76
  <span className={stepDisabled} aria-hidden="true">
71
- Next
77
+ {c('next')}
72
78
  </span>
73
79
  ) : (
74
80
  <a href={nextHref} rel="next" className={step}>
75
- Next
81
+ {c('next')}
76
82
  </a>
77
83
  )}
78
84
  </nav>
@@ -1,5 +1,6 @@
1
- import { Separator, cn } from '@meith/ui'
2
- import type { PostActionsSlotModel } from '@meith/theme-kit'
1
+ import type { PostActionsSlotModel, SlotCopy } from '@meith/theme-kit'
2
+ import { fromSlotCopy } from '@meith/theme-kit'
3
+ import { cn, Separator } from '@meith/ui'
3
4
 
4
5
  import { BUTTON, isEmptyRegion } from '../shared'
5
6
 
@@ -10,18 +11,24 @@ interface Action {
10
11
 
11
12
  const ACTION = cn(BUTTON, 'h-7 px-2.5 text-muted-foreground hover:bg-accent hover:text-foreground')
12
13
 
13
- export function PostActions({ actions, children }: PostActionsSlotModel) {
14
+ export function PostActions({
15
+ actions,
16
+ children,
17
+ copy,
18
+ }: PostActionsSlotModel & { copy: SlotCopy }) {
19
+ const c = (key: string) => fromSlotCopy(copy, `clubhouse.postActions.${key}`)
20
+
14
21
  const reader: Action[] = [
15
- actions.quoteHref === null ? null : { href: actions.quoteHref, label: 'Quote' },
16
- actions.editHref === null ? null : { href: actions.editHref, label: 'Edit' },
17
- actions.rateHref === null ? null : { href: actions.rateHref, label: 'Rate' },
18
- actions.reportHref === null ? null : { href: actions.reportHref, label: 'Report' },
22
+ actions.quoteHref === null ? null : { href: actions.quoteHref, label: c('quote') },
23
+ actions.editHref === null ? null : { href: actions.editHref, label: c('edit') },
24
+ actions.rateHref === null ? null : { href: actions.rateHref, label: c('rate') },
25
+ actions.reportHref === null ? null : { href: actions.reportHref, label: c('report') },
19
26
  ].filter((action): action is Action => action !== null)
20
27
 
21
28
  const staff: Action[] = [
22
- actions.restoreHref === null ? null : { href: actions.restoreHref, label: 'Restore' },
23
- actions.warnHref === null ? null : { href: actions.warnHref, label: 'Warn' },
24
- actions.moderateHref === null ? null : { href: actions.moderateHref, label: 'Moderate' },
29
+ actions.restoreHref === null ? null : { href: actions.restoreHref, label: c('restore') },
30
+ actions.warnHref === null ? null : { href: actions.warnHref, label: c('warn') },
31
+ actions.moderateHref === null ? null : { href: actions.moderateHref, label: c('moderate') },
25
32
  ].filter((action): action is Action => action !== null)
26
33
 
27
34
  const extra = isEmptyRegion(children) ? null : children
@@ -30,7 +37,7 @@ export function PostActions({ actions, children }: PostActionsSlotModel) {
30
37
 
31
38
  return (
32
39
  <nav
33
- aria-label="Post actions"
40
+ aria-label={c('postActions')}
34
41
  className="flex flex-wrap items-center gap-1 border-t border-border bg-surface px-3 py-1.5 empty:hidden"
35
42
  >
36
43
  {reader.map((action) => (