fix(notifications): a notice keeps what to say and says it in the reader's language when shown

This commit is contained in:
2026-10-29 22:37:14 +01:00
parent 6986eb1937
commit 4ef772d37b
125 changed files with 973 additions and 674 deletions
@@ -29,16 +29,18 @@ import { useLiveQuery } from "../../lib/useLiveQuery";
import { focusAccessRequestsTab } from "../../lib/adminUsersTab";
import { focusSettingsTab } from "../../lib/settingsTab";
import {
type ChannelSubscribedMeta,
clearAll as clearClient,
dismiss as dismissClient,
getNotifications,
getUnreadCount,
markAllRead as markAllClientRead,
msg,
type Notification as ClientNotif,
remove as removeClient,
resolveVideo,
sayNotif,
subscribe,
type Notification as ClientNotif,
type ChannelSubscribedMeta,
type VideoHiddenMeta,
type VideoWatchedMeta,
} from "../../lib/notifications";
@@ -250,7 +252,7 @@ export default function NotificationsPanel() {
// Quietly resolve the now-stale notice (no confirmation toast — the change is visible).
resolveVideo(meta.videoId);
})
.catch((e) => notifyActionError(e, t("inbox.revertFailed")));
.catch((e) => notifyActionError(e, msg("inbox.revertFailed")));
}
// --- The rows' ONE menu -------------------------------------------------------------
@@ -707,10 +709,12 @@ function serverRowText(
* Trimmed as Back saves it (`lib/listNav`), or a title ending in a space never matches its row. */
const rowName = (title: string, body: string | null | undefined): string =>
(body ? `${title}: ${body}` : title).trim();
const clientRowName = (n: ClientNotif): string =>
n.title ? rowName(n.title, n.message) : rowName(n.message, null);
const clientRowName = (n: ClientNotif, t: TFunction): string =>
n.title
? rowName(sayNotif(n.title, t), sayNotif(n.message, t))
: rowName(sayNotif(n.message, t), null);
const entryName = (e: InboxEntry, t: TFunction, lang: string): string => {
if (e.src === "client") return clientRowName(e.n);
if (e.src === "client") return clientRowName(e.n, t);
const { title, body } = serverRowText(e.n, t, lang);
return rowName(title, body);
};
@@ -854,15 +858,15 @@ function ClientActivityRow({
const access = n.meta?.kind === "access-requests" ? n.meta : null;
return (
<div
{...navItemAttrs(navIndex, clientRowName(n))}
{...navItemAttrs(navIndex, clientRowName(n, t))}
{...rowProps}
className={`${SURFACE.card} group p-3.5 flex items-start gap-3 ${needsAction ? "ring-1 ring-accent/30" : ""}`}
>
<Icon className={`w-4 h-4 shrink-0 mt-0.5 ${color}`} />
<div className="min-w-0 flex-1">
{n.title && <div className="text-sm font-semibold">{n.title}</div>}
{n.title && <div className="text-sm font-semibold">{sayNotif(n.title, t)}</div>}
<div className="text-sm wrap-break-word">
{n.message}
{sayNotif(n.message, t)}
{n.repeat > 1 && (
<span className="ml-1.5 align-middle text-2xs font-semibold text-muted tabular-nums">
×{n.repeat}