From ec67ab994b34d8b7764c021d4c859d40747708fb Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Mon, 21 Sep 2026 20:52:02 +0200 Subject: [PATCH] feat: add missing mail action toasts and show sonner toasts again --- components/email/email-list.tsx | 57 +++++++++------ components/mail/mail-app.tsx | 93 ++++++++++++++---------- components/settings/keyword-settings.tsx | 7 +- lib/email-action-toast.ts | 27 +++++++ 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/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/tr/common.json | 4 + locales/uk/common.json | 4 + locales/zh-TW/common.json | 4 + locales/zh/common.json | 4 + 31 files changed, 225 insertions(+), 67 deletions(-) create mode 100644 lib/email-action-toast.ts diff --git a/components/email/email-list.tsx b/components/email/email-list.tsx index 77775c44c..8c22957cf 100644 --- a/components/email/email-list.tsx +++ b/components/email/email-list.tsx @@ -9,7 +9,7 @@ import { Trash2, Mail, MailX, MailOpen, Loader2, SearchX, AlertTriangle, Calenda import { useState, useEffect, useRef, useCallback, useMemo } from "react"; import { Button } from "@/components/ui/button"; import { ConfirmDialog } from "@/components/ui/confirm-dialog"; -import { useEmailStore } from "@/stores/email-store"; +import { useEmailStore, ArchiveMailboxNotFoundError } from "@/stores/email-store"; import { useAuthStore } from "@/stores/auth-store"; import { useSettingsStore } from "@/stores/settings-store"; import { useUIStore } from "@/stores/ui-store"; @@ -17,6 +17,8 @@ import { groupEmailsByThread, sortThreadGroups } from "@/lib/thread-utils"; import { useContextMenu } from "@/hooks/use-context-menu"; import { useConfirmDialog } from "@/hooks/use-confirm-dialog"; import { useTranslations } from "next-intl"; +import { toast } from "@/stores/toast-store"; +import { runBatchEmailAction } from "@/lib/email-action-toast"; import { useVirtualizer } from "@tanstack/react-virtual"; import { TagDisplayContext, useMeasuredTagDisplay } from "@/hooks/use-tag-display"; import { SearchChips } from "@/components/search/search-chips"; @@ -86,6 +88,8 @@ export function EmailList({ const t = useTranslations('email_list'); const tContextMenu = useTranslations('context_menu'); const tSpam = useTranslations('email_viewer.spam'); + const tNotifications = useTranslations('notifications'); + const tViewer = useTranslations('email_viewer'); const { client } = useAuthStore(); const { selectedEmailIds, @@ -245,10 +249,8 @@ export function EmailList({ try { const emailIds = Array.from(selectedEmailIds); await batchUndoSpam(client, emailIds); - const { toast } = await import('sonner'); toast.success(tSpam('toast_not_spam_batch', { count: emailIds.length })); } catch { - const { toast } = await import('sonner'); toast.error(tSpam('error_not_spam')); } finally { setTimeout(() => setIsProcessing(false), 500); @@ -276,16 +278,12 @@ export function EmailList({ if (!confirmed) return; setIsProcessing(true); + const count = selectedEmailIds.size; try { - await batchDelete(client, isInTrash); - const storeError = useEmailStore.getState().error; - if (storeError) { - const { toast } = await import('sonner'); - toast.error(storeError); - } - } catch (err) { - const { toast } = await import('sonner'); - toast.error(err instanceof Error ? err.message : 'Failed to delete emails'); + await runBatchEmailAction(() => batchDelete(client, isInTrash), { + success: tNotifications('emails_deleted', { count }), + error: tNotifications('error_deleting'), + }); } finally { setTimeout(() => setIsProcessing(false), 500); } @@ -648,27 +646,42 @@ export function EmailList({ onCancelScheduledForEdit={onCancelScheduledForEdit ? () => onCancelScheduledForEdit(contextMenuEmail!) : undefined} onRescheduleScheduled={onRescheduleScheduled ? () => onRescheduleScheduled(contextMenuEmail!) : undefined} onBatchMarkAsRead={(read) => client && batchMarkAsRead(client, read)} - onBatchDelete={() => client && batchDelete(client)} + onBatchDelete={async () => { + if (!client) return; + const count = selectedEmailIds.size; + await runBatchEmailAction(() => batchDelete(client), { + success: tNotifications('emails_deleted', { count }), + error: tNotifications('error_deleting'), + }); + }} onBatchArchive={async () => { if (!client) return; - try { - await batchArchive(client); - } catch (error) { - console.error('Failed to batch archive:', error); - } + const count = selectedEmailIds.size; + await runBatchEmailAction(() => batchArchive(client), { + success: tNotifications('emails_archived', { count }), + error: tNotifications('error_archiving'), + describeError: (error) => error instanceof ArchiveMailboxNotFoundError + ? tViewer('archive_mailbox_not_found') + : undefined, + }); + }} + onBatchMoveToMailbox={async (mailboxId) => { + if (!client) return; + const count = selectedEmailIds.size; + await runBatchEmailAction(() => batchMoveToMailbox(client, mailboxId), { + success: tNotifications('emails_moved', { count }), + error: tNotifications('move_failed'), + }); }} - onBatchMoveToMailbox={(mailboxId) => client && batchMoveToMailbox(client, mailboxId)} onBatchMarkAsSpam={async () => { if (client) { const emailIds = Array.from(selectedEmailIds); try { await batchMarkAsSpam(client, emailIds); - const { toast } = await import('sonner'); toast.success( tSpam('toast_batch', { count: emailIds.length }) ); } catch { - const { toast } = await import('sonner'); toast.error(tSpam('error')); } } @@ -678,12 +691,10 @@ export function EmailList({ const emailIds = Array.from(selectedEmailIds); try { await batchUndoSpam(client, emailIds); - const { toast } = await import('sonner'); toast.success( tSpam('toast_not_spam_batch', { count: emailIds.length }) ); } catch { - const { toast } = await import('sonner'); toast.error(tSpam('error_not_spam')); } } diff --git a/components/mail/mail-app.tsx b/components/mail/mail-app.tsx index 3ac27b5da..6f87fe242 100644 --- a/components/mail/mail-app.tsx +++ b/components/mail/mail-app.tsx @@ -33,6 +33,7 @@ import { connectedAccountsGrew } from "@/lib/unified-mailbox"; import { KeyboardShortcutsModal } from "@/components/keyboard-shortcuts-modal"; import { useEmailStore, buildUnifiedAccountClients, ArchiveMailboxNotFoundError, findArchiveMailbox, resolveUnstampedEmailAccountId } from "@/stores/email-store"; import { toast } from "@/stores/toast-store"; +import { runBatchEmailAction } from "@/lib/email-action-toast"; import { MailboxShareDialog } from "@/components/layout/mailbox-share-dialog"; import { ShareNotificationToaster } from "@/components/layout/share-notification-toaster"; import { CalendarEventNotificationToaster } from "@/components/layout/calendar-event-notification-toaster"; @@ -51,7 +52,7 @@ import { usePromptDialog } from "@/hooks/use-prompt-dialog"; import { useBrowserNavigation, type NavSnapshot } from "@/hooks/use-browser-navigation"; import { debug } from "@/lib/debug"; import { playNotificationSound } from "@/lib/notification-sound"; -import { cn } from "@/lib/utils"; +import { cn, getMailboxPath } from "@/lib/utils"; import { localizeMailboxName } from "@/lib/mailbox-label"; import { KEYWORD_PREFIX, KEYWORD_PREFIX_LEGACY, groupEmailsByThread } from "@/lib/thread-utils"; import { resolveThreadRoute } from "@/lib/thread-routing"; @@ -704,15 +705,14 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { onArchive: async () => { if (isScheduledView) return; if (selectedEmailIds.size > 0 && client) { - try { - await batchArchive(client); - } catch (error) { - console.error("Failed to batch archive:", error); - if (error instanceof ArchiveMailboxNotFoundError) { - const { toast } = await import('sonner'); - toast.error(t('email_viewer.archive_mailbox_not_found')); - } - } + const count = selectedEmailIds.size; + await runBatchEmailAction(() => batchArchive(client), { + success: t('notifications.emails_archived', { count }), + error: t('notifications.error_archiving'), + describeError: (error) => error instanceof ArchiveMailboxNotFoundError + ? t('email_viewer.archive_mailbox_not_found') + : undefined, + }); } else if (selectedEmail) { handleArchive(); } @@ -738,11 +738,11 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { variant: "destructive", }); if (!confirmed) return; - try { - await batchDelete(client, permanent); - } catch (error) { - console.error("Failed to batch delete:", error); - } + const count = selectedEmailIds.size; + await runBatchEmailAction(() => batchDelete(client, permanent), { + success: t('notifications.emails_deleted', { count }), + error: t('notifications.error_deleting'), + }); } else if (selectedEmail) { handleDelete(); } @@ -778,11 +778,14 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { try { if (isInJunk) { await batchUndoSpam(client, ids); + toast.success(t('email_viewer.spam.toast_not_spam_batch', { count: ids.length })); } else { await batchMarkAsSpam(client, ids); + toast.success(t('email_viewer.spam.toast_batch', { count: ids.length })); } } catch (error) { console.error("Failed to batch toggle spam:", error); + toast.error(t(isInJunk ? 'email_viewer.spam.error_not_spam' : 'email_viewer.spam.error')); } } else if (selectedEmail) { if (isInJunk) { @@ -1713,8 +1716,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { // removing the old draft) was rejected - warn instead of staying // silent, so a stale draft row is not mistaken for a failed send // and re-sent (#592). - const toastInstance = (await import('sonner')).toast; - toastInstance.warning(t('email_composer.send_filing_warning')); + toast.warning(t('email_composer.send_filing_warning')); } // Mark the original email with $answered or $forwarded keyword. Route the // write to the email's own account so the flag lands on shared/group-mailbox @@ -2178,8 +2180,10 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { try { await deleteEmail(client, emailToDelete.id, true); + toast.success(t('notifications.email_deleted')); } catch (error) { console.error("Failed to permanently delete email:", error); + toast.error(t('notifications.error_deleting'), error instanceof Error ? error.message : undefined); } } else { // Not in trash: always move to trash (in the email's own account). Scope @@ -2199,13 +2203,12 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { if (trashMailbox) { try { await moveToMailbox(client, emailToDelete.id, trashMailbox.id); + toast.success(t('notifications.email_deleted')); } catch (error) { console.error("Failed to move email to trash:", error); - const { toast } = await import('sonner'); toast.error(error instanceof Error ? error.message : 'Failed to move email to trash'); } } else { - const { toast } = await import('sonner'); toast.error('Trash mailbox not found - cannot move email to trash'); } } @@ -2243,7 +2246,6 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { // the selected shared folder's owner, otherwise the user's own archive. (#889) const archiveMailbox = findArchiveMailbox(currentMailboxes, selectedMailbox, archiveAccountId); if (!archiveMailbox) { - const { toast } = await import('sonner'); toast.error(t('email_viewer.archive_mailbox_not_found')); return; } @@ -2288,11 +2290,30 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { setConversationEmails([]); } + toast.success(t('notifications.email_archived')); void refreshMailboxes(); } catch (error) { console.error("Failed to archive email:", error); - const { toast } = await import('sonner'); - toast.error(error instanceof Error ? error.message : 'Failed to archive email'); + toast.error(t('notifications.error_archiving'), error instanceof Error ? error.message : undefined); + } + }; + + const handleMoveToMailbox = async (emailId: string, mailboxId: string) => { + if (!client) return; + const destinationList = [mailboxes, ...Object.values(accountMailboxes)] + .find(list => list.some(m => m.id === mailboxId)); + const destination = destinationList?.find(m => m.id === mailboxId); + try { + await moveToMailboxCrossAware(client, emailId, mailboxId); + toast.success( + t('notifications.email_moved'), + destination && destinationList + ? t('notifications.moved_to_mailbox', { mailbox: getMailboxPath(destination, destinationList) }) + : undefined, + ); + } catch (error) { + console.error("Failed to move email:", error); + toast.error(t('notifications.move_failed'), t('notifications.move_error')); } }; @@ -2303,6 +2324,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { await toggleStar(client, selectedEmail.id); } catch (error) { console.error("Failed to toggle star:", error); + toast.error(t('notifications.error_updating')); } }; @@ -2314,17 +2336,16 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { try { await markAsSpam(client, emailId); - const toastInstance = (await import('sonner')).toast; - toastInstance.success(t('email_viewer.spam.toast_success'), { + toast.success(t('email_viewer.spam.toast_success'), { action: { label: t('email_viewer.spam.toast_undo'), onClick: async () => { try { await undoSpam(client, emailId); - toastInstance.success(t('notifications.email_moved')); + toast.success(t('notifications.email_moved')); } catch (_error) { console.error("Failed to undo spam:", _error); - toastInstance.error(t('email_viewer.spam.error')); + toast.error(t('email_viewer.spam.error')); } }, }, @@ -2332,8 +2353,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { }); } catch (_error) { console.error("Failed to mark as spam:", _error); - const toastInstance = (await import('sonner')).toast; - toastInstance.error(t('email_viewer.spam.error')); + toast.error(t('email_viewer.spam.error')); } }; @@ -2343,12 +2363,10 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { try { await undoSpam(client, emailToRestore.id); - const toastInstance = (await import('sonner')).toast; - toastInstance.success(t('email_viewer.spam.toast_not_spam_success')); + toast.success(t('email_viewer.spam.toast_not_spam_success')); } catch (_error) { console.error("Failed to restore email:", _error); - const toastInstance = (await import('sonner')).toast; - toastInstance.error(t('email_viewer.spam.error_not_spam')); + toast.error(t('email_viewer.spam.error_not_spam')); } }; @@ -2379,6 +2397,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { } } catch (error) { console.error("Failed to toggle pin:", error); + toast.error(t('notifications.error_updating')); } }; @@ -4066,11 +4085,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { onSetTag={(emailId, color) => { handleSetTag(emailId, color); }} - onMoveToMailbox={async (emailId, mailboxId) => { - if (client) { - await moveToMailboxCrossAware(client, emailId, mailboxId); - } - }} + onMoveToMailbox={handleMoveToMailbox} onMarkAsSpam={async (email) => { await handleMarkAsSpam(email); }} @@ -4345,9 +4360,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { mailboxes={mailboxes} selectedMailbox={selectedMailbox} onMoveToMailbox={async (mailboxId) => { - if (client && selectedEmail) { - await moveToMailboxCrossAware(client, selectedEmail.id, mailboxId); - } + if (selectedEmail) await handleMoveToMailbox(selectedEmail.id, mailboxId); }} className={isMobile ? "flex-1" : undefined} /> diff --git a/components/settings/keyword-settings.tsx b/components/settings/keyword-settings.tsx index 21661c339..bb69473ea 100644 --- a/components/settings/keyword-settings.tsx +++ b/components/settings/keyword-settings.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from "react"; import { useTranslations } from "next-intl"; +import { toast } from "@/stores/toast-store"; import { useSettingsStore, KEYWORD_PALETTE, @@ -580,13 +581,11 @@ export function KeywordSettings() { if (migration.refused > 0) { // Some mail kept the old keyword. The definition still follows the // messages that did move; the rest is what the warning is about. - const toastModule = await import('sonner'); - toastModule.toast.warning(t("migration_error")); + toast.warning(t("migration_error")); } } catch (error) { console.error("Failed to migrate keyword:", error); - const toastModule = await import('sonner'); - toastModule.toast.error(t("migration_error")); + toast.error(t("migration_error")); setIsMigrating(false); return; } diff --git a/lib/email-action-toast.ts b/lib/email-action-toast.ts new file mode 100644 index 000000000..a160dbff3 --- /dev/null +++ b/lib/email-action-toast.ts @@ -0,0 +1,27 @@ +import { toast } from "@/stores/toast-store"; +import { useEmailStore } from "@/stores/email-store"; + +/** + * Runs a bulk email-store action and toasts the outcome. Most batch actions + * report failure through `state.error` instead of throwing (batchArchive does + * both), so a resolved promise alone does not mean the mail moved. + */ +export async function runBatchEmailAction( + run: () => Promise, + messages: { success: string; error: string; describeError?: (error: unknown) => string | undefined }, +): Promise { + try { + await run(); + } catch (error) { + console.error(messages.error, error); + const detail = messages.describeError?.(error) ?? (error instanceof Error ? error.message : undefined); + toast.error(messages.error, detail); + return; + } + const storeError = useEmailStore.getState().error; + if (storeError) { + toast.error(messages.error, storeError); + } else { + toast.success(messages.success); + } +} diff --git a/locales/ar/common.json b/locales/ar/common.json index 53d4bf6d8..1d9bf34c5 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -778,6 +778,10 @@ "email_sent": "تم إرسال الرسالة بنجاح", "email_deleted": "تم حذف الرسالة", "email_archived": "تمت أرشفة الرسالة", + "emails_deleted": "{count, plural, one {تم حذف رسالة واحدة} other {تم حذف # رسائل}}", + "emails_archived": "{count, plural, one {تمت أرشفة رسالة واحدة} other {تمت أرشفة # رسائل}}", + "error_archiving": "فشل أرشفة الرسالة", + "error_updating": "فشل تحديث الرسالة", "email_starred": "تم تمييز الرسالة بنجمة", "email_unstarred": "تمت إزالة النجمة عن الرسالة", "email_marked_read": "تم تمييز الرسالة كمقروءة", diff --git a/locales/ca/common.json b/locales/ca/common.json index 686039db0..8ebc48e91 100644 --- a/locales/ca/common.json +++ b/locales/ca/common.json @@ -778,6 +778,10 @@ "email_sent": "Correu enviat correctament", "email_deleted": "Correu suprimit", "email_archived": "Correu arxivat", + "emails_deleted": "{count, plural, one {# correu suprimit} other {# correus suprimits}}", + "emails_archived": "{count, plural, one {# correu arxivat} other {# correus arxivats}}", + "error_archiving": "No s'ha pogut arxivar el correu", + "error_updating": "No s'ha pogut actualitzar el correu", "email_starred": "Correu destacat", "email_unstarred": "S'ha tret l'estrella del correu", "email_marked_read": "Correu marcat com a llegit", diff --git a/locales/cs/common.json b/locales/cs/common.json index 5262ee69d..a66b097e3 100644 --- a/locales/cs/common.json +++ b/locales/cs/common.json @@ -778,6 +778,10 @@ "email_sent": "Zpráva byla úspěšně odeslána", "email_deleted": "Zpráva byla odstraněna", "email_archived": "Zpráva byla archivována", + "emails_deleted": "{count, plural, one {# e-mail smazán} few {# e-maily smazány} other {# e-mailů smazáno}}", + "emails_archived": "{count, plural, one {# e-mail archivován} few {# e-maily archivovány} other {# e-mailů archivováno}}", + "error_archiving": "E-mail se nepodařilo archivovat", + "error_updating": "E-mail se nepodařilo aktualizovat", "email_starred": "Zpráva byla označena hvězdičkou", "email_unstarred": "Hvězdička byla odebrána", "email_marked_read": "Zpráva byla označena jako přečtená", diff --git a/locales/da/common.json b/locales/da/common.json index 09552435b..1c64ae51d 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -778,6 +778,10 @@ "email_sent": "E-mail sendt succesfuldt", "email_deleted": "E-mail slettet", "email_archived": "E-mail arkiveret", + "emails_deleted": "{count, plural, one {# e-mail slettet} other {# e-mails slettet}}", + "emails_archived": "{count, plural, one {# e-mail arkiveret} other {# e-mails arkiveret}}", + "error_archiving": "Kunne ikke arkivere e-mail", + "error_updating": "Kunne ikke opdatere e-mail", "email_starred": "E-mail stjernemarkeret", "email_unstarred": "Stjernemarkering fjernet", "email_marked_read": "E-mail markeret som læst", diff --git a/locales/de/common.json b/locales/de/common.json index 2d39bfc03..21fdccf8d 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -778,6 +778,10 @@ "email_sent": "E-Mail erfolgreich gesendet", "email_deleted": "E-Mail gelöscht", "email_archived": "E-Mail archiviert", + "emails_deleted": "{count, plural, one {# E-Mail gelöscht} other {# E-Mails gelöscht}}", + "emails_archived": "{count, plural, one {# E-Mail archiviert} other {# E-Mails archiviert}}", + "error_archiving": "E-Mail konnte nicht archiviert werden", + "error_updating": "E-Mail konnte nicht aktualisiert werden", "email_starred": "Stern hinzugefügt", "email_unstarred": "Stern entfernt", "email_marked_read": "E-Mail als gelesen markiert", diff --git a/locales/en/common.json b/locales/en/common.json index 78a509e09..eea711cbd 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -778,6 +778,10 @@ "email_sent": "Email sent successfully", "email_deleted": "Email deleted", "email_archived": "Email archived", + "emails_deleted": "{count, plural, one {# email deleted} other {# emails deleted}}", + "emails_archived": "{count, plural, one {# email archived} other {# emails archived}}", + "error_archiving": "Failed to archive email", + "error_updating": "Failed to update email", "email_starred": "Email starred", "email_unstarred": "Email unstarred", "email_marked_read": "Email marked as read", diff --git a/locales/es/common.json b/locales/es/common.json index ae2413a7f..d40b4e44c 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -778,6 +778,10 @@ "email_sent": "Correo enviado exitosamente", "email_deleted": "Correo eliminado", "email_archived": "Correo archivado", + "emails_deleted": "{count, plural, one {# correo eliminado} other {# correos eliminados}}", + "emails_archived": "{count, plural, one {# correo archivado} other {# correos archivados}}", + "error_archiving": "No se pudo archivar el correo", + "error_updating": "No se pudo actualizar el correo", "email_starred": "Correo destacado", "email_unstarred": "Correo sin destacar", "email_marked_read": "Correo marcado como leído", diff --git a/locales/fa/common.json b/locales/fa/common.json index c454007f8..22ae0e6d0 100644 --- a/locales/fa/common.json +++ b/locales/fa/common.json @@ -778,6 +778,10 @@ "email_sent": "ایمیل با موفقیت ارسال شد", "email_deleted": "ایمیل حذف شد", "email_archived": "ایمیل بایگانی شد", + "emails_deleted": "{count, plural, other {# ایمیل حذف شد}}", + "emails_archived": "{count, plural, other {# ایمیل بایگانی شد}}", + "error_archiving": "بایگانی ایمیل ناموفق بود", + "error_updating": "به‌روزرسانی ایمیل ناموفق بود", "email_starred": "ایمیل ستاره‌دار شد", "email_unstarred": "ستاره ایمیل برداشته شد", "email_marked_read": "ایمیل خوانده شده علامت‌گذاری شد", diff --git a/locales/fr/common.json b/locales/fr/common.json index 738fd0b3f..c5b9241ec 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -778,6 +778,10 @@ "email_sent": "Email envoyé avec succès", "email_deleted": "Email supprimé", "email_archived": "Email archivé", + "emails_deleted": "{count, plural, one {# e-mail supprimé} other {# e-mails supprimés}}", + "emails_archived": "{count, plural, one {# e-mail archivé} other {# e-mails archivés}}", + "error_archiving": "Impossible d'archiver l'e-mail", + "error_updating": "Impossible de mettre à jour l'e-mail", "email_starred": "Email ajouté aux favoris", "email_unstarred": "Email retiré des favoris", "email_marked_read": "Email marqué comme lu", diff --git a/locales/he/common.json b/locales/he/common.json index a03914d4f..c300472e4 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -743,6 +743,10 @@ "email_sent": "האימייל נשלח בהצלחה", "email_deleted": "האימייל נמחק", "email_archived": "האימייל הועבר לארכיון", + "emails_deleted": "{count, plural, one {הודעה אחת נמחקה} other {# הודעות נמחקו}}", + "emails_archived": "{count, plural, one {הודעה אחת הועברה לארכיון} other {# הודעות הועברו לארכיון}}", + "error_archiving": "העברת ההודעה לארכיון נכשלה", + "error_updating": "עדכון ההודעה נכשל", "email_starred": "אימייל מסומן בכוכב", "email_unstarred": "דוא\"ל בוטל בכוכב", "email_marked_read": "אימייל סומן כנקראה", diff --git a/locales/hu/common.json b/locales/hu/common.json index d348bccb5..c8ae7c832 100644 --- a/locales/hu/common.json +++ b/locales/hu/common.json @@ -778,6 +778,10 @@ "email_sent": "E-mail sikeresen elküldve", "email_deleted": "E-mail törölve", "email_archived": "E-mail archiválva", + "emails_deleted": "{count, plural, other {# e-mail törölve}}", + "emails_archived": "{count, plural, other {# e-mail archiválva}}", + "error_archiving": "Nem sikerült archiválni az e-mailt", + "error_updating": "Nem sikerült frissíteni az e-mailt", "email_starred": "E-mail csillagozva", "email_unstarred": "E-mail csillagozás megszüntetve", "email_marked_read": "E-mail olvasottnak jelölve", diff --git a/locales/it/common.json b/locales/it/common.json index 30c7ab7af..b0fab1da8 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -778,6 +778,10 @@ "email_sent": "Messaggio inviato con successo", "email_deleted": "Messaggio eliminato", "email_archived": "Messaggio archiviato", + "emails_deleted": "{count, plural, one {# email eliminata} other {# email eliminate}}", + "emails_archived": "{count, plural, one {# email archiviata} other {# email archiviate}}", + "error_archiving": "Impossibile archiviare l'email", + "error_updating": "Impossibile aggiornare l'email", "email_starred": "Stella aggiunta al messaggio", "email_unstarred": "Stella rimossa dal messaggio", "email_marked_read": "Messaggio segnato come letto", diff --git a/locales/ja/common.json b/locales/ja/common.json index c6555f190..3b5c5eb7b 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -778,6 +778,10 @@ "email_sent": "メールを送信しました", "email_deleted": "メールを削除しました", "email_archived": "メールをアーカイブしました", + "emails_deleted": "{count, plural, other {#件のメールを削除しました}}", + "emails_archived": "{count, plural, other {#件のメールをアーカイブしました}}", + "error_archiving": "メールをアーカイブできませんでした", + "error_updating": "メールを更新できませんでした", "email_starred": "スターを付けました", "email_unstarred": "スターを外しました", "email_marked_read": "既読にしました", diff --git a/locales/ko/common.json b/locales/ko/common.json index 93f56bda1..bd3123e84 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -778,6 +778,10 @@ "email_sent": "메일이 전송되었어요", "email_deleted": "메일이 삭제되었어요", "email_archived": "메일이 보관되었어요", + "emails_deleted": "{count, plural, other {이메일 #개 삭제됨}}", + "emails_archived": "{count, plural, other {이메일 #개 보관됨}}", + "error_archiving": "이메일을 보관하지 못했습니다", + "error_updating": "이메일을 업데이트하지 못했습니다", "email_starred": "별표가 추가되었어요", "email_unstarred": "별표가 해제되었어요", "email_marked_read": "읽은 상태로 변경되었어요", diff --git a/locales/lv/common.json b/locales/lv/common.json index b31dd7047..f1b1009b4 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -778,6 +778,10 @@ "email_sent": "Vēstule veiksmīgi nosūtīta", "email_deleted": "Vēstule izdzēsta", "email_archived": "Vēstule arhivēta", + "emails_deleted": "{count, plural, zero {# e-pasti dzēsti} one {# e-pasts dzēsts} other {# e-pasti dzēsti}}", + "emails_archived": "{count, plural, zero {# e-pasti arhivēti} one {# e-pasts arhivēts} other {# e-pasti arhivēti}}", + "error_archiving": "Neizdevās arhivēt e-pastu", + "error_updating": "Neizdevās atjaunināt e-pastu", "email_starred": "Vēstulei pievienota zvaigznīte", "email_unstarred": "Zvaigznīte noņemta", "email_marked_read": "Vēstule atzīmēta kā izlasīta", diff --git a/locales/mn/common.json b/locales/mn/common.json index 0fc2b17f2..aaf234126 100644 --- a/locales/mn/common.json +++ b/locales/mn/common.json @@ -778,6 +778,10 @@ "email_sent": "Имэйл амжилттай илгээгдсэн", "email_deleted": "Имэйл устгасан", "email_archived": "Имэйл архивлагдсан", + "emails_deleted": "{count, plural, other {# имэйл устгагдлаа}}", + "emails_archived": "{count, plural, other {# имэйл архивлагдлаа}}", + "error_archiving": "Имэйлийг архивлаж чадсангүй", + "error_updating": "Имэйлийг шинэчилж чадсангүй", "email_starred": "И-мэйл одоор тэмдэглэгдсэн", "email_unstarred": "И-мэйл одыг арилгасан", "email_marked_read": "И-мэйл уншсан гэж тэмдэглэсэн", diff --git a/locales/nb/common.json b/locales/nb/common.json index 3648dccfc..5bc816bdf 100644 --- a/locales/nb/common.json +++ b/locales/nb/common.json @@ -778,6 +778,10 @@ "email_sent": "E-posten er sendt", "email_deleted": "E-posten er slettet", "email_archived": "E-posten er arkivert", + "emails_deleted": "{count, plural, one {# e-post slettet} other {# e-poster slettet}}", + "emails_archived": "{count, plural, one {# e-post arkivert} other {# e-poster arkivert}}", + "error_archiving": "Kunne ikke arkivere e-posten", + "error_updating": "Kunne ikke oppdatere e-posten", "email_starred": "E-posten er stjernemerket", "email_unstarred": "E-posten er ikke lenger stjernemerket", "email_marked_read": "E-posten er merket som lest", diff --git a/locales/nl/common.json b/locales/nl/common.json index 12e564a77..adc901688 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -778,6 +778,10 @@ "email_sent": "E-mail succesvol verzonden", "email_deleted": "E-mail verwijderd", "email_archived": "E-mail gearchiveerd", + "emails_deleted": "{count, plural, one {# e-mail verwijderd} other {# e-mails verwijderd}}", + "emails_archived": "{count, plural, one {# e-mail gearchiveerd} other {# e-mails gearchiveerd}}", + "error_archiving": "E-mail kon niet worden gearchiveerd", + "error_updating": "E-mail kon niet worden bijgewerkt", "email_starred": "Ster toegevoegd aan e-mail", "email_unstarred": "Ster verwijderd van e-mail", "email_marked_read": "E-mail gemarkeerd als gelezen", diff --git a/locales/pl/common.json b/locales/pl/common.json index e903226ee..de19437c9 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -778,6 +778,10 @@ "email_sent": "Wiadomość wysłana pomyślnie", "email_deleted": "Wiadomość usunięta", "email_archived": "Wiadomość zarchiwizowana", + "emails_deleted": "{count, plural, one {# wiadomość usunięta} few {# wiadomości usunięte} many {# wiadomości usuniętych} other {# wiadomości usuniętych}}", + "emails_archived": "{count, plural, one {# wiadomość zarchiwizowana} few {# wiadomości zarchiwizowane} many {# wiadomości zarchiwizowanych} other {# wiadomości zarchiwizowanych}}", + "error_archiving": "Nie udało się zarchiwizować wiadomości", + "error_updating": "Nie udało się zaktualizować wiadomości", "email_starred": "Wiadomość oznaczona gwiazdką", "email_unstarred": "Gwiazdka usunięta", "email_marked_read": "Wiadomość oznaczona jako przeczytana", diff --git a/locales/pt/common.json b/locales/pt/common.json index bb8f8c8fc..5efe797d7 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -778,6 +778,10 @@ "email_sent": "E-mail enviado com sucesso", "email_deleted": "E-mail excluído", "email_archived": "E-mail arquivado", + "emails_deleted": "{count, plural, one {# e-mail excluído} other {# e-mails excluídos}}", + "emails_archived": "{count, plural, one {# e-mail arquivado} other {# e-mails arquivados}}", + "error_archiving": "Falha ao arquivar o e-mail", + "error_updating": "Falha ao atualizar o e-mail", "email_starred": "E-mail marcado com estrela", "email_unstarred": "Estrela removida do e-mail", "email_marked_read": "E-mail marcado como lido", diff --git a/locales/ro/common.json b/locales/ro/common.json index 0af8fbf90..b17e6c15b 100644 --- a/locales/ro/common.json +++ b/locales/ro/common.json @@ -778,6 +778,10 @@ "email_sent": "E-mailul a fost trimis cu succes", "email_deleted": "E-mail șters", "email_archived": "E-mail arhivat", + "emails_deleted": "{count, plural, one {# e-mail șters} few {# e-mailuri șterse} other {# de e-mailuri șterse}}", + "emails_archived": "{count, plural, one {# e-mail arhivat} few {# e-mailuri arhivate} other {# de e-mailuri arhivate}}", + "error_archiving": "Arhivarea e-mailului a eșuat", + "error_updating": "Actualizarea e-mailului a eșuat", "email_starred": "E-mail marcat cu stea", "email_unstarred": "E-mail fără stea", "email_marked_read": "E-mail marcat ca citit", diff --git a/locales/ru/common.json b/locales/ru/common.json index bd08b879c..2ec809094 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -778,6 +778,10 @@ "email_sent": "Письмо успешно отправлено", "email_deleted": "Письмо удалено", "email_archived": "Письмо архивировано", + "emails_deleted": "{count, plural, one {# письмо удалено} few {# письма удалены} many {# писем удалено} other {# письма удалено}}", + "emails_archived": "{count, plural, one {# письмо архивировано} few {# письма архивированы} many {# писем архивировано} other {# письма архивировано}}", + "error_archiving": "Не удалось архивировать письмо", + "error_updating": "Не удалось обновить письмо", "email_starred": "Письмо помечено", "email_unstarred": "Пометка снята", "email_marked_read": "Письмо отмечено прочитанным", diff --git a/locales/sk/common.json b/locales/sk/common.json index 2e17b787a..5ce7599c2 100644 --- a/locales/sk/common.json +++ b/locales/sk/common.json @@ -778,6 +778,10 @@ "email_sent": "E-mail bol úspešne odoslaný", "email_deleted": "E-mail bol odstránený", "email_archived": "E-mail bol archivovaný", + "emails_deleted": "{count, plural, one {# e-mail odstránený} few {# e-maily odstránené} other {# e-mailov odstránených}}", + "emails_archived": "{count, plural, one {# e-mail archivovaný} few {# e-maily archivované} other {# e-mailov archivovaných}}", + "error_archiving": "E-mail sa nepodarilo archivovať", + "error_updating": "E-mail sa nepodarilo aktualizovať", "email_starred": "E-mail bol označený hviezdičkou", "email_unstarred": "Hviezdička bola odstránená", "email_marked_read": "E-mail bol označený ako prečítaný", diff --git a/locales/tr/common.json b/locales/tr/common.json index f6755de49..dec655159 100644 --- a/locales/tr/common.json +++ b/locales/tr/common.json @@ -778,6 +778,10 @@ "email_sent": "E-posta başarıyla gönderildi", "email_deleted": "E-posta silindi", "email_archived": "E-posta arşivlendi", + "emails_deleted": "{count, plural, other {# e-posta silindi}}", + "emails_archived": "{count, plural, other {# e-posta arşivlendi}}", + "error_archiving": "E-posta arşivlenemedi", + "error_updating": "E-posta güncellenemedi", "email_starred": "E-posta yıldızlandı", "email_unstarred": "E-postanın yıldızı kaldırıldı", "email_marked_read": "E-posta okundu olarak işaretlendi", diff --git a/locales/uk/common.json b/locales/uk/common.json index a896c863c..0a74fa265 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -778,6 +778,10 @@ "email_sent": "Електронна пошта успішно надіслана", "email_deleted": "Електронну пошту видалено", "email_archived": "Електронний лист заархівовано", + "emails_deleted": "{count, plural, one {# лист видалено} few {# листи видалено} many {# листів видалено} other {# листа видалено}}", + "emails_archived": "{count, plural, one {# лист архівовано} few {# листи архівовано} many {# листів архівовано} other {# листа архівовано}}", + "error_archiving": "Не вдалося архівувати лист", + "error_updating": "Не вдалося оновити лист", "email_starred": "Електронна пошта позначена зірочкою", "email_unstarred": "З електронної пошти знято зірочку", "email_marked_read": "Електронна пошта позначена як прочитана", diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json index 289ce6d53..926d428af 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -778,6 +778,10 @@ "email_sent": "郵件傳送成功", "email_deleted": "郵件已刪除", "email_archived": "郵件已封存", + "emails_deleted": "{count, plural, other {已刪除 # 封郵件}}", + "emails_archived": "{count, plural, other {已封存 # 封郵件}}", + "error_archiving": "封存郵件失敗", + "error_updating": "更新郵件失敗", "email_starred": "郵件已加上星號", "email_unstarred": "郵件已移除星號", "email_marked_read": "郵件已標示為已讀", diff --git a/locales/zh/common.json b/locales/zh/common.json index 2cf732396..a47ce10c6 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -778,6 +778,10 @@ "email_sent": "邮件发送成功", "email_deleted": "邮件已删除", "email_archived": "邮件已归档", + "emails_deleted": "{count, plural, other {已删除 # 封邮件}}", + "emails_archived": "{count, plural, other {已归档 # 封邮件}}", + "error_archiving": "归档邮件失败", + "error_updating": "更新邮件失败", "email_starred": "邮件已加星标", "email_unstarred": "邮件已取消星标", "email_marked_read": "邮件已标记为已读",