mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
feat: add missing mail action toasts and show sonner toasts again
This commit is contained in:
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<void>,
|
||||
messages: { success: string; error: string; describeError?: (error: unknown) => string | undefined },
|
||||
): Promise<void> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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": "تم تمييز الرسالة كمقروءة",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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á",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "ایمیل خوانده شده علامتگذاری شد",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "אימייל סומן כנקראה",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "既読にしました",
|
||||
|
||||
@@ -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": "읽은 상태로 변경되었어요",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "И-мэйл уншсан гэж тэмдэглэсэн",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "Письмо отмечено прочитанным",
|
||||
|
||||
@@ -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ý",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "Електронна пошта позначена як прочитана",
|
||||
|
||||
@@ -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": "郵件已標示為已讀",
|
||||
|
||||
@@ -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": "邮件已标记为已读",
|
||||
|
||||
Reference in New Issue
Block a user