Fix: localize reply/forward quote header incl. sender address
The reply/forward quote header was always emitted in English ("On {date},
{from} wrote:", "---------- Forwarded message ----------", From/Date/Subject)
regardless of UI language, in both the main path (lib/quote-header.ts) and the
composer's inline fallback. quote-header.ts now takes an optional localized
QuoteHeaderLabels set (English defaults preserved for back-compat); page.tsx
builds it from a new quote_header message namespace, and the composer fallback
uses the same keys. Added the quote_header namespace to all 17 locales.
Also folds in the forward-sender-address fix: the forward "From:" line now
shows the full "Name <email>" like every mail client (the reply line keeps the
bare name, which reads naturally in "On … wrote:").
This commit is contained in:
+38
-4
@@ -10,6 +10,17 @@ import { formatDateTime } from "@/lib/utils";
|
||||
import { emailHooks } from "@/lib/plugin-hooks";
|
||||
import type { QuoteHeader, QuoteHeaderContext } from "@/lib/plugin-types";
|
||||
|
||||
// Localized label set the caller passes in. Labels live on the client where
|
||||
// useTranslations is available; this module stays framework-agnostic.
|
||||
export interface QuoteHeaderLabels {
|
||||
/** ICU-formatted reply line, e.g. "On {date}, {from} wrote:" with placeholders already substituted. */
|
||||
formatReplyLine: (vars: { date: string; from: string }) => string;
|
||||
forwardedSeparator: string;
|
||||
fromLabel: string;
|
||||
dateLabel: string;
|
||||
subjectLabel: string;
|
||||
}
|
||||
|
||||
interface BuildArgs {
|
||||
mode: "reply" | "replyAll" | "forward";
|
||||
email: {
|
||||
@@ -24,10 +35,24 @@ interface BuildArgs {
|
||||
locale: string;
|
||||
timeFormat: "12h" | "24h";
|
||||
unknownLabel: string;
|
||||
/**
|
||||
* Localized labels. Optional for backward compatibility; falls back to
|
||||
* English (matching the original hardcoded behaviour) when not supplied.
|
||||
*/
|
||||
labels?: QuoteHeaderLabels;
|
||||
}
|
||||
|
||||
const DEFAULT_LABELS: QuoteHeaderLabels = {
|
||||
formatReplyLine: ({ date, from }) => `On ${date}, ${from} wrote:`,
|
||||
forwardedSeparator: "---------- Forwarded message ----------",
|
||||
fromLabel: "From",
|
||||
dateLabel: "Date",
|
||||
subjectLabel: "Subject",
|
||||
};
|
||||
|
||||
function defaultHeader(args: BuildArgs): QuoteHeader {
|
||||
const { mode, email, timeFormat, unknownLabel } = args;
|
||||
const labels = args.labels ?? DEFAULT_LABELS;
|
||||
const date = email.receivedAt
|
||||
? formatDateTime(email.receivedAt, timeFormat, {
|
||||
weekday: "short",
|
||||
@@ -38,16 +63,25 @@ function defaultHeader(args: BuildArgs): QuoteHeader {
|
||||
: "";
|
||||
const from = email.from?.[0];
|
||||
const fromStr = from ? `${from.name || from.email}` : unknownLabel;
|
||||
// Forward header "From:" shows the full sender incl. address ("Name
|
||||
// <email>"), like every mail client. The reply line keeps the bare name
|
||||
// (reads more naturally in "On … wrote:").
|
||||
const fromStrFull = from
|
||||
? (from.name && from.email && from.name !== from.email
|
||||
? `${from.name} <${from.email}>`
|
||||
: (from.email || from.name || unknownLabel))
|
||||
: unknownLabel;
|
||||
const subject = email.subject || "";
|
||||
|
||||
if (mode === "forward") {
|
||||
const text = `---------- Forwarded message ----------\nFrom: ${fromStr}\nDate: ${date}\nSubject: ${subject}\n`;
|
||||
const html = `<div>---------- Forwarded message ----------<br>From: ${fromStr}<br>Date: ${date}<br>Subject: ${subject}<br><br></div>`;
|
||||
const text = `${labels.forwardedSeparator}\n${labels.fromLabel}: ${fromStrFull}\n${labels.dateLabel}: ${date}\n${labels.subjectLabel}: ${subject}\n`;
|
||||
const html = `<div>${labels.forwardedSeparator}<br>${labels.fromLabel}: ${fromStrFull}<br>${labels.dateLabel}: ${date}<br>${labels.subjectLabel}: ${subject}<br><br></div>`;
|
||||
return { html, text, wrapInBlockquote: false };
|
||||
}
|
||||
|
||||
const text = `On ${date}, ${fromStr} wrote:\n`;
|
||||
const html = `<div>On ${date}, ${fromStr} wrote:<br></div>`;
|
||||
const replyLine = labels.formatReplyLine({ date, from: fromStr });
|
||||
const text = `${replyLine}\n`;
|
||||
const html = `<div>${replyLine}<br></div>`;
|
||||
return { html, text, wrapInBlockquote: true };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user