From 48df0db1af5f682097a69b477c88576fdffb1a9c Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Wed, 4 Nov 2026 07:34:29 +0100 Subject: [PATCH] feat: list To and Cc in the header of a forwarded message --- .../composer-reply-signature.test.tsx | 36 +++++++++++++++++ components/email/email-composer.tsx | 10 +++-- lib/__tests__/quote-header.test.ts | 32 +++++++++++++++ lib/quote-header.ts | 40 ++++++++++++++++++- locales/ar/common.json | 4 +- locales/ca/common.json | 4 +- locales/cs/common.json | 4 +- locales/da/common.json | 4 +- locales/de/common.json | 4 +- locales/en/common.json | 4 +- locales/es/common.json | 4 +- locales/et/common.json | 4 +- locales/fa/common.json | 4 +- locales/fr/common.json | 4 +- locales/he/common.json | 4 +- locales/hu/common.json | 4 +- locales/it/common.json | 4 +- locales/ja/common.json | 4 +- locales/ko/common.json | 4 +- locales/lv/common.json | 4 +- locales/mn/common.json | 4 +- locales/nb/common.json | 4 +- locales/nl/common.json | 4 +- locales/pl/common.json | 4 +- locales/pt/common.json | 4 +- locales/ro/common.json | 4 +- locales/ru/common.json | 4 +- locales/sk/common.json | 4 +- locales/th/common.json | 4 +- locales/tr/common.json | 4 +- locales/uk/common.json | 4 +- locales/vi/common.json | 4 +- locales/zh-TW/common.json | 4 +- locales/zh/common.json | 4 +- 34 files changed, 203 insertions(+), 35 deletions(-) diff --git a/components/email/__tests__/composer-reply-signature.test.tsx b/components/email/__tests__/composer-reply-signature.test.tsx index 2198cec74..7cfc8a9d6 100644 --- a/components/email/__tests__/composer-reply-signature.test.tsx +++ b/components/email/__tests__/composer-reply-signature.test.tsx @@ -379,3 +379,39 @@ describe('reply quote attribution markers', () => { expect(html).toContain('

From: Bob

'); }); }); + +// The forwarded header had From, Date and Subject only; Gmail and Outlook +// also say who the mail went to. +describe('forwarded header recipients', () => { + afterEach(() => { + useSettingsStore.setState({ plainTextMode: false, signaturePosition: 'below_quote' }); + setIdentities([ME]); + }); + const FORWARDED = { + ...REPLY_TO, + to: [{ name: 'Anna Becker', email: 'anna@example.com' }, { email: 'team@example.com' }], + cc: [{ name: 'Carol', email: 'carol@example.com' }], + }; + + it('lists To and Cc in a plain text forward', async () => { + useSettingsStore.setState({ plainTextMode: true }); + const onSend = vi.fn(); + render(); + const sent = await send(onSend); + expect(sent.body).toContain('subject_label: Question\nforward_to_label: Anna Becker , team@example.com\nforward_cc_label: Carol \n\nOriginal text'); + }); + + // escapeHtml is mocked to pass values through in this file. + it('lists To and Cc in an HTML forward', () => { + render(); + const html = screen.getByTestId('rich-text-editor').getAttribute('data-html')!; + expect(html).toContain('subject_label: Question
forward_to_label: Anna Becker , team@example.com
forward_cc_label: Carol

'); + }); + + it('leaves out a Cc line when nobody was copied', () => { + render(); + const html = screen.getByTestId('rich-text-editor').getAttribute('data-html')!; + expect(html).toContain('forward_to_label: '); + expect(html).not.toContain('forward_cc_label'); + }); +}); diff --git a/components/email/email-composer.tsx b/components/email/email-composer.tsx index 3b0003861..6c8e8935e 100644 --- a/components/email/email-composer.tsx +++ b/components/email/email-composer.tsx @@ -53,6 +53,7 @@ import { plainOwnRange, readOwnContent, readSelection as readEditorSelection, re import { actionsFor, runAction } from "@/lib/plugin-sandbox/actions"; import { matchesCombo } from "@/lib/plugin-sandbox/shortcuts"; import { cn, formatFileSize, formatDateTime, generateUUID } from "@/lib/utils"; +import { forwardRecipientLines } from "@/lib/quote-header"; import { ScheduleSendDialog } from "./schedule-send-dialog"; import { debug } from "@/lib/debug"; import { toast } from "@/stores/toast-store"; @@ -839,6 +840,7 @@ export function EmailComposer({ ? `${from.name} <${from.email}>` : (from.email || from.name || tCommon('unknown'))) : tCommon('unknown'); + const forwardLines = forwardRecipientLines(replyTo, { toLabel: tWords('forward_to_label'), ccLabel: tWords('forward_cc_label') }); const originalText = replyTo.body || (replyTo.htmlBody ? htmlToPlainText(replyTo.htmlBody) : ''); const quotedText = originalText.split('\n').map(line => `> ${line}`).join('\n'); @@ -859,7 +861,7 @@ export function EmailComposer({ } if (mode === 'forward') { - return `${prefix}${signatureBlock}\n\n${tQuote('forwarded_separator')}\n${tQuote('from_label')}: ${fromStrFull}\n${tQuote('date_label')}: ${date}\n${tQuote('subject_label')}: ${replyTo.subject || ''}\n\n${originalText}`; + return `${prefix}${signatureBlock}\n\n${tQuote('forwarded_separator')}\n${tQuote('from_label')}: ${fromStrFull}\n${tQuote('date_label')}: ${date}\n${tQuote('subject_label')}: ${replyTo.subject || ''}${forwardLines.map((line) => `\n${line.label}: ${line.value}`).join('')}\n\n${originalText}`; } else if (mode === 'reply' || mode === 'replyAll') { return `${prefix}${signatureBlock}\n\n${tQuote('reply_line', { date, from: fromStrFull })}\n${quotedText}`; } @@ -889,6 +891,8 @@ export function EmailComposer({ ? `${from.name} <${from.email}>` : (from.email || from.name || tCommon('unknown'))) : tCommon('unknown'); + const forwardLinesHtml = forwardRecipientLines(replyTo, { toLabel: tWords('forward_to_label'), ccLabel: tWords('forward_cc_label') }) + .map((line) => `${line.label}: ${escapeHtml(line.value)}
`).join(''); // Like a new mail, an empty line above the signature gives the cursor a // place for the reply. Without it the reply started on the "-- " line (#1503). @@ -937,7 +941,7 @@ export function EmailComposer({ // HTML-escape user-controlled values: an unescaped sender "Name " // has its "" eaten as a bogus HTML tag by the rich-text editor (#482). const quoteHeader = mode === 'forward' - ? `${tQuote('forwarded_separator')}
${tQuote('from_label')}: ${escapeHtml(fromStrFull)}
${tQuote('date_label')}: ${escapeHtml(date)}
${tQuote('subject_label')}: ${escapeHtml(replyTo.subject || '')}

` + ? `${tQuote('forwarded_separator')}
${tQuote('from_label')}: ${escapeHtml(fromStrFull)}
${tQuote('date_label')}: ${escapeHtml(date)}
${tQuote('subject_label')}: ${escapeHtml(replyTo.subject || '')}
${forwardLinesHtml}
` : `${tQuote('reply_line', { date: escapeHtml(date), from: escapeHtml(fromStrFull) })}
`; // Embed the original as a QuotedHtml island (verbatim, schema-free) so // its layout survives the editor round-trip. Sanitize first to strip @@ -953,7 +957,7 @@ export function EmailComposer({ if (replyTo.body) { const escapedOriginal = replyTo.body.replace(/&/g, '&').replace(//g, '>').replace(/\n/g, '
'); if (mode === 'forward') { - return `${head}

${tQuote('forwarded_separator')}
${tQuote('from_label')}: ${escapeHtml(fromStrFull)}
${tQuote('date_label')}: ${escapeHtml(date)}
${tQuote('subject_label')}: ${escapeHtml(replyTo.subject || '')}

${escapedOriginal}`; + return `${head}

${tQuote('forwarded_separator')}
${tQuote('from_label')}: ${escapeHtml(fromStrFull)}
${tQuote('date_label')}: ${escapeHtml(date)}
${tQuote('subject_label')}: ${escapeHtml(replyTo.subject || '')}
${forwardLinesHtml}
${escapedOriginal}`; } else if (mode === 'reply' || mode === 'replyAll') { return `${head}

${replyHeader(`

${tQuote('reply_line', { date: escapeHtml(date), from: escapeHtml(fromStrFull) })}

`)}
${escapedOriginal}
`; } diff --git a/lib/__tests__/quote-header.test.ts b/lib/__tests__/quote-header.test.ts index 5493f646d..dced402e6 100644 --- a/lib/__tests__/quote-header.test.ts +++ b/lib/__tests__/quote-header.test.ts @@ -90,3 +90,35 @@ describe('buildQuoteHeader (#482 — sender address survives HTML rendering)', ( expect(h.text).not.toContain(''); }); }); + +// Gmail and Outlook list who the forwarded mail went to. +describe('buildQuoteHeader forward recipients', () => { + const email = { + from: [sender], + to: [{ name: 'Anna Becker', email: 'anna@example.com' }, { email: 'team@example.com' }], + cc: [{ name: 'Carol ', email: 'carol@example.com' }], + subject: 'Hello', + receivedAt: '2026-01-01T10:00:00Z', + }; + + it('adds To and Cc lines after the subject', async () => { + const h = await buildQuoteHeader({ mode: 'forward', email, ...base }); + expect(h.text).toContain('Subject: Hello\nTo: Anna Becker , team@example.com\nCc: Carol \n'); + expect(h.html).toContain('To: Anna Becker <anna@example.com>, team@example.com
Cc: Carol <x> <carol@example.com>
'); + }); + + it('uses the caller\'s To and Cc labels', async () => { + const labels = { + formatReplyLine: () => '', forwardedSeparator: '--', fromLabel: 'Von', dateLabel: 'Datum', subjectLabel: 'Betreff', + toLabel: 'An', ccLabel: 'Kopie', + }; + const h = await buildQuoteHeader({ mode: 'forward', email, labels, ...base }); + expect(h.text).toContain('\nAn: Anna Becker , team@example.com\nKopie: Carol \n'); + }); + + it('leaves out a line for an empty list', async () => { + const h = await buildQuoteHeader({ mode: 'forward', email: { ...email, cc: [] }, ...base }); + expect(h.text).toContain('\nTo: '); + expect(h.text).not.toContain('Cc:'); + }); +}); diff --git a/lib/quote-header.ts b/lib/quote-header.ts index 686df5e13..92c56c9c1 100644 --- a/lib/quote-header.ts +++ b/lib/quote-header.ts @@ -20,6 +20,36 @@ export interface QuoteHeaderLabels { fromLabel: string; dateLabel: string; subjectLabel: string; + /** The forward header's To and Cc lines; left out when not given. */ + toLabel?: string; + ccLabel?: string; +} + +type HeaderAddress = { email?: string; name?: string }; + +/** "Name
, address", as the forward header's From line writes one. */ +function formatAddressList(list: HeaderAddress[] | undefined): string { + return (list ?? []) + .filter((r) => r.email) + .map((r) => (r.name && r.name !== r.email ? `${r.name} <${r.email}>` : r.email as string)) + .join(", "); +} + +/** + * The To and Cc lines of a forward header, as Gmail and Outlook write them: + * one per list that has anyone on it, for a label the caller gave. Values + * are plain text; escape them for HTML. + */ +export function forwardRecipientLines( + email: { to?: HeaderAddress[]; cc?: HeaderAddress[] }, + labels: { toLabel?: string; ccLabel?: string }, +): { label: string; value: string }[] { + const lines: { label: string; value: string }[] = []; + const to = formatAddressList(email.to); + const cc = formatAddressList(email.cc); + if (labels.toLabel && to) lines.push({ label: labels.toLabel, value: to }); + if (labels.ccLabel && cc) lines.push({ label: labels.ccLabel, value: cc }); + return lines; } interface BuildArgs { @@ -49,6 +79,8 @@ const DEFAULT_LABELS: QuoteHeaderLabels = { fromLabel: "From", dateLabel: "Date", subjectLabel: "Subject", + toLabel: "To", + ccLabel: "Cc", }; function defaultHeader(args: BuildArgs): QuoteHeader { @@ -73,12 +105,16 @@ function defaultHeader(args: BuildArgs): QuoteHeader { const subject = email.subject || ""; if (mode === "forward") { - const text = `${labels.forwardedSeparator}\n${labels.fromLabel}: ${fromStrFull}\n${labels.dateLabel}: ${date}\n${labels.subjectLabel}: ${subject}\n`; + const recipients = forwardRecipientLines(email, labels); + const text = `${labels.forwardedSeparator}\n${labels.fromLabel}: ${fromStrFull}\n${labels.dateLabel}: ${date}\n${labels.subjectLabel}: ${subject}\n` + + recipients.map((line) => `${line.label}: ${line.value}\n`).join(""); // Escape the interpolated values for the HTML variant: the sender string is // "Name ", and the unescaped "" would be parsed as an HTML tag // by the rich-text composer and silently dropped (#482). Subject/name are // likewise user-controlled. Label/separator strings are trusted i18n text. - const html = `
${labels.forwardedSeparator}
${labels.fromLabel}: ${escapeHtml(fromStrFull)}
${labels.dateLabel}: ${escapeHtml(date)}
${labels.subjectLabel}: ${escapeHtml(subject)}

`; + const html = `
${labels.forwardedSeparator}
${labels.fromLabel}: ${escapeHtml(fromStrFull)}
${labels.dateLabel}: ${escapeHtml(date)}
${labels.subjectLabel}: ${escapeHtml(subject)}
` + + recipients.map((line) => `${line.label}: ${escapeHtml(line.value)}
`).join("") + + `
`; return { html, text, wrapInBlockquote: false }; } diff --git a/locales/ar/common.json b/locales/ar/common.json index 08b672c45..12b2d73d1 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -6398,7 +6398,9 @@ "encrypt": "تشفير…", "encrypt_hint": "يتطلب إضافة S/MIME أو PGP. يفتح الإعدادات.", "quick_reply_to": "الرد على {names}…", - "open_full_editor": "فتح المحرر الكامل" + "open_full_editor": "فتح المحرر الكامل", + "forward_to_label": "إلى", + "forward_cc_label": "نسخة" }, "plugin_list": { "filters": "المرشحات", diff --git a/locales/ca/common.json b/locales/ca/common.json index 79db8efdb..8611a20d0 100644 --- a/locales/ca/common.json +++ b/locales/ca/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Xifra…", "encrypt_hint": "Cal un complement S/MIME o PGP. Obre la configuració.", "quick_reply_to": "Respon a {names}…", - "open_full_editor": "Obre l'editor complet" + "open_full_editor": "Obre l'editor complet", + "forward_to_label": "Per a", + "forward_cc_label": "CC" }, "plugin_list": { "filters": "Filtres", diff --git a/locales/cs/common.json b/locales/cs/common.json index 8bb772b79..c104a4ae4 100644 --- a/locales/cs/common.json +++ b/locales/cs/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Šifrovat…", "encrypt_hint": "Vyžaduje doplněk S/MIME nebo PGP. Otevře Nastavení.", "quick_reply_to": "Odpověď pro {names}…", - "open_full_editor": "Otevřít v plném editoru" + "open_full_editor": "Otevřít v plném editoru", + "forward_to_label": "Komu", + "forward_cc_label": "Kopie" }, "plugin_list": { "filters": "Filtry", diff --git a/locales/da/common.json b/locales/da/common.json index a21a64b6a..8f3646620 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Krypter…", "encrypt_hint": "Kræver en S/MIME- eller PGP-tilføjelse. Åbner Indstillinger.", "quick_reply_to": "Svar til {names}…", - "open_full_editor": "Åbn fuld editor" + "open_full_editor": "Åbn fuld editor", + "forward_to_label": "Til", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filtre", diff --git a/locales/de/common.json b/locales/de/common.json index 118e73984..f071eda62 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Verschlüsseln…", "encrypt_hint": "Dafür brauchen Sie eine S/MIME- oder PGP-Erweiterung. Öffnet die Einstellungen.", "quick_reply_to": "Antwort an {names}…", - "open_full_editor": "Im vollen Editor öffnen" + "open_full_editor": "Im vollen Editor öffnen", + "forward_to_label": "An", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filter", diff --git a/locales/en/common.json b/locales/en/common.json index 5c156b566..ab1f2707c 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Encrypt…", "encrypt_hint": "Needs an S/MIME or PGP add-on. Opens Settings.", "quick_reply_to": "Reply to {names}…", - "open_full_editor": "Open full editor" + "open_full_editor": "Open full editor", + "forward_to_label": "To", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filters", diff --git a/locales/es/common.json b/locales/es/common.json index e2c5abe2c..2aadeb752 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Cifrar…", "encrypt_hint": "Necesita un complemento S/MIME o PGP. Abre la Configuración.", "quick_reply_to": "Responder a {names}…", - "open_full_editor": "Abrir el editor completo" + "open_full_editor": "Abrir el editor completo", + "forward_to_label": "Para", + "forward_cc_label": "CC" }, "plugin_list": { "filters": "Filtros", diff --git a/locales/et/common.json b/locales/et/common.json index 7c10b5be3..7ad6a8e04 100644 --- a/locales/et/common.json +++ b/locales/et/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Krüpteeri…", "encrypt_hint": "Vajab S/MIME või PGP lisa. Avab seaded.", "quick_reply_to": "Vastus saajale {names}…", - "open_full_editor": "Ava täielik redaktor" + "open_full_editor": "Ava täielik redaktor", + "forward_to_label": "Saajale", + "forward_cc_label": "Koopia" }, "plugin_list": { "filters": "Filtrid", diff --git a/locales/fa/common.json b/locales/fa/common.json index 6245bfe57..1d2dd6c1e 100644 --- a/locales/fa/common.json +++ b/locales/fa/common.json @@ -6398,7 +6398,9 @@ "encrypt": "رمزگذاری…", "encrypt_hint": "به افزونهٔ S/MIME یا PGP نیاز دارد. تنظیمات را باز می‌کند.", "quick_reply_to": "پاسخ به {names}…", - "open_full_editor": "باز کردن ویرایشگر کامل" + "open_full_editor": "باز کردن ویرایشگر کامل", + "forward_to_label": "به", + "forward_cc_label": "رونوشت" }, "plugin_list": { "filters": "فیلترها", diff --git a/locales/fr/common.json b/locales/fr/common.json index d1f479d10..6b4d1c3e4 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Chiffrer…", "encrypt_hint": "Nécessite une extension S/MIME ou PGP. Ouvre les Paramètres.", "quick_reply_to": "Répondre à {names}…", - "open_full_editor": "Ouvrir l'éditeur complet" + "open_full_editor": "Ouvrir l'éditeur complet", + "forward_to_label": "À", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filtres", diff --git a/locales/he/common.json b/locales/he/common.json index d71e21f53..7e1679e6b 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -6399,7 +6399,9 @@ "encrypt": "הצפנה…", "encrypt_hint": "דורש תוסף S/MIME או PGP. פותח את ההגדרות.", "quick_reply_to": "תשובה אל {names}…", - "open_full_editor": "פתיחה בעורך המלא" + "open_full_editor": "פתיחה בעורך המלא", + "forward_to_label": "אל", + "forward_cc_label": "עותק" }, "plugin_list": { "filters": "מסננים", diff --git a/locales/hu/common.json b/locales/hu/common.json index a1224176a..5dce2bb87 100644 --- a/locales/hu/common.json +++ b/locales/hu/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Titkosítás…", "encrypt_hint": "S/MIME vagy PGP bővítmény kell hozzá. Megnyitja a Beállításokat.", "quick_reply_to": "Válasz neki: {names}…", - "open_full_editor": "Megnyitás a teljes szerkesztőben" + "open_full_editor": "Megnyitás a teljes szerkesztőben", + "forward_to_label": "Címzett", + "forward_cc_label": "Másolat" }, "plugin_list": { "filters": "Szűrők", diff --git a/locales/it/common.json b/locales/it/common.json index cbe010633..f7f210938 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Cifra…", "encrypt_hint": "Serve un componente aggiuntivo S/MIME o PGP. Apre le Impostazioni.", "quick_reply_to": "Rispondi a {names}…", - "open_full_editor": "Apri l'editor completo" + "open_full_editor": "Apri l'editor completo", + "forward_to_label": "A", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filtri", diff --git a/locales/ja/common.json b/locales/ja/common.json index 14d4a3fc7..838d04b89 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -6398,7 +6398,9 @@ "encrypt": "暗号化…", "encrypt_hint": "S/MIME または PGP のアドオンが必要です。設定を開きます。", "quick_reply_to": "{names} に返信…", - "open_full_editor": "フルエディターで開く" + "open_full_editor": "フルエディターで開く", + "forward_to_label": "宛先", + "forward_cc_label": "CC" }, "plugin_list": { "filters": "フィルター", diff --git a/locales/ko/common.json b/locales/ko/common.json index dd10f83c1..95c50a7dd 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -6398,7 +6398,9 @@ "encrypt": "암호화…", "encrypt_hint": "S/MIME 또는 PGP 추가 기능이 필요합니다. 설정을 엽니다.", "quick_reply_to": "{names}에게 답장…", - "open_full_editor": "전체 편집기에서 열기" + "open_full_editor": "전체 편집기에서 열기", + "forward_to_label": "받는 사람", + "forward_cc_label": "참조" }, "plugin_list": { "filters": "필터", diff --git a/locales/lv/common.json b/locales/lv/common.json index f42e200e7..a0c3ec9e4 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Šifrēt…", "encrypt_hint": "Nepieciešams S/MIME vai PGP papildinājums. Atver iestatījumus.", "quick_reply_to": "Atbilde: {names}…", - "open_full_editor": "Atvērt pilnajā redaktorā" + "open_full_editor": "Atvērt pilnajā redaktorā", + "forward_to_label": "Kam", + "forward_cc_label": "Kopija" }, "plugin_list": { "filters": "Filtri", diff --git a/locales/mn/common.json b/locales/mn/common.json index 00f75758f..dde99c21d 100644 --- a/locales/mn/common.json +++ b/locales/mn/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Шифрлэх…", "encrypt_hint": "S/MIME эсвэл PGP нэмэлт хэрэгтэй. Тохиргоог нээнэ.", "quick_reply_to": "{names} руу хариу бичих…", - "open_full_editor": "Бүтэн засварлагчид нээх" + "open_full_editor": "Бүтэн засварлагчид нээх", + "forward_to_label": "Хэнд", + "forward_cc_label": "Хуулбар" }, "plugin_list": { "filters": "Шүүлтүүр", diff --git a/locales/nb/common.json b/locales/nb/common.json index c3ad75ca1..49816a157 100644 --- a/locales/nb/common.json +++ b/locales/nb/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Krypter…", "encrypt_hint": "Krever et S/MIME- eller PGP-tillegg. Åpner Innstillinger.", "quick_reply_to": "Svar til {names}…", - "open_full_editor": "Åpne i full redigering" + "open_full_editor": "Åpne i full redigering", + "forward_to_label": "Til", + "forward_cc_label": "Kopi" }, "plugin_list": { "filters": "Filtre", diff --git a/locales/nl/common.json b/locales/nl/common.json index e2cb76904..cf9d351d3 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Versleutelen…", "encrypt_hint": "Vereist een S/MIME- of PGP-add-on. Opent Instellingen.", "quick_reply_to": "Antwoord aan {names}…", - "open_full_editor": "Openen in volledige editor" + "open_full_editor": "Openen in volledige editor", + "forward_to_label": "Aan", + "forward_cc_label": "CC" }, "plugin_list": { "filters": "Filters", diff --git a/locales/pl/common.json b/locales/pl/common.json index d59272edd..367b75fe9 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Zaszyfruj…", "encrypt_hint": "Wymaga dodatku S/MIME lub PGP. Otwiera Ustawienia.", "quick_reply_to": "Odpowiedź do: {names}…", - "open_full_editor": "Otwórz w pełnym edytorze" + "open_full_editor": "Otwórz w pełnym edytorze", + "forward_to_label": "Do", + "forward_cc_label": "DW" }, "plugin_list": { "filters": "Filtry", diff --git a/locales/pt/common.json b/locales/pt/common.json index b1ea6d35a..92082c690 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Cifrar…", "encrypt_hint": "Precisa de um extra S/MIME ou PGP. Abre as Configurações.", "quick_reply_to": "Responder a {names}…", - "open_full_editor": "Abrir no editor completo" + "open_full_editor": "Abrir no editor completo", + "forward_to_label": "Para", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filtros", diff --git a/locales/ro/common.json b/locales/ro/common.json index f810811fa..ea2e68370 100644 --- a/locales/ro/common.json +++ b/locales/ro/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Criptează…", "encrypt_hint": "Necesită un supliment S/MIME sau PGP. Deschide Setările.", "quick_reply_to": "Răspuns către {names}…", - "open_full_editor": "Deschide în editorul complet" + "open_full_editor": "Deschide în editorul complet", + "forward_to_label": "Către", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filtre", diff --git a/locales/ru/common.json b/locales/ru/common.json index 74a021762..e7d197426 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Зашифровать…", "encrypt_hint": "Нужно дополнение S/MIME или PGP. Открывает настройки.", "quick_reply_to": "Ответ для {names}…", - "open_full_editor": "Открыть в полном редакторе" + "open_full_editor": "Открыть в полном редакторе", + "forward_to_label": "Кому", + "forward_cc_label": "Копия" }, "plugin_list": { "filters": "Фильтры", diff --git a/locales/sk/common.json b/locales/sk/common.json index c491884a9..f3b956c6f 100644 --- a/locales/sk/common.json +++ b/locales/sk/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Šifrovať…", "encrypt_hint": "Vyžaduje doplnok S/MIME alebo PGP. Otvorí Nastavenia.", "quick_reply_to": "Odpoveď pre {names}…", - "open_full_editor": "Otvoriť v plnom editore" + "open_full_editor": "Otvoriť v plnom editore", + "forward_to_label": "Komu", + "forward_cc_label": "Kópia" }, "plugin_list": { "filters": "Filtre", diff --git a/locales/th/common.json b/locales/th/common.json index f079d2742..3ba1fb2b9 100644 --- a/locales/th/common.json +++ b/locales/th/common.json @@ -3319,7 +3319,9 @@ "encrypt": "เข้ารหัส…", "encrypt_hint": "ต้องใช้ส่วนเสริม S/MIME หรือ PGP จะเปิดการตั้งค่า", "quick_reply_to": "ตอบกลับถึง {names}…", - "open_full_editor": "เปิดในตัวแก้ไขเต็มรูปแบบ" + "open_full_editor": "เปิดในตัวแก้ไขเต็มรูปแบบ", + "forward_to_label": "ถึง", + "forward_cc_label": "สำเนา" }, "plugin_list": { "filters": "ตัวกรอง", diff --git a/locales/tr/common.json b/locales/tr/common.json index 8c060f63d..5daf2a82e 100644 --- a/locales/tr/common.json +++ b/locales/tr/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Şifrele…", "encrypt_hint": "S/MIME veya PGP eklentisi gerekir. Ayarlar'ı açar.", "quick_reply_to": "Yanıtla: {names}…", - "open_full_editor": "Tam düzenleyicide aç" + "open_full_editor": "Tam düzenleyicide aç", + "forward_to_label": "Kime", + "forward_cc_label": "Cc" }, "plugin_list": { "filters": "Filtreler", diff --git a/locales/uk/common.json b/locales/uk/common.json index b0d78303e..2fd4c08ca 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -6398,7 +6398,9 @@ "encrypt": "Зашифрувати…", "encrypt_hint": "Потрібен додаток S/MIME або PGP. Відкриває налаштування.", "quick_reply_to": "Відповідь для {names}…", - "open_full_editor": "Відкрити в повному редакторі" + "open_full_editor": "Відкрити в повному редакторі", + "forward_to_label": "Кому", + "forward_cc_label": "Копія" }, "plugin_list": { "filters": "Фільтри", diff --git a/locales/vi/common.json b/locales/vi/common.json index 6c864887b..6a689656f 100644 --- a/locales/vi/common.json +++ b/locales/vi/common.json @@ -6410,7 +6410,9 @@ "encrypt": "Mã hóa…", "encrypt_hint": "Cần tiện ích S/MIME hoặc PGP. Mở Cài đặt.", "quick_reply_to": "Trả lời {names}…", - "open_full_editor": "Mở trong trình soạn thảo đầy đủ" + "open_full_editor": "Mở trong trình soạn thảo đầy đủ", + "forward_to_label": "Đến", + "forward_cc_label": "CC" }, "plugin_list": { "filters": "Bộ lọc", diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json index 3ba374dd0..856c877dc 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -6398,7 +6398,9 @@ "encrypt": "加密…", "encrypt_hint": "需要 S/MIME 或 PGP 附加元件。將開啟設定。", "quick_reply_to": "回覆給 {names}…", - "open_full_editor": "在完整編輯器中開啟" + "open_full_editor": "在完整編輯器中開啟", + "forward_to_label": "收件者", + "forward_cc_label": "副本" }, "plugin_list": { "filters": "篩選", diff --git a/locales/zh/common.json b/locales/zh/common.json index 4138f943a..48add2912 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -6398,7 +6398,9 @@ "encrypt": "加密…", "encrypt_hint": "需要 S/MIME 或 PGP 附加组件。将打开设置。", "quick_reply_to": "回复 {names}…", - "open_full_editor": "在完整编辑器中打开" + "open_full_editor": "在完整编辑器中打开", + "forward_to_label": "收件人", + "forward_cc_label": "抄送" }, "plugin_list": { "filters": "筛选",