@meith/theme-phasebook 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.
- package/package.json +4 -4
- package/src/copy.ts +276 -0
- package/src/index.ts +2 -2
- package/src/messages/en.json +149 -0
- package/src/messages/index.ts +5 -0
- package/src/shared.tsx +5 -5
- package/src/slots/announcement.tsx +13 -3
- package/src/slots/board-index.tsx +12 -5
- package/src/slots/board-stats.tsx +14 -12
- package/src/slots/discovery-view.tsx +13 -7
- package/src/slots/error-notice.tsx +17 -6
- package/src/slots/footer.tsx +15 -4
- package/src/slots/forum-display.tsx +23 -14
- package/src/slots/forum-row.tsx +10 -7
- package/src/slots/header.tsx +17 -4
- package/src/slots/latest-posts.tsx +12 -8
- package/src/slots/latest-threads.tsx +18 -9
- package/src/slots/member-profile.tsx +15 -13
- package/src/slots/navigation.tsx +6 -3
- package/src/slots/notice.tsx +10 -8
- package/src/slots/pagination.tsx +13 -10
- package/src/slots/panel-nav.tsx +30 -8
- package/src/slots/panel-page.tsx +3 -8
- package/src/slots/post-actions.tsx +17 -10
- package/src/slots/post-bit.tsx +21 -16
- package/src/slots/post-form.tsx +7 -3
- package/src/slots/redirect-notice.tsx +15 -6
- package/src/slots/search-form.tsx +15 -8
- package/src/slots/search-results.tsx +18 -17
- package/src/slots/shell.tsx +4 -3
- package/src/slots/subforum-list.tsx +9 -5
- package/src/slots/thread-row.tsx +16 -13
- package/src/slots/thread-view.tsx +33 -10
- package/src/slots/user-panel.tsx +18 -14
- package/src/slots/who-is-online.tsx +33 -16
- package/src/theme.ts +61 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meith/theme-phasebook",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "A theme for Meith with a familiar social shape, built on the default theme's slots.",
|
|
5
5
|
"license": "LGPL-3.0-or-later",
|
|
6
6
|
"repository": {
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"access": "public"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@meith/
|
|
24
|
-
"@meith/theme-
|
|
25
|
-
"@meith/
|
|
23
|
+
"@meith/ui": "^0.8.0",
|
|
24
|
+
"@meith/theme-default": "^0.8.0",
|
|
25
|
+
"@meith/theme-kit": "^0.8.0"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": "^19.2.0"
|
package/src/copy.ts
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import type { SlotCopy, Translator } from '@meith/theme-kit'
|
|
2
|
+
|
|
3
|
+
function copyFor(t: Translator, keys: readonly string[]): SlotCopy {
|
|
4
|
+
const copy: Record<string, string> = {}
|
|
5
|
+
for (const key of keys) copy[key] = t.t(key)
|
|
6
|
+
return copy
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function announcementCopy(t: Translator): SlotCopy {
|
|
10
|
+
return copyFor(t, ['phasebook.announcement.announcement'])
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function boardIndexCopy(t: Translator): SlotCopy {
|
|
14
|
+
return copyFor(t, ['phasebook.boardIndex.activityAriaLabel', 'phasebook.boardIndex.markAllRead'])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function boardStatsCopy(t: Translator): SlotCopy {
|
|
18
|
+
return copyFor(t, [
|
|
19
|
+
'phasebook.boardStats.counted',
|
|
20
|
+
'phasebook.boardStats.members',
|
|
21
|
+
'phasebook.boardStats.newestMember',
|
|
22
|
+
'phasebook.boardStats.notComputed',
|
|
23
|
+
'phasebook.boardStats.posts',
|
|
24
|
+
'phasebook.boardStats.threads',
|
|
25
|
+
'phasebook.boardStats.title',
|
|
26
|
+
])
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function discoveryViewCopy(t: Translator): SlotCopy {
|
|
30
|
+
return copyFor(t, [
|
|
31
|
+
'phasebook.discoveryView.by',
|
|
32
|
+
'phasebook.discoveryView.in',
|
|
33
|
+
'phasebook.discoveryView.lastPost',
|
|
34
|
+
'phasebook.discoveryView.reply.one',
|
|
35
|
+
'phasebook.discoveryView.reply.other',
|
|
36
|
+
'phasebook.discoveryView.startedBy',
|
|
37
|
+
])
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function errorNoticeCopy(t: Translator): SlotCopy {
|
|
41
|
+
return copyFor(t, [
|
|
42
|
+
'phasebook.errorNotice.error',
|
|
43
|
+
'phasebook.errorNotice.home',
|
|
44
|
+
'phasebook.errorNotice.quote',
|
|
45
|
+
])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function footerCopy(t: Translator): SlotCopy {
|
|
49
|
+
return copyFor(t, ['phasebook.footer.ariaLabel', 'phasebook.footer.timezone'])
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function forumDisplayCopy(t: Translator): SlotCopy {
|
|
53
|
+
return copyFor(t, [
|
|
54
|
+
'phasebook.forumDisplay.emptyForum',
|
|
55
|
+
'phasebook.forumDisplay.emptyForumInvite',
|
|
56
|
+
'phasebook.forumDisplay.markRead',
|
|
57
|
+
'phasebook.forumDisplay.newThread',
|
|
58
|
+
'phasebook.forumDisplay.noThreadsYet',
|
|
59
|
+
'phasebook.forumDisplay.post.one',
|
|
60
|
+
'phasebook.forumDisplay.post.other',
|
|
61
|
+
'phasebook.forumDisplay.startFirstThread',
|
|
62
|
+
'phasebook.forumDisplay.startThreadIn',
|
|
63
|
+
'phasebook.forumDisplay.thread.one',
|
|
64
|
+
'phasebook.forumDisplay.thread.other',
|
|
65
|
+
])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function forumRowCopy(t: Translator): SlotCopy {
|
|
69
|
+
return copyFor(t, [
|
|
70
|
+
'phasebook.forumRow.newPosts',
|
|
71
|
+
'phasebook.forumRow.noPostsYet',
|
|
72
|
+
'phasebook.forumRow.post.one',
|
|
73
|
+
'phasebook.forumRow.post.other',
|
|
74
|
+
'phasebook.forumRow.thread.one',
|
|
75
|
+
'phasebook.forumRow.thread.other',
|
|
76
|
+
])
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function headerCopy(t: Translator): SlotCopy {
|
|
80
|
+
return copyFor(t, ['phasebook.header.sectionsAriaLabel'])
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function latestPostsCopy(t: Translator): SlotCopy {
|
|
84
|
+
return copyFor(t, [
|
|
85
|
+
'phasebook.latestPosts.empty',
|
|
86
|
+
'phasebook.latestPosts.in',
|
|
87
|
+
'phasebook.latestPosts.title',
|
|
88
|
+
])
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function latestThreadsCopy(t: Translator): SlotCopy {
|
|
92
|
+
return copyFor(t, [
|
|
93
|
+
'phasebook.latestThreads.empty',
|
|
94
|
+
'phasebook.latestThreads.reply.one',
|
|
95
|
+
'phasebook.latestThreads.reply.other',
|
|
96
|
+
'phasebook.latestThreads.title',
|
|
97
|
+
])
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function memberProfileCopy(t: Translator): SlotCopy {
|
|
101
|
+
return copyFor(t, [
|
|
102
|
+
'phasebook.memberProfile.about',
|
|
103
|
+
'phasebook.memberProfile.actionsAriaLabel',
|
|
104
|
+
'phasebook.memberProfile.joined',
|
|
105
|
+
'phasebook.memberProfile.lastVisit',
|
|
106
|
+
'phasebook.memberProfile.never',
|
|
107
|
+
'phasebook.memberProfile.posts',
|
|
108
|
+
'phasebook.memberProfile.signature',
|
|
109
|
+
])
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function navigationCopy(t: Translator): SlotCopy {
|
|
113
|
+
return copyFor(t, ['phasebook.navigation.ariaLabel'])
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function noticeCopy(t: Translator): SlotCopy {
|
|
117
|
+
return copyFor(t, [
|
|
118
|
+
'phasebook.notice.dismiss',
|
|
119
|
+
'phasebook.notice.error',
|
|
120
|
+
'phasebook.notice.info',
|
|
121
|
+
'phasebook.notice.success',
|
|
122
|
+
'phasebook.notice.warning',
|
|
123
|
+
])
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function paginationCopy(t: Translator): SlotCopy {
|
|
127
|
+
return copyFor(t, [
|
|
128
|
+
'phasebook.pagination.ariaLabel',
|
|
129
|
+
'phasebook.pagination.next',
|
|
130
|
+
'phasebook.pagination.of',
|
|
131
|
+
'phasebook.pagination.page',
|
|
132
|
+
'phasebook.pagination.previous',
|
|
133
|
+
])
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function panelNavCopy(t: Translator): SlotCopy {
|
|
137
|
+
return copyFor(t, ['phasebook.panelNav.waiting'])
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function postActionsCopy(t: Translator): SlotCopy {
|
|
141
|
+
return copyFor(t, [
|
|
142
|
+
'phasebook.postActions.ariaLabel',
|
|
143
|
+
'phasebook.postActions.edit',
|
|
144
|
+
'phasebook.postActions.moderate',
|
|
145
|
+
'phasebook.postActions.quote',
|
|
146
|
+
'phasebook.postActions.rate',
|
|
147
|
+
'phasebook.postActions.report',
|
|
148
|
+
'phasebook.postActions.restore',
|
|
149
|
+
'phasebook.postActions.warn',
|
|
150
|
+
])
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function postBitCopy(t: Translator): SlotCopy {
|
|
154
|
+
return copyFor(t, [
|
|
155
|
+
'phasebook.postBit.deletedPost',
|
|
156
|
+
'phasebook.postBit.hiddenNote',
|
|
157
|
+
'phasebook.postBit.ignoring',
|
|
158
|
+
'phasebook.postBit.moderatorsOnly',
|
|
159
|
+
'phasebook.postBit.online',
|
|
160
|
+
'phasebook.postBit.post.one',
|
|
161
|
+
'phasebook.postBit.post.other',
|
|
162
|
+
'phasebook.postBit.rep',
|
|
163
|
+
'phasebook.postBit.showAnyway',
|
|
164
|
+
'phasebook.postBit.waitingApproval',
|
|
165
|
+
])
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function postFormCopy(t: Translator): SlotCopy {
|
|
169
|
+
return copyFor(t, ['phasebook.postForm.cannotPost'])
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function redirectNoticeCopy(t: Translator): SlotCopy {
|
|
173
|
+
return copyFor(t, [
|
|
174
|
+
'phasebook.redirectNotice.continueNow',
|
|
175
|
+
'phasebook.redirectNotice.continuing',
|
|
176
|
+
'phasebook.redirectNotice.pleaseWait',
|
|
177
|
+
'phasebook.redirectNotice.redirecting',
|
|
178
|
+
'phasebook.redirectNotice.second.one',
|
|
179
|
+
'phasebook.redirectNotice.second.other',
|
|
180
|
+
])
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function searchFormCopy(t: Translator): SlotCopy {
|
|
184
|
+
return copyFor(t, [
|
|
185
|
+
'phasebook.searchForm.in',
|
|
186
|
+
'phasebook.searchForm.placeholder',
|
|
187
|
+
'phasebook.searchForm.search',
|
|
188
|
+
'phasebook.searchForm.searchFor',
|
|
189
|
+
'phasebook.searchForm.sortBy',
|
|
190
|
+
])
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function searchResultsCopy(t: Translator): SlotCopy {
|
|
194
|
+
return copyFor(t, [
|
|
195
|
+
'phasebook.searchResults.clearFilters',
|
|
196
|
+
'phasebook.searchResults.newSearch',
|
|
197
|
+
'phasebook.searchResults.noHits',
|
|
198
|
+
'phasebook.searchResults.removeFilter',
|
|
199
|
+
'phasebook.searchResults.resultsFor',
|
|
200
|
+
'phasebook.searchResults.searched',
|
|
201
|
+
'phasebook.searchResults.searchedNote',
|
|
202
|
+
])
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function shellCopy(t: Translator): SlotCopy {
|
|
206
|
+
return copyFor(t, ['phasebook.shell.skipToContent'])
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function subforumListCopy(t: Translator): SlotCopy {
|
|
210
|
+
return copyFor(t, [
|
|
211
|
+
'phasebook.subforumList.thread.one',
|
|
212
|
+
'phasebook.subforumList.thread.other',
|
|
213
|
+
'phasebook.subforumList.title',
|
|
214
|
+
])
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function threadRowCopy(t: Translator): SlotCopy {
|
|
218
|
+
return copyFor(t, [
|
|
219
|
+
'phasebook.threadRow.by',
|
|
220
|
+
'phasebook.threadRow.latestReply',
|
|
221
|
+
'phasebook.threadRow.locked',
|
|
222
|
+
'phasebook.threadRow.moved',
|
|
223
|
+
'phasebook.threadRow.newPosts',
|
|
224
|
+
'phasebook.threadRow.noRepliesYet',
|
|
225
|
+
'phasebook.threadRow.pinned',
|
|
226
|
+
'phasebook.threadRow.reply.one',
|
|
227
|
+
'phasebook.threadRow.reply.other',
|
|
228
|
+
'phasebook.threadRow.startedBy',
|
|
229
|
+
'phasebook.threadRow.view.one',
|
|
230
|
+
'phasebook.threadRow.view.other',
|
|
231
|
+
])
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function threadViewCopy(t: Translator): SlotCopy {
|
|
235
|
+
return copyFor(t, [
|
|
236
|
+
'phasebook.threadView.locked',
|
|
237
|
+
'phasebook.threadView.markRead',
|
|
238
|
+
'phasebook.threadView.moved',
|
|
239
|
+
'phasebook.threadView.pinned',
|
|
240
|
+
'phasebook.threadView.reply.one',
|
|
241
|
+
'phasebook.threadView.reply.other',
|
|
242
|
+
'phasebook.threadView.replyAction',
|
|
243
|
+
'phasebook.threadView.view.one',
|
|
244
|
+
'phasebook.threadView.view.other',
|
|
245
|
+
])
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function userPanelCopy(t: Translator): SlotCopy {
|
|
249
|
+
return copyFor(t, [
|
|
250
|
+
'phasebook.userPanel.accountAriaLabel',
|
|
251
|
+
'phasebook.userPanel.messages',
|
|
252
|
+
'phasebook.userPanel.notifications',
|
|
253
|
+
'phasebook.userPanel.signedIn',
|
|
254
|
+
'phasebook.userPanel.unreadMessages',
|
|
255
|
+
'phasebook.userPanel.unreadNotifications',
|
|
256
|
+
])
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function whoIsOnlineCopy(t: Translator): SlotCopy {
|
|
260
|
+
return copyFor(t, [
|
|
261
|
+
'phasebook.whoIsOnline.and',
|
|
262
|
+
'phasebook.whoIsOnline.guest.one',
|
|
263
|
+
'phasebook.whoIsOnline.guest.other',
|
|
264
|
+
'phasebook.whoIsOnline.invisible',
|
|
265
|
+
'phasebook.whoIsOnline.member.one',
|
|
266
|
+
'phasebook.whoIsOnline.member.other',
|
|
267
|
+
'phasebook.whoIsOnline.more',
|
|
268
|
+
'phasebook.whoIsOnline.nobody',
|
|
269
|
+
'phasebook.whoIsOnline.on',
|
|
270
|
+
'phasebook.whoIsOnline.online',
|
|
271
|
+
'phasebook.whoIsOnline.onlyGuests',
|
|
272
|
+
'phasebook.whoIsOnline.record',
|
|
273
|
+
'phasebook.whoIsOnline.seeAll',
|
|
274
|
+
'phasebook.whoIsOnline.title',
|
|
275
|
+
])
|
|
276
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
{
|
|
2
|
+
"phasebook.announcement.announcement": "Announcement",
|
|
3
|
+
"phasebook.boardIndex.activityAriaLabel": "Board activity",
|
|
4
|
+
"phasebook.boardIndex.markAllRead": "Mark all forums read",
|
|
5
|
+
"phasebook.boardStats.counted": "Counted",
|
|
6
|
+
"phasebook.boardStats.members": "Members",
|
|
7
|
+
"phasebook.boardStats.newestMember": "Newest member",
|
|
8
|
+
"phasebook.boardStats.notComputed": "The board’s totals are rolled up on a schedule, and the first run has not happened.",
|
|
9
|
+
"phasebook.boardStats.posts": "Posts",
|
|
10
|
+
"phasebook.boardStats.threads": "Threads",
|
|
11
|
+
"phasebook.boardStats.title": "Board stats",
|
|
12
|
+
"phasebook.discoveryView.by": "by",
|
|
13
|
+
"phasebook.discoveryView.in": "in",
|
|
14
|
+
"phasebook.discoveryView.lastPost": "last post",
|
|
15
|
+
"phasebook.discoveryView.reply.one": "reply",
|
|
16
|
+
"phasebook.discoveryView.reply.other": "replies",
|
|
17
|
+
"phasebook.discoveryView.startedBy": "started by",
|
|
18
|
+
"phasebook.errorNotice.error": "Error",
|
|
19
|
+
"phasebook.errorNotice.home": "Forum home",
|
|
20
|
+
"phasebook.errorNotice.quote": "Quote this if you report it:",
|
|
21
|
+
"phasebook.footer.ariaLabel": "Footer",
|
|
22
|
+
"phasebook.footer.timezone": "Times are shown in",
|
|
23
|
+
"phasebook.forumDisplay.emptyForum": "Nothing has been posted in this forum.",
|
|
24
|
+
"phasebook.forumDisplay.emptyForumInvite": "Nothing has been posted in this forum. Yours would be the first.",
|
|
25
|
+
"phasebook.forumDisplay.markRead": "Mark read",
|
|
26
|
+
"phasebook.forumDisplay.newThread": "New thread",
|
|
27
|
+
"phasebook.forumDisplay.noThreadsYet": "No threads here yet",
|
|
28
|
+
"phasebook.forumDisplay.post.one": "post",
|
|
29
|
+
"phasebook.forumDisplay.post.other": "posts",
|
|
30
|
+
"phasebook.forumDisplay.startFirstThread": "Start the first thread",
|
|
31
|
+
"phasebook.forumDisplay.startThreadIn": "Start a thread in",
|
|
32
|
+
"phasebook.forumDisplay.thread.one": "thread",
|
|
33
|
+
"phasebook.forumDisplay.thread.other": "threads",
|
|
34
|
+
"phasebook.forumRow.newPosts": "(new posts)",
|
|
35
|
+
"phasebook.forumRow.noPostsYet": "No posts yet",
|
|
36
|
+
"phasebook.forumRow.post.one": "post",
|
|
37
|
+
"phasebook.forumRow.post.other": "posts",
|
|
38
|
+
"phasebook.forumRow.thread.one": "thread",
|
|
39
|
+
"phasebook.forumRow.thread.other": "threads",
|
|
40
|
+
"phasebook.header.sectionsAriaLabel": "Board sections",
|
|
41
|
+
"phasebook.latestPosts.empty": "The newest posts you can see will appear here.",
|
|
42
|
+
"phasebook.latestPosts.in": "in",
|
|
43
|
+
"phasebook.latestPosts.title": "Latest posts",
|
|
44
|
+
"phasebook.latestThreads.empty": "The newest threads you can see will appear here.",
|
|
45
|
+
"phasebook.latestThreads.reply.one": "reply",
|
|
46
|
+
"phasebook.latestThreads.reply.other": "replies",
|
|
47
|
+
"phasebook.latestThreads.title": "Latest threads",
|
|
48
|
+
"phasebook.memberProfile.about": "About",
|
|
49
|
+
"phasebook.memberProfile.actionsAriaLabel": "Member actions",
|
|
50
|
+
"phasebook.memberProfile.joined": "Joined",
|
|
51
|
+
"phasebook.memberProfile.lastVisit": "Last visit",
|
|
52
|
+
"phasebook.memberProfile.never": "Never",
|
|
53
|
+
"phasebook.memberProfile.posts": "Posts",
|
|
54
|
+
"phasebook.memberProfile.signature": "Signature",
|
|
55
|
+
"phasebook.navigation.ariaLabel": "Breadcrumb",
|
|
56
|
+
"phasebook.notice.dismiss": "Dismiss",
|
|
57
|
+
"phasebook.notice.error": "Error",
|
|
58
|
+
"phasebook.notice.info": "Notice",
|
|
59
|
+
"phasebook.notice.success": "Done",
|
|
60
|
+
"phasebook.notice.warning": "Warning",
|
|
61
|
+
"phasebook.pagination.ariaLabel": "Pagination",
|
|
62
|
+
"phasebook.pagination.next": "Next",
|
|
63
|
+
"phasebook.pagination.of": "of",
|
|
64
|
+
"phasebook.pagination.page": "Page",
|
|
65
|
+
"phasebook.pagination.previous": "Previous",
|
|
66
|
+
"phasebook.panelNav.waiting": "waiting",
|
|
67
|
+
"phasebook.postActions.ariaLabel": "Post actions",
|
|
68
|
+
"phasebook.postActions.edit": "Edit",
|
|
69
|
+
"phasebook.postActions.moderate": "Moderate",
|
|
70
|
+
"phasebook.postActions.quote": "Quote",
|
|
71
|
+
"phasebook.postActions.rate": "Rate",
|
|
72
|
+
"phasebook.postActions.report": "Report",
|
|
73
|
+
"phasebook.postActions.restore": "Restore",
|
|
74
|
+
"phasebook.postActions.warn": "Warn",
|
|
75
|
+
"phasebook.postBit.deletedPost": "Deleted post.",
|
|
76
|
+
"phasebook.postBit.hiddenNote": "This post is hidden.",
|
|
77
|
+
"phasebook.postBit.ignoring": "You are ignoring",
|
|
78
|
+
"phasebook.postBit.moderatorsOnly": "Only moderators can see this.",
|
|
79
|
+
"phasebook.postBit.online": "Online",
|
|
80
|
+
"phasebook.postBit.post.one": "post",
|
|
81
|
+
"phasebook.postBit.post.other": "posts",
|
|
82
|
+
"phasebook.postBit.rep": "rep",
|
|
83
|
+
"phasebook.postBit.showAnyway": "Show it anyway",
|
|
84
|
+
"phasebook.postBit.waitingApproval": "Waiting for approval.",
|
|
85
|
+
"phasebook.postForm.cannotPost": "Cannot post.",
|
|
86
|
+
"phasebook.redirectNotice.continueNow": "Continue now",
|
|
87
|
+
"phasebook.redirectNotice.continuing": "Continuing on its own in",
|
|
88
|
+
"phasebook.redirectNotice.pleaseWait": "Please wait",
|
|
89
|
+
"phasebook.redirectNotice.redirecting": "Redirecting",
|
|
90
|
+
"phasebook.redirectNotice.second.one": "second",
|
|
91
|
+
"phasebook.redirectNotice.second.other": "seconds",
|
|
92
|
+
"phasebook.searchForm.in": "In",
|
|
93
|
+
"phasebook.searchForm.placeholder": "Words in a subject or a post",
|
|
94
|
+
"phasebook.searchForm.search": "Search",
|
|
95
|
+
"phasebook.searchForm.searchFor": "Search for",
|
|
96
|
+
"phasebook.searchForm.sortBy": "Sort by",
|
|
97
|
+
"phasebook.searchResults.clearFilters": "Clear filters",
|
|
98
|
+
"phasebook.searchResults.newSearch": "Start a new search",
|
|
99
|
+
"phasebook.searchResults.noHits": "Nothing matched — or nothing you can see does. Try fewer words, or a different spelling.",
|
|
100
|
+
"phasebook.searchResults.removeFilter": "— remove this filter",
|
|
101
|
+
"phasebook.searchResults.resultsFor": "Results for",
|
|
102
|
+
"phasebook.searchResults.searched": "Searched",
|
|
103
|
+
"phasebook.searchResults.searchedNote": "Results are checked against your access every time this page is opened, so they can change.",
|
|
104
|
+
"phasebook.shell.skipToContent": "Skip to content",
|
|
105
|
+
"phasebook.subforumList.thread.one": "thread",
|
|
106
|
+
"phasebook.subforumList.thread.other": "threads",
|
|
107
|
+
"phasebook.subforumList.title": "Subforums",
|
|
108
|
+
"phasebook.threadRow.by": "by",
|
|
109
|
+
"phasebook.threadRow.latestReply": "Latest reply",
|
|
110
|
+
"phasebook.threadRow.locked": "Locked",
|
|
111
|
+
"phasebook.threadRow.moved": "Moved",
|
|
112
|
+
"phasebook.threadRow.newPosts": "(new posts)",
|
|
113
|
+
"phasebook.threadRow.noRepliesYet": "No replies yet",
|
|
114
|
+
"phasebook.threadRow.pinned": "Pinned",
|
|
115
|
+
"phasebook.threadRow.reply.one": "reply",
|
|
116
|
+
"phasebook.threadRow.reply.other": "replies",
|
|
117
|
+
"phasebook.threadRow.startedBy": "Started by",
|
|
118
|
+
"phasebook.threadRow.view.one": "view",
|
|
119
|
+
"phasebook.threadRow.view.other": "views",
|
|
120
|
+
"phasebook.threadView.locked": "Locked — no new replies",
|
|
121
|
+
"phasebook.threadView.markRead": "Mark read",
|
|
122
|
+
"phasebook.threadView.moved": "Moved",
|
|
123
|
+
"phasebook.threadView.pinned": "Pinned",
|
|
124
|
+
"phasebook.threadView.reply.one": "reply",
|
|
125
|
+
"phasebook.threadView.reply.other": "replies",
|
|
126
|
+
"phasebook.threadView.replyAction": "Reply",
|
|
127
|
+
"phasebook.threadView.view.one": "view",
|
|
128
|
+
"phasebook.threadView.view.other": "views",
|
|
129
|
+
"phasebook.userPanel.accountAriaLabel": "Your account",
|
|
130
|
+
"phasebook.userPanel.messages": "Messages",
|
|
131
|
+
"phasebook.userPanel.notifications": "Notifications",
|
|
132
|
+
"phasebook.userPanel.signedIn": "Signed in",
|
|
133
|
+
"phasebook.userPanel.unreadMessages": "unread messages",
|
|
134
|
+
"phasebook.userPanel.unreadNotifications": "unread notifications",
|
|
135
|
+
"phasebook.whoIsOnline.and": "and",
|
|
136
|
+
"phasebook.whoIsOnline.guest.one": "guest",
|
|
137
|
+
"phasebook.whoIsOnline.guest.other": "guests",
|
|
138
|
+
"phasebook.whoIsOnline.invisible": "Invisible",
|
|
139
|
+
"phasebook.whoIsOnline.member.one": "member",
|
|
140
|
+
"phasebook.whoIsOnline.member.other": "members",
|
|
141
|
+
"phasebook.whoIsOnline.more": "more",
|
|
142
|
+
"phasebook.whoIsOnline.nobody": "Nobody is reading the board right now.",
|
|
143
|
+
"phasebook.whoIsOnline.on": "on",
|
|
144
|
+
"phasebook.whoIsOnline.online": "online —",
|
|
145
|
+
"phasebook.whoIsOnline.onlyGuests": "Only guests are reading the board right now.",
|
|
146
|
+
"phasebook.whoIsOnline.record": "Record:",
|
|
147
|
+
"phasebook.whoIsOnline.seeAll": "See all",
|
|
148
|
+
"phasebook.whoIsOnline.title": "Online now"
|
|
149
|
+
}
|
package/src/shared.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { CountModel, PrefixModel, TimeModel, UserRefModel } from '@meith/theme-kit'
|
|
1
2
|
import { Avatar, cn } from '@meith/ui'
|
|
2
|
-
import type { PrefixModel, TimeModel, UserRefModel } from '@meith/theme-kit'
|
|
3
3
|
|
|
4
4
|
export const PAGE = 'mx-auto w-full max-w-6xl px-3 sm:px-4'
|
|
5
5
|
|
|
@@ -176,10 +176,10 @@ export function isEmptyRegion(node: React.ReactNode): boolean {
|
|
|
176
176
|
return Array.isArray(node) && node.length === 0
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
export function count(value:
|
|
180
|
-
return value.
|
|
179
|
+
export function count(value: CountModel): string {
|
|
180
|
+
return value.label
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
export function plural(value:
|
|
184
|
-
return value === 1 ? one : many
|
|
183
|
+
export function plural(value: CountModel, one: string, many: string): string {
|
|
184
|
+
return value.value === 1 ? one : many
|
|
185
185
|
}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import type { AnnouncementModel } from '@meith/theme-kit'
|
|
1
|
+
import type { AnnouncementModel, SlotCopy } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
2
3
|
|
|
3
4
|
import { Circle, MUTED_LINK, Stamp, Tag, UserRef } from '../shared'
|
|
4
5
|
|
|
5
|
-
export function Announcement({
|
|
6
|
+
export function Announcement({
|
|
7
|
+
title,
|
|
8
|
+
bodyHtml,
|
|
9
|
+
postedBy,
|
|
10
|
+
postedAt,
|
|
11
|
+
forum,
|
|
12
|
+
copy,
|
|
13
|
+
}: AnnouncementModel & { copy: SlotCopy }) {
|
|
14
|
+
const c = (key: string) => fromSlotCopy(copy, `phasebook.announcement.${key}`)
|
|
15
|
+
|
|
6
16
|
return (
|
|
7
17
|
<article className="overflow-hidden rounded-lg border border-border bg-card text-card-foreground shadow-elevation">
|
|
8
18
|
<div className="flex items-start gap-2.5 px-4 pt-3">
|
|
@@ -25,7 +35,7 @@ export function Announcement({ title, bodyHtml, postedBy, postedAt, forum }: Ann
|
|
|
25
35
|
</p>
|
|
26
36
|
</div>
|
|
27
37
|
|
|
28
|
-
<Tag className="mt-0.5">
|
|
38
|
+
<Tag className="mt-0.5">{c('announcement')}</Tag>
|
|
29
39
|
</div>
|
|
30
40
|
|
|
31
41
|
<div
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import type { BoardIndexModel } from '@meith/theme-kit'
|
|
1
|
+
import type { BoardIndexModel, SlotCopy } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
2
3
|
|
|
3
|
-
import { FEED, PAGE, PILL_QUIET
|
|
4
|
+
import { FEED, isEmptyRegion, PAGE, PILL_QUIET } from '../shared'
|
|
4
5
|
|
|
5
|
-
export function BoardIndex({
|
|
6
|
+
export function BoardIndex({
|
|
7
|
+
markAllReadAction,
|
|
8
|
+
regions,
|
|
9
|
+
copy,
|
|
10
|
+
}: BoardIndexModel & { copy: SlotCopy }) {
|
|
6
11
|
const hasRail = [regions.latest, regions.online, regions.stats].some(
|
|
7
12
|
(region) => !isEmptyRegion(region),
|
|
8
13
|
)
|
|
9
14
|
|
|
15
|
+
const c = (key: string) => fromSlotCopy(copy, `phasebook.boardIndex.${key}`)
|
|
16
|
+
|
|
10
17
|
return (
|
|
11
18
|
<div className={`${PAGE} py-4 sm:py-6`}>
|
|
12
19
|
<div
|
|
@@ -24,7 +31,7 @@ export function BoardIndex({ markAllReadAction, regions }: BoardIndexModel) {
|
|
|
24
31
|
{markAllReadAction !== null && (
|
|
25
32
|
<form action={markAllReadAction} method="post" className="self-end">
|
|
26
33
|
<button type="submit" className={PILL_QUIET}>
|
|
27
|
-
|
|
34
|
+
{c('markAllRead')}
|
|
28
35
|
</button>
|
|
29
36
|
</form>
|
|
30
37
|
)}
|
|
@@ -36,7 +43,7 @@ export function BoardIndex({ markAllReadAction, regions }: BoardIndexModel) {
|
|
|
36
43
|
|
|
37
44
|
{hasRail && (
|
|
38
45
|
<aside
|
|
39
|
-
aria-label=
|
|
46
|
+
aria-label={c('activityAriaLabel')}
|
|
40
47
|
className="flex min-w-0 flex-col gap-4 lg:sticky lg:top-[4.5rem]"
|
|
41
48
|
>
|
|
42
49
|
{regions.latest}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { BoardStatsModel } from '@meith/theme-kit'
|
|
1
|
+
import type { BoardStatsModel, SlotCopy } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
2
3
|
|
|
3
|
-
import { NUMERIC, Rail, Stamp, UserRef
|
|
4
|
+
import { count, NUMERIC, Rail, Stamp, UserRef } from '../shared'
|
|
4
5
|
|
|
5
6
|
export function BoardStats({
|
|
6
7
|
threadCount,
|
|
@@ -8,20 +9,21 @@ export function BoardStats({
|
|
|
8
9
|
memberCount,
|
|
9
10
|
newestMember,
|
|
10
11
|
computedAt,
|
|
11
|
-
|
|
12
|
+
copy,
|
|
13
|
+
}: BoardStatsModel & { copy: SlotCopy }) {
|
|
14
|
+
const c = (key: string) => fromSlotCopy(copy, `phasebook.boardStats.${key}`)
|
|
15
|
+
|
|
12
16
|
return (
|
|
13
|
-
<Rail title=
|
|
17
|
+
<Rail title={c('title')} titleId="board-stats-heading">
|
|
14
18
|
{computedAt === null ? (
|
|
15
|
-
<p className="px-3 pb-3 text-xs text-muted-foreground">
|
|
16
|
-
The board’s totals are rolled up on a schedule, and the first run has not happened.
|
|
17
|
-
</p>
|
|
19
|
+
<p className="px-3 pb-3 text-xs text-muted-foreground">{c('notComputed')}</p>
|
|
18
20
|
) : (
|
|
19
21
|
<>
|
|
20
22
|
<dl className="grid grid-cols-3 gap-1 px-3 pb-2 text-center">
|
|
21
23
|
{[
|
|
22
|
-
{ label: '
|
|
23
|
-
{ label: '
|
|
24
|
-
{ label: '
|
|
24
|
+
{ label: c('threads'), value: threadCount },
|
|
25
|
+
{ label: c('posts'), value: postCount },
|
|
26
|
+
{ label: c('members'), value: memberCount },
|
|
25
27
|
].map((figure) => (
|
|
26
28
|
<div key={figure.label} className="rounded-lg bg-secondary/60 px-1 py-2">
|
|
27
29
|
<dd className={`text-base font-bold text-foreground ${NUMERIC}`}>
|
|
@@ -35,13 +37,13 @@ export function BoardStats({
|
|
|
35
37
|
<p className="flex flex-wrap items-center gap-x-1.5 px-3 pb-3 text-xs text-muted-foreground">
|
|
36
38
|
{newestMember !== null && (
|
|
37
39
|
<>
|
|
38
|
-
<span>
|
|
40
|
+
<span>{c('newestMember')}</span>
|
|
39
41
|
<UserRef user={newestMember} className="text-xs" />
|
|
40
42
|
<span aria-hidden="true">·</span>
|
|
41
43
|
</>
|
|
42
44
|
)}
|
|
43
45
|
<span className={NUMERIC}>
|
|
44
|
-
|
|
46
|
+
{c('counted')} <Stamp at={computedAt} />
|
|
45
47
|
</span>
|
|
46
48
|
</p>
|
|
47
49
|
</>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { DiscoveryViewModel, SlotCopy, TabModel } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
1
3
|
import { cn } from '@meith/ui'
|
|
2
|
-
import type { DiscoveryViewModel, TabModel } from '@meith/theme-kit'
|
|
3
4
|
|
|
4
|
-
import { Chip, FEED, LINK, PAGE, PILL,
|
|
5
|
+
import { Chip, count, FEED, LINK, PAGE, PILL, plural, Stamp } from '../shared'
|
|
5
6
|
|
|
6
7
|
function Tabs({ label, tabs }: { label: string; tabs: readonly TabModel[] }) {
|
|
7
8
|
if (tabs.length === 0) return null
|
|
@@ -43,7 +44,10 @@ export function DiscoveryView({
|
|
|
43
44
|
nextLabel,
|
|
44
45
|
emptyMessage,
|
|
45
46
|
refusal,
|
|
46
|
-
|
|
47
|
+
copy,
|
|
48
|
+
}: DiscoveryViewModel & { copy: SlotCopy }) {
|
|
49
|
+
const c = (key: string) => fromSlotCopy(copy, `phasebook.discoveryView.${key}`)
|
|
50
|
+
|
|
47
51
|
return (
|
|
48
52
|
<main id="board-content" tabIndex={-1} className={`${PAGE} flex-1 py-4 sm:py-6`}>
|
|
49
53
|
<div className={`${FEED} flex flex-col gap-4`}>
|
|
@@ -83,17 +87,19 @@ export function DiscoveryView({
|
|
|
83
87
|
{row.title}
|
|
84
88
|
</a>
|
|
85
89
|
<Chip>
|
|
86
|
-
{count(row.replyCount)}
|
|
90
|
+
{count(row.replyCount)}{' '}
|
|
91
|
+
{plural(row.replyCount, c('reply.one'), c('reply.other'))}
|
|
87
92
|
</Chip>
|
|
88
93
|
</div>
|
|
89
94
|
|
|
90
95
|
<p className="mt-1 text-xs text-muted-foreground">
|
|
91
|
-
in{' '}
|
|
96
|
+
{c('in')}{' '}
|
|
92
97
|
<a href={row.forum.href} className={LINK}>
|
|
93
98
|
{row.forum.label}
|
|
94
99
|
</a>{' '}
|
|
95
|
-
·
|
|
96
|
-
|
|
100
|
+
· {c('startedBy')} {row.authorUsername} · {c('lastPost')}{' '}
|
|
101
|
+
<Stamp at={row.lastPostAt} />
|
|
102
|
+
{row.lastPostUsername === null ? null : ` ${c('by')} ${row.lastPostUsername}`}
|
|
97
103
|
</p>
|
|
98
104
|
</li>
|
|
99
105
|
))}
|