import type { DownloadJob, DownloadJobKind } from "./api"; // The i18n keys that explain a failed download, most specific first — the list form `t()` takes, so // the first key a locale has wins. A failure-catalog entry (`error_detail`, e.g. `facebook.login_wall`) // names what went wrong on that site and what to do; the category (`error_code`) is the generic // sentence, and the fallback when an older client meets a detail it has no copy for; a category it has // no copy for falls back to the unknown one, so the row never prints a key. A job that is not a // download (an upload's conversion, a clip) may word a category its own way, ahead of the shared // sentence — "this download was stopped" is not what happened to it — and its own unknown sentence // comes before the download's. One helper for the queue row's headline and the failure window, so // the two can never explain the same job differently. export function failCopyKeys( job: Pick, part: "short" | "body", ): string[] { // A clip from YouTube or Plex is worded as the editor's clip: both are "making the clip". const kind = job.job_kind === "clip" ? "edit" : (job.job_kind ?? "download"); const category = (code: string) => [ ...(kind === "download" ? [] : [`downloads.errors.fail.${kind}.${code}.${part}`]), `downloads.errors.fail.cat.${code}.${part}`, ]; const code = job.error_code || "unknown"; return [ ...(job.error_detail ? [`downloads.errors.fail.catalog.${job.error_detail}.${part}`] : []), ...category(code), ...(code === "unknown" ? [] : category("unknown")), ]; } const TITLE_KEYS: Record = { download: "downloads.errors.fail.title", upload: "downloads.errors.fail.titleUpload", // its failure is a conversion, not a download edit: "downloads.errors.fail.titleEdit", // a clip being cut clip: "downloads.errors.fail.titleEdit", // a clip being cut, from YouTube or Plex }; /** The title over a failed job's explanation, worded for what the job was making. */ export function failTitleKey(job: Pick): string { return TITLE_KEYS[job.job_kind ?? "download"]; }