mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-06 00:15:32 +00:00
fix: show every attachment in the composer, with type icons and a total, failed and uploading files first
The attachment list test now expects every chip and a bounded, scrolling row instead of three chips and a +N counter.
This commit is contained in:
@@ -218,21 +218,20 @@ const DRAFT = {
|
||||
attachments: ATTACHMENTS,
|
||||
};
|
||||
|
||||
/** The wrapping flex row that holds every chip and the expand button. */
|
||||
/** The wrapping flex row that holds every chip. */
|
||||
function chipRow() {
|
||||
return screen.getByText('invoice-0.pdf').closest('[class*="flex-wrap"]') as HTMLElement;
|
||||
return screen.getByTestId('composer-attachments');
|
||||
}
|
||||
|
||||
/**
|
||||
* The attachment row is a shrink-0 sibling of the body's scroll container,
|
||||
* so whatever height it takes is taken from the composer and from nothing
|
||||
* else. Collapsed that is three chips. Expanded it is one row per two
|
||||
* attachments, and with a few dozen files it grew past the bottom of the
|
||||
* composer: the send toolbar was pushed off-screen and no ancestor
|
||||
* scrolled, so neither the rest of the list nor Send could be reached.
|
||||
* Expanding therefore has to bound the row and scroll it itself.
|
||||
* else. With a few dozen files it grew past the bottom of the composer: the
|
||||
* send toolbar was pushed off-screen and no ancestor scrolled. It used to
|
||||
* show three chips and "+N", which hid the fourth file's upload. Now every
|
||||
* chip shows, wrapping, and the row is bounded and scrolls itself.
|
||||
*/
|
||||
describe('expanded attachment list', () => {
|
||||
describe('attachment list', () => {
|
||||
beforeEach(() => {
|
||||
observers.length = 0;
|
||||
vi.stubGlobal('ResizeObserver', ResizeObserverStub);
|
||||
@@ -242,39 +241,27 @@ describe('expanded attachment list', () => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('does not scroll while collapsed', () => {
|
||||
it('shows every attachment, with no counter to expand', () => {
|
||||
render(<EmailComposer initialData={DRAFT} />);
|
||||
|
||||
expect(chipRow().className).not.toContain('overflow-y-auto');
|
||||
expect(screen.getByText('invoice-3.pdf')).toBeInTheDocument();
|
||||
expect(screen.getByText('invoice-11.pdf')).toBeInTheDocument();
|
||||
expect(screen.queryByText(`+${ATTACHMENTS.length - 3}`)).toBeNull();
|
||||
});
|
||||
|
||||
it('shows only the first three attachments and a counter for the rest', () => {
|
||||
it('caps its height and scrolls itself', () => {
|
||||
render(<EmailComposer initialData={DRAFT} />);
|
||||
|
||||
expect(screen.getByText('invoice-2.pdf')).toBeInTheDocument();
|
||||
expect(screen.queryByText('invoice-3.pdf')).not.toBeInTheDocument();
|
||||
expect(screen.getByText(`+${ATTACHMENTS.length - 3}`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('caps its height and scrolls once expanded', () => {
|
||||
render(<EmailComposer initialData={DRAFT} />);
|
||||
|
||||
fireEvent.click(screen.getByText(`+${ATTACHMENTS.length - 3}`));
|
||||
|
||||
const row = chipRow();
|
||||
expect(screen.getByText('invoice-11.pdf')).toBeInTheDocument();
|
||||
expect(row.className).toContain('overflow-y-auto');
|
||||
// Bounded, or the row grows with the attachment count again and takes
|
||||
// the send toolbar off the bottom of the composer with it.
|
||||
expect(row.className).toContain('max-h-[');
|
||||
});
|
||||
|
||||
it('stops scrolling again when collapsed back', () => {
|
||||
it('says how many files and how much they weigh', () => {
|
||||
render(<EmailComposer initialData={DRAFT} />);
|
||||
|
||||
fireEvent.click(screen.getByText(`+${ATTACHMENTS.length - 3}`));
|
||||
fireEvent.click(screen.getByText('show_less'));
|
||||
|
||||
expect(chipRow().className).not.toContain('overflow-y-auto');
|
||||
expect(screen.getByTestId('composer-attachments-summary')).toHaveTextContent('attachments_summary');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,6 +68,8 @@ import { isFilePreviewable } from "@/lib/file-preview";
|
||||
import { isEditableEventTarget } from "@/lib/keyboard";
|
||||
import { isSingleKeyShortcutOff } from "@/lib/single-key-shortcuts";
|
||||
import { markReplyQuoteHeader } from "@/components/email/reply-quote-collapse";
|
||||
import { attachmentIcon } from "@/components/email/attachment-chips";
|
||||
import { attachmentsForDisplay } from "@/lib/compose/attachment-order";
|
||||
import { showDraftSavedToast } from "@/lib/compose/draft-close-toast";
|
||||
import { buildQuotedHtmlBlock, serializeEditorContent } from "@/components/email/quoted-html";
|
||||
import { containsEmbeddedSignature } from "@/components/email/signature-block";
|
||||
@@ -1244,7 +1246,6 @@ export function EmailComposer({
|
||||
const [closeDialogKind, setCloseDialogKind] = useState<'close' | 'discard'>('close');
|
||||
// Closing saves without asking; the question comes only when that save failed.
|
||||
const [closeSaveFailed, setCloseSaveFailed] = useState(false);
|
||||
const [showAllAttachments, setShowAllAttachments] = useState(false);
|
||||
const [previewAttachment, setPreviewAttachment] = useState<ComposerAttachment | null>(null);
|
||||
// What the checks before sending found (no subject, no text, placeholders,
|
||||
// a missing attachment, open proofreading issues), asked about in one dialog.
|
||||
@@ -5538,21 +5539,24 @@ export function EmailComposer({
|
||||
{/* Attachments */}
|
||||
{attachments.length > 0 && (
|
||||
<div className="px-4 py-2 border-t shrink-0">
|
||||
{attachments.length > 1 && (
|
||||
<p className="mb-1.5 text-xs text-muted-foreground tabular-nums" data-testid="composer-attachments-summary">
|
||||
{tUx('attachments_summary', {
|
||||
count: attachments.length,
|
||||
size: formatFileSize(attachments.reduce((sum, att) => sum + (att.size || 0), 0)),
|
||||
})}
|
||||
</p>
|
||||
)}
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-wrap gap-2",
|
||||
// Collapsed this is three chips and a counter, so it stays
|
||||
// small. Expanded it is as tall as the attachment count
|
||||
// makes it, and it sits outside the body's scroll container
|
||||
// and cannot shrink - so a few dozen files grew it past the
|
||||
// composer, pushed the send toolbar off the bottom and left
|
||||
// nothing that scrolled: the list was stuck with its last
|
||||
// rows and the Send button both unreachable. Cap the
|
||||
// expanded list and give it a scroller of its own.
|
||||
showAllAttachments && "max-h-[30vh] overflow-y-auto overscroll-contain",
|
||||
)}
|
||||
// Every file shows, wrapping. Past about two rows the list
|
||||
// scrolls by itself: it sits outside the body's scroller and
|
||||
// can't shrink, and a few dozen files pushed Send off the
|
||||
// bottom. Files still uploading or failed come first, so their
|
||||
// progress and errors are never out of sight.
|
||||
className="flex flex-wrap gap-2 max-h-[5.25rem] overflow-y-auto overscroll-contain"
|
||||
data-testid="composer-attachments"
|
||||
>
|
||||
{(showAllAttachments ? attachments : attachments.slice(0, 3)).map((att, index) => {
|
||||
{attachmentsForDisplay(attachments).map(({ att, index }) => {
|
||||
// Clickable to preview only once it has content (local File or an
|
||||
// uploaded blob) and the type is previewable; never mid-upload.
|
||||
const canPreview = !att.uploading && !att.error
|
||||
@@ -5612,9 +5616,11 @@ export function EmailComposer({
|
||||
<Loader2 className="w-3 h-3 animate-spin flex-shrink-0" />
|
||||
) : att.error ? (
|
||||
<AlertCircle className="w-3 h-3 flex-shrink-0" />
|
||||
) : (
|
||||
<Paperclip className="w-3 h-3 flex-shrink-0" />
|
||||
)}
|
||||
) : (() => {
|
||||
// The file's type, as the reader shows it.
|
||||
const { icon: TypeIcon, className: typeIconClass } = attachmentIcon(att.type, att.name);
|
||||
return <TypeIcon className={cn("w-3.5 h-3.5 flex-shrink-0", typeIconClass)} aria-hidden />;
|
||||
})()}
|
||||
{canPreview ? (
|
||||
<button
|
||||
type="button"
|
||||
@@ -5661,14 +5667,6 @@ export function EmailComposer({
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{attachments.length > 3 && (
|
||||
<button
|
||||
onClick={() => setShowAllAttachments(prev => !prev)}
|
||||
className="flex items-center gap-1 px-3 py-1.5 rounded-md text-sm bg-muted text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
{showAllAttachments ? t('show_less') : `+${attachments.length - 3}`}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { attachmentsForDisplay } from '../attachment-order';
|
||||
|
||||
describe('the order of the composer attachment chips', () => {
|
||||
it('puts failed, then uploading files first, and keeps the rest in the order added', () => {
|
||||
const files = [
|
||||
{ name: 'a.pdf' },
|
||||
{ name: 'b.pdf', uploading: true },
|
||||
{ name: 'c.pdf' },
|
||||
{ name: 'big.zip', uploading: true },
|
||||
{ name: 'broken.png', error: 'failed' },
|
||||
];
|
||||
const shown = attachmentsForDisplay(files);
|
||||
expect(shown.map(({ att }) => att.name)).toEqual(['broken.png', 'b.pdf', 'big.zip', 'a.pdf', 'c.pdf']);
|
||||
// Each keeps its place in the composer's list, for Remove.
|
||||
expect(shown.map(({ index }) => index)).toEqual([4, 1, 3, 0, 2]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* The composer's attachment chips in the order they're shown: failed first,
|
||||
* then still uploading, then the rest, each group in the order added. The
|
||||
* list scrolls past about two rows, so the files that need an eye on them
|
||||
* are the ones always in view. `index` is the place in the composer's list.
|
||||
*/
|
||||
export function attachmentsForDisplay<T extends { error?: unknown; uploading?: boolean }>(
|
||||
attachments: readonly T[],
|
||||
): Array<{ att: T; index: number }> {
|
||||
const rank = (att: T) => (att.error ? 0 : att.uploading ? 1 : 2);
|
||||
return attachments
|
||||
.map((att, index) => ({ att, index }))
|
||||
.sort((a, b) => rank(a.att) - rank(b.att) || a.index - b.index);
|
||||
}
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "تجاهل المسودة",
|
||||
"save_failed_close": "تعذّر حفظ المسودة. حاول مرة أخرى أو تجاهلها.",
|
||||
"try_again": "حاول مرة أخرى",
|
||||
"add_description": "إضافة وصف"
|
||||
"add_description": "إضافة وصف",
|
||||
"attachments_summary": "المرفقات: {count}، {size}",
|
||||
"from_sub_address": "استخدام عنوان فرعي…",
|
||||
"from_edit_sender": "تعديل المرسل…",
|
||||
"shortcut_insert_link": "إدراج رابط",
|
||||
"shortcut_save_draft": "حفظ المسودة",
|
||||
"shortcut_show_cc": "إظهار نسخة",
|
||||
"shortcut_show_bcc": "إظهار نسخة مخفية"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "تأكيد",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Descarta l'esborrany",
|
||||
"save_failed_close": "No s'ha pogut desar l'esborrany. Torneu-ho a provar o descarteu-lo.",
|
||||
"try_again": "Torna-ho a provar",
|
||||
"add_description": "Afegeix una descripció"
|
||||
"add_description": "Afegeix una descripció",
|
||||
"attachments_summary": "Adjunts: {count}, {size}",
|
||||
"from_sub_address": "Fes servir una subadreça…",
|
||||
"from_edit_sender": "Edita el remitent…",
|
||||
"shortcut_insert_link": "Insereix un enllaç",
|
||||
"shortcut_save_draft": "Desa l'esborrany",
|
||||
"shortcut_show_cc": "Mostra Cc",
|
||||
"shortcut_show_bcc": "Mostra Cco"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Confirma",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Zahodit koncept",
|
||||
"save_failed_close": "Koncept se nepodařilo uložit. Zkuste to znovu, nebo ho zahoďte.",
|
||||
"try_again": "Zkusit znovu",
|
||||
"add_description": "Přidat popis"
|
||||
"add_description": "Přidat popis",
|
||||
"attachments_summary": "Přílohy: {count}, {size}",
|
||||
"from_sub_address": "Použít podadresu…",
|
||||
"from_edit_sender": "Upravit odesílatele…",
|
||||
"shortcut_insert_link": "Vložit odkaz",
|
||||
"shortcut_save_draft": "Uložit koncept",
|
||||
"shortcut_show_cc": "Zobrazit kopii",
|
||||
"shortcut_show_bcc": "Zobrazit skrytou kopii"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Potvrdit",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Kassér kladde",
|
||||
"save_failed_close": "Kladden kunne ikke gemmes. Prøv igen, eller kassér den.",
|
||||
"try_again": "Prøv igen",
|
||||
"add_description": "Tilføj beskrivelse"
|
||||
"add_description": "Tilføj beskrivelse",
|
||||
"attachments_summary": "Vedhæftede filer: {count}, {size}",
|
||||
"from_sub_address": "Brug en underadresse…",
|
||||
"from_edit_sender": "Rediger afsender…",
|
||||
"shortcut_insert_link": "Indsæt link",
|
||||
"shortcut_save_draft": "Gem kladde",
|
||||
"shortcut_show_cc": "Vis Cc",
|
||||
"shortcut_show_bcc": "Vis Bcc"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Bekræft",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Entwurf verwerfen",
|
||||
"save_failed_close": "Der Entwurf konnte nicht gespeichert werden. Versuchen Sie es erneut oder verwerfen Sie ihn.",
|
||||
"try_again": "Erneut versuchen",
|
||||
"add_description": "Beschreibung hinzufügen"
|
||||
"add_description": "Beschreibung hinzufügen",
|
||||
"attachments_summary": "Anhänge: {count}, {size}",
|
||||
"from_sub_address": "Unteradresse verwenden…",
|
||||
"from_edit_sender": "Absender bearbeiten…",
|
||||
"shortcut_insert_link": "Link einfügen",
|
||||
"shortcut_save_draft": "Entwurf speichern",
|
||||
"shortcut_show_cc": "Cc anzeigen",
|
||||
"shortcut_show_bcc": "Bcc anzeigen"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Bestätigen",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Discard draft",
|
||||
"save_failed_close": "The draft could not be saved. Try again, or discard it.",
|
||||
"try_again": "Try again",
|
||||
"add_description": "Add description"
|
||||
"add_description": "Add description",
|
||||
"attachments_summary": "Attachments: {count}, {size}",
|
||||
"from_sub_address": "Use a sub-address…",
|
||||
"from_edit_sender": "Edit sender…",
|
||||
"shortcut_insert_link": "Insert link",
|
||||
"shortcut_save_draft": "Save draft",
|
||||
"shortcut_show_cc": "Show Cc",
|
||||
"shortcut_show_bcc": "Show Bcc"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Confirm",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Descartar borrador",
|
||||
"save_failed_close": "No se pudo guardar el borrador. Inténtelo de nuevo o descártelo.",
|
||||
"try_again": "Reintentar",
|
||||
"add_description": "Añadir descripción"
|
||||
"add_description": "Añadir descripción",
|
||||
"attachments_summary": "Adjuntos: {count}, {size}",
|
||||
"from_sub_address": "Usar una subdirección…",
|
||||
"from_edit_sender": "Editar remitente…",
|
||||
"shortcut_insert_link": "Insertar enlace",
|
||||
"shortcut_save_draft": "Guardar borrador",
|
||||
"shortcut_show_cc": "Mostrar CC",
|
||||
"shortcut_show_bcc": "Mostrar CCO"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Confirmar",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Loobu mustandist",
|
||||
"save_failed_close": "Mustandit ei saanud salvestada. Proovige uuesti või loobuge sellest.",
|
||||
"try_again": "Proovi uuesti",
|
||||
"add_description": "Lisa kirjeldus"
|
||||
"add_description": "Lisa kirjeldus",
|
||||
"attachments_summary": "Manused: {count}, {size}",
|
||||
"from_sub_address": "Kasuta alamaadressi…",
|
||||
"from_edit_sender": "Muuda saatjat…",
|
||||
"shortcut_insert_link": "Lisa link",
|
||||
"shortcut_save_draft": "Salvesta mustand",
|
||||
"shortcut_show_cc": "Näita koopiat",
|
||||
"shortcut_show_bcc": "Näita pimekoopiat"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Kinnita",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "دور انداختن پیشنویس",
|
||||
"save_failed_close": "پیشنویس ذخیره نشد. دوباره تلاش کنید یا آن را دور بیندازید.",
|
||||
"try_again": "تلاش دوباره",
|
||||
"add_description": "افزودن توضیح"
|
||||
"add_description": "افزودن توضیح",
|
||||
"attachments_summary": "پیوستها: {count}، {size}",
|
||||
"from_sub_address": "استفاده از زیرنشانی…",
|
||||
"from_edit_sender": "ویرایش فرستنده…",
|
||||
"shortcut_insert_link": "درج پیوند",
|
||||
"shortcut_save_draft": "ذخیرهٔ پیشنویس",
|
||||
"shortcut_show_cc": "نمایش رونوشت",
|
||||
"shortcut_show_bcc": "نمایش رونوشت پنهان"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "تأیید",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Supprimer le brouillon",
|
||||
"save_failed_close": "Le brouillon n'a pas pu être enregistré. Réessayez ou supprimez-le.",
|
||||
"try_again": "Réessayer",
|
||||
"add_description": "Ajouter une description"
|
||||
"add_description": "Ajouter une description",
|
||||
"attachments_summary": "Pièces jointes : {count}, {size}",
|
||||
"from_sub_address": "Utiliser une sous-adresse…",
|
||||
"from_edit_sender": "Modifier l'expéditeur…",
|
||||
"shortcut_insert_link": "Insérer un lien",
|
||||
"shortcut_save_draft": "Enregistrer le brouillon",
|
||||
"shortcut_show_cc": "Afficher Cc",
|
||||
"shortcut_show_bcc": "Afficher Cci"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Confirmer",
|
||||
|
||||
@@ -1161,7 +1161,14 @@
|
||||
"discard_draft": "מחיקת הטיוטה",
|
||||
"save_failed_close": "לא ניתן היה לשמור את הטיוטה. נסו שוב או מחקו אותה.",
|
||||
"try_again": "ניסיון נוסף",
|
||||
"add_description": "הוספת תיאור"
|
||||
"add_description": "הוספת תיאור",
|
||||
"attachments_summary": "קבצים מצורפים: {count}, {size}",
|
||||
"from_sub_address": "שימוש בכתובת משנה…",
|
||||
"from_edit_sender": "עריכת השולח…",
|
||||
"shortcut_insert_link": "הוספת קישור",
|
||||
"shortcut_save_draft": "שמירת טיוטה",
|
||||
"shortcut_show_cc": "הצגת עותק",
|
||||
"shortcut_show_bcc": "הצגת עותק מוסתר"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "אשר",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Piszkozat elvetése",
|
||||
"save_failed_close": "A piszkozatot nem sikerült menteni. Próbálja újra, vagy vesse el.",
|
||||
"try_again": "Újra",
|
||||
"add_description": "Leírás hozzáadása"
|
||||
"add_description": "Leírás hozzáadása",
|
||||
"attachments_summary": "Mellékletek: {count}, {size}",
|
||||
"from_sub_address": "Alcím használata…",
|
||||
"from_edit_sender": "Feladó szerkesztése…",
|
||||
"shortcut_insert_link": "Hivatkozás beszúrása",
|
||||
"shortcut_save_draft": "Piszkozat mentése",
|
||||
"shortcut_show_cc": "Másolat megjelenítése",
|
||||
"shortcut_show_bcc": "Titkos másolat megjelenítése"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Megerősítés",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Elimina bozza",
|
||||
"save_failed_close": "Impossibile salvare la bozza. Riprova o eliminala.",
|
||||
"try_again": "Riprova",
|
||||
"add_description": "Aggiungi descrizione"
|
||||
"add_description": "Aggiungi descrizione",
|
||||
"attachments_summary": "Allegati: {count}, {size}",
|
||||
"from_sub_address": "Usa un sottoindirizzo…",
|
||||
"from_edit_sender": "Modifica mittente…",
|
||||
"shortcut_insert_link": "Inserisci link",
|
||||
"shortcut_save_draft": "Salva bozza",
|
||||
"shortcut_show_cc": "Mostra Cc",
|
||||
"shortcut_show_bcc": "Mostra Ccn"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Conferma",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "下書きを破棄",
|
||||
"save_failed_close": "下書きを保存できませんでした。もう一度試すか、破棄してください。",
|
||||
"try_again": "再試行",
|
||||
"add_description": "説明を追加"
|
||||
"add_description": "説明を追加",
|
||||
"attachments_summary": "添付ファイル: {count} 件、{size}",
|
||||
"from_sub_address": "サブアドレスを使用…",
|
||||
"from_edit_sender": "差出人を編集…",
|
||||
"shortcut_insert_link": "リンクを挿入",
|
||||
"shortcut_save_draft": "下書きを保存",
|
||||
"shortcut_show_cc": "Cc を表示",
|
||||
"shortcut_show_bcc": "Bcc を表示"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "確認",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "임시 보관 메일 삭제",
|
||||
"save_failed_close": "임시 보관 메일을 저장하지 못했습니다. 다시 시도하거나 삭제하세요.",
|
||||
"try_again": "다시 시도",
|
||||
"add_description": "설명 추가"
|
||||
"add_description": "설명 추가",
|
||||
"attachments_summary": "첨부 파일: {count}개, {size}",
|
||||
"from_sub_address": "하위 주소 사용…",
|
||||
"from_edit_sender": "보낸 사람 편집…",
|
||||
"shortcut_insert_link": "링크 삽입",
|
||||
"shortcut_save_draft": "임시 저장",
|
||||
"shortcut_show_cc": "참조 표시",
|
||||
"shortcut_show_bcc": "숨은 참조 표시"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "확인",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Atmest melnrakstu",
|
||||
"save_failed_close": "Melnrakstu neizdevās saglabāt. Mēģiniet vēlreiz vai atmetiet to.",
|
||||
"try_again": "Mēģināt vēlreiz",
|
||||
"add_description": "Pievienot aprakstu"
|
||||
"add_description": "Pievienot aprakstu",
|
||||
"attachments_summary": "Pielikumi: {count}, {size}",
|
||||
"from_sub_address": "Izmantot apakšadresi…",
|
||||
"from_edit_sender": "Rediģēt sūtītāju…",
|
||||
"shortcut_insert_link": "Ievietot saiti",
|
||||
"shortcut_save_draft": "Saglabāt melnrakstu",
|
||||
"shortcut_show_cc": "Rādīt kopiju",
|
||||
"shortcut_show_bcc": "Rādīt diskrēto kopiju"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Apstiprināt",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Ноорог устгах",
|
||||
"save_failed_close": "Ноорогийг хадгалж чадсангүй. Дахин оролдох эсвэл устгана уу.",
|
||||
"try_again": "Дахин оролдох",
|
||||
"add_description": "Тайлбар нэмэх"
|
||||
"add_description": "Тайлбар нэмэх",
|
||||
"attachments_summary": "Хавсралт: {count}, {size}",
|
||||
"from_sub_address": "Дэд хаяг ашиглах…",
|
||||
"from_edit_sender": "Илгээгчийг засах…",
|
||||
"shortcut_insert_link": "Холбоос оруулах",
|
||||
"shortcut_save_draft": "Ноорог хадгалах",
|
||||
"shortcut_show_cc": "Хуулбар харуулах",
|
||||
"shortcut_show_bcc": "Нууц хуулбар харуулах"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Баталгаажуулах",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Forkast utkast",
|
||||
"save_failed_close": "Utkastet kunne ikke lagres. Prøv igjen, eller forkast det.",
|
||||
"try_again": "Prøv igjen",
|
||||
"add_description": "Legg til beskrivelse"
|
||||
"add_description": "Legg til beskrivelse",
|
||||
"attachments_summary": "Vedlegg: {count}, {size}",
|
||||
"from_sub_address": "Bruk en underadresse…",
|
||||
"from_edit_sender": "Rediger avsender…",
|
||||
"shortcut_insert_link": "Sett inn lenke",
|
||||
"shortcut_save_draft": "Lagre utkast",
|
||||
"shortcut_show_cc": "Vis kopi",
|
||||
"shortcut_show_bcc": "Vis blindkopi"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Bekreft",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Concept verwijderen",
|
||||
"save_failed_close": "Het concept kon niet worden opgeslagen. Probeer het opnieuw of verwijder het.",
|
||||
"try_again": "Opnieuw proberen",
|
||||
"add_description": "Beschrijving toevoegen"
|
||||
"add_description": "Beschrijving toevoegen",
|
||||
"attachments_summary": "Bijlagen: {count}, {size}",
|
||||
"from_sub_address": "Subadres gebruiken…",
|
||||
"from_edit_sender": "Afzender bewerken…",
|
||||
"shortcut_insert_link": "Link invoegen",
|
||||
"shortcut_save_draft": "Concept opslaan",
|
||||
"shortcut_show_cc": "Cc tonen",
|
||||
"shortcut_show_bcc": "Bcc tonen"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Bevestigen",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Odrzuć wersję roboczą",
|
||||
"save_failed_close": "Nie udało się zapisać wersji roboczej. Spróbuj ponownie lub ją odrzuć.",
|
||||
"try_again": "Spróbuj ponownie",
|
||||
"add_description": "Dodaj opis"
|
||||
"add_description": "Dodaj opis",
|
||||
"attachments_summary": "Załączniki: {count}, {size}",
|
||||
"from_sub_address": "Użyj podadresu…",
|
||||
"from_edit_sender": "Edytuj nadawcę…",
|
||||
"shortcut_insert_link": "Wstaw link",
|
||||
"shortcut_save_draft": "Zapisz wersję roboczą",
|
||||
"shortcut_show_cc": "Pokaż DW",
|
||||
"shortcut_show_bcc": "Pokaż UDW"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Potwierdź",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Descartar rascunho",
|
||||
"save_failed_close": "Não foi possível guardar o rascunho. Tente novamente ou descarte-o.",
|
||||
"try_again": "Tentar novamente",
|
||||
"add_description": "Adicionar descrição"
|
||||
"add_description": "Adicionar descrição",
|
||||
"attachments_summary": "Anexos: {count}, {size}",
|
||||
"from_sub_address": "Usar um subendereço…",
|
||||
"from_edit_sender": "Editar remetente…",
|
||||
"shortcut_insert_link": "Inserir ligação",
|
||||
"shortcut_save_draft": "Guardar rascunho",
|
||||
"shortcut_show_cc": "Mostrar Cc",
|
||||
"shortcut_show_bcc": "Mostrar Bcc"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Confirmar",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Renunță la ciornă",
|
||||
"save_failed_close": "Ciorna nu a putut fi salvată. Încercați din nou sau renunțați la ea.",
|
||||
"try_again": "Încearcă din nou",
|
||||
"add_description": "Adaugă o descriere"
|
||||
"add_description": "Adaugă o descriere",
|
||||
"attachments_summary": "Atașamente: {count}, {size}",
|
||||
"from_sub_address": "Folosește o subadresă…",
|
||||
"from_edit_sender": "Editează expeditorul…",
|
||||
"shortcut_insert_link": "Inserează un link",
|
||||
"shortcut_save_draft": "Salvează ciorna",
|
||||
"shortcut_show_cc": "Afișează Cc",
|
||||
"shortcut_show_bcc": "Afișează Bcc"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Confirmare",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Удалить черновик",
|
||||
"save_failed_close": "Не удалось сохранить черновик. Попробуйте ещё раз или удалите его.",
|
||||
"try_again": "Повторить",
|
||||
"add_description": "Добавить описание"
|
||||
"add_description": "Добавить описание",
|
||||
"attachments_summary": "Вложения: {count}, {size}",
|
||||
"from_sub_address": "Использовать подадрес…",
|
||||
"from_edit_sender": "Изменить отправителя…",
|
||||
"shortcut_insert_link": "Вставить ссылку",
|
||||
"shortcut_save_draft": "Сохранить черновик",
|
||||
"shortcut_show_cc": "Показать копию",
|
||||
"shortcut_show_bcc": "Показать скрытую копию"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Подтвердить",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Zahodiť koncept",
|
||||
"save_failed_close": "Koncept sa nepodarilo uložiť. Skúste to znova alebo ho zahoďte.",
|
||||
"try_again": "Skúsiť znova",
|
||||
"add_description": "Pridať popis"
|
||||
"add_description": "Pridať popis",
|
||||
"attachments_summary": "Prílohy: {count}, {size}",
|
||||
"from_sub_address": "Použiť podadresu…",
|
||||
"from_edit_sender": "Upraviť odosielateľa…",
|
||||
"shortcut_insert_link": "Vložiť odkaz",
|
||||
"shortcut_save_draft": "Uložiť koncept",
|
||||
"shortcut_show_cc": "Zobraziť kópiu",
|
||||
"shortcut_show_bcc": "Zobraziť skrytú kópiu"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Potvrdiť",
|
||||
|
||||
@@ -1566,7 +1566,14 @@
|
||||
"discard_draft": "ทิ้งฉบับร่าง",
|
||||
"save_failed_close": "บันทึกฉบับร่างไม่ได้ ลองอีกครั้งหรือทิ้งไป",
|
||||
"try_again": "ลองอีกครั้ง",
|
||||
"add_description": "เพิ่มคำอธิบาย"
|
||||
"add_description": "เพิ่มคำอธิบาย",
|
||||
"attachments_summary": "ไฟล์แนบ: {count} ไฟล์, {size}",
|
||||
"from_sub_address": "ใช้ที่อยู่ย่อย…",
|
||||
"from_edit_sender": "แก้ไขผู้ส่ง…",
|
||||
"shortcut_insert_link": "แทรกลิงก์",
|
||||
"shortcut_save_draft": "บันทึกฉบับร่าง",
|
||||
"shortcut_show_cc": "แสดงสำเนา",
|
||||
"shortcut_show_bcc": "แสดงสำเนาลับ"
|
||||
},
|
||||
"email_viewer": {
|
||||
"read_receipt": {
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Taslağı sil",
|
||||
"save_failed_close": "Taslak kaydedilemedi. Yeniden deneyin ya da silin.",
|
||||
"try_again": "Yeniden dene",
|
||||
"add_description": "Açıklama ekle"
|
||||
"add_description": "Açıklama ekle",
|
||||
"attachments_summary": "Ekler: {count}, {size}",
|
||||
"from_sub_address": "Alt adres kullan…",
|
||||
"from_edit_sender": "Göndereni düzenle…",
|
||||
"shortcut_insert_link": "Bağlantı ekle",
|
||||
"shortcut_save_draft": "Taslağı kaydet",
|
||||
"shortcut_show_cc": "Bilgiyi göster",
|
||||
"shortcut_show_bcc": "Gizli bilgiyi göster"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Onayla",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "Видалити чернетку",
|
||||
"save_failed_close": "Не вдалося зберегти чернетку. Спробуйте ще раз або видаліть її.",
|
||||
"try_again": "Спробувати ще раз",
|
||||
"add_description": "Додати опис"
|
||||
"add_description": "Додати опис",
|
||||
"attachments_summary": "Вкладення: {count}, {size}",
|
||||
"from_sub_address": "Використати підадресу…",
|
||||
"from_edit_sender": "Змінити відправника…",
|
||||
"shortcut_insert_link": "Вставити посилання",
|
||||
"shortcut_save_draft": "Зберегти чернетку",
|
||||
"shortcut_show_cc": "Показати копію",
|
||||
"shortcut_show_bcc": "Показати приховану копію"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Підтвердити",
|
||||
|
||||
@@ -1230,7 +1230,14 @@
|
||||
"discard_draft": "Hủy bản nháp",
|
||||
"save_failed_close": "Không lưu được bản nháp. Hãy thử lại hoặc hủy bản nháp.",
|
||||
"try_again": "Thử lại",
|
||||
"add_description": "Thêm mô tả"
|
||||
"add_description": "Thêm mô tả",
|
||||
"attachments_summary": "Tệp đính kèm: {count}, {size}",
|
||||
"from_sub_address": "Dùng địa chỉ phụ…",
|
||||
"from_edit_sender": "Sửa người gửi…",
|
||||
"shortcut_insert_link": "Chèn liên kết",
|
||||
"shortcut_save_draft": "Lưu bản nháp",
|
||||
"shortcut_show_cc": "Hiện Cc",
|
||||
"shortcut_show_bcc": "Hiện Bcc"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "Xác nhận",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "捨棄草稿",
|
||||
"save_failed_close": "無法儲存草稿。請再試一次或捨棄草稿。",
|
||||
"try_again": "再試一次",
|
||||
"add_description": "新增描述"
|
||||
"add_description": "新增描述",
|
||||
"attachments_summary": "附件:{count} 個,{size}",
|
||||
"from_sub_address": "使用子地址…",
|
||||
"from_edit_sender": "編輯寄件者…",
|
||||
"shortcut_insert_link": "插入連結",
|
||||
"shortcut_save_draft": "儲存草稿",
|
||||
"shortcut_show_cc": "顯示副本",
|
||||
"shortcut_show_bcc": "顯示密件副本"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "確認",
|
||||
|
||||
@@ -1218,7 +1218,14 @@
|
||||
"discard_draft": "舍弃草稿",
|
||||
"save_failed_close": "无法保存草稿。请重试或舍弃草稿。",
|
||||
"try_again": "重试",
|
||||
"add_description": "添加描述"
|
||||
"add_description": "添加描述",
|
||||
"attachments_summary": "附件:{count} 个,{size}",
|
||||
"from_sub_address": "使用子地址…",
|
||||
"from_edit_sender": "编辑发件人…",
|
||||
"shortcut_insert_link": "插入链接",
|
||||
"shortcut_save_draft": "保存草稿",
|
||||
"shortcut_show_cc": "显示抄送",
|
||||
"shortcut_show_bcc": "显示密送"
|
||||
},
|
||||
"confirm_dialog": {
|
||||
"confirm": "确认",
|
||||
|
||||
Reference in New Issue
Block a user