112 lines
4.4 KiB
TypeScript
112 lines
4.4 KiB
TypeScript
// The labels each component takes, built from a message lookup. Every key the account page uses is
|
|
// named here and nowhere else, so `__tests__/i18n.test.ts` can run these builders against the
|
|
// catalogues and fail on a key either language lacks -- the page itself holds no string.
|
|
//
|
|
// `t` takes a key relative to the module (`export.heading`); the page binds it to
|
|
// `i18n.message("account." + key)`. The app's `app.failed` is passed in already looked up.
|
|
|
|
import { RECENT_SIGN_IN_SECONDS } from "../contract/constants.js"
|
|
import type { DeletionStatus } from "../contract/procedures.js"
|
|
import type { AccountAnalyticsLabels } from "./account-analytics.js"
|
|
import type { AccountDeletionLabels } from "./account-deletion.js"
|
|
import type { AccountExportLabels } from "./account-export.js"
|
|
|
|
export type Translate = (key: string, values?: Record<string, string | number>) => string
|
|
|
|
/** The sections this module has a name for; another module's key is shown as it is. */
|
|
const NAMED_SECTIONS = ["account", "guides", "support"] as const
|
|
|
|
export function sectionNames(t: Translate): Record<string, string> {
|
|
return Object.fromEntries(NAMED_SECTIONS.map((key) => [key, t(`sections.${key}`)]))
|
|
}
|
|
|
|
const named = (keys: readonly string[], names: Readonly<Record<string, string>>): string =>
|
|
keys.map((key) => names[key] ?? key).join(", ")
|
|
|
|
export function pageLabels(t: Translate) {
|
|
return {
|
|
title: t("title"),
|
|
intro: t("intro"),
|
|
link: t("link"),
|
|
profileHeading: t("profile.heading"),
|
|
name: t("profile.name"),
|
|
email: t("profile.email"),
|
|
}
|
|
}
|
|
|
|
export function exportLabels(t: Translate, failed: string): AccountExportLabels {
|
|
return {
|
|
heading: t("export.heading"),
|
|
body: t("export.body"),
|
|
submit: t("export.submit"),
|
|
busy: t("export.busy"),
|
|
done: t("export.done"),
|
|
partial: t("export.partial", { sections: "{sections}" }),
|
|
filename: t("export.filename"),
|
|
failed,
|
|
sectionNames: sectionNames(t),
|
|
}
|
|
}
|
|
|
|
export function deletionLabels(
|
|
t: Translate,
|
|
failed: string,
|
|
status: Pick<DeletionStatus, "modules" | "lastOwnerOf" | "onlyMemberOf">,
|
|
email: string,
|
|
): AccountDeletionLabels {
|
|
const names = sectionNames(t)
|
|
const organizations = (list: readonly { name: string }[]) => list.map((org) => org.name).join(", ")
|
|
return {
|
|
heading: t("deletion.heading"),
|
|
body: t("deletion.body"),
|
|
services: status.modules.length > 0 ? t("deletion.services", { modules: named(status.modules, names) }) : "",
|
|
...(status.lastOwnerOf.length > 0
|
|
? { lastOwner: t("deletion.lastOwner", { organizations: organizations(status.lastOwnerOf) }) }
|
|
: {}),
|
|
...(status.onlyMemberOf.length > 0
|
|
? { onlyMember: t("deletion.onlyMember", { organizations: organizations(status.onlyMemberOf) }) }
|
|
: {}),
|
|
reauth: t("deletion.reauth", { minutes: Math.round(RECENT_SIGN_IN_SECONDS / 60) }),
|
|
reauthLink: t("deletion.reauthLink"),
|
|
notInteractive: t("deletion.notInteractive"),
|
|
confirmLabel: t("deletion.confirmLabel"),
|
|
confirmHint: t("deletion.confirmHint", { email }),
|
|
submit: t("deletion.submit"),
|
|
busy: t("deletion.busy"),
|
|
completed: t("deletion.completed"),
|
|
erasing: t("deletion.erasing", { modules: "{modules}" }),
|
|
home: t("deletion.home"),
|
|
failed,
|
|
sectionNames: names,
|
|
}
|
|
}
|
|
|
|
/** The platform stores an analytics request reports on (ADR-049 §3). */
|
|
const ANALYTICS_STORES = ["session_replay", "errors", "proxy_logs", "traces", "logs", "analytics"] as const
|
|
const ANALYTICS_STATUSES = ["pending", "running", "completed", "failed", "expired"] as const
|
|
|
|
export function analyticsLabels(t: Translate, failed: string): AccountAnalyticsLabels {
|
|
return {
|
|
heading: t("analytics.heading"),
|
|
body: t("analytics.body"),
|
|
erase: t("analytics.erase"),
|
|
exportSubmit: t("analytics.exportSubmit"),
|
|
busy: t("analytics.busy"),
|
|
confirmErase: t("analytics.confirmErase"),
|
|
confirm: t("analytics.confirm"),
|
|
cancel: t("analytics.cancel"),
|
|
download: t("analytics.download"),
|
|
filename: t("analytics.filename"),
|
|
status: Object.fromEntries(
|
|
ANALYTICS_STATUSES.map((key) => [key, t(`analytics.status.${key}`)]),
|
|
) as AccountAnalyticsLabels["status"],
|
|
store: t("analytics.store"),
|
|
storeStatus: t("analytics.storeStatus"),
|
|
deleted: t("analytics.deleted"),
|
|
anonymized: t("analytics.anonymized"),
|
|
exported: t("analytics.exported"),
|
|
storeNames: Object.fromEntries(ANALYTICS_STORES.map((key) => [key, t(`analytics.stores.${key}`)])),
|
|
failed,
|
|
}
|
|
}
|