mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
feat: hold toasts while focused and jump to the newest with Alt+Shift+N
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { act, fireEvent, render, screen, within } from '@testing-library/react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { ToastContainer } from '../toast';
|
||||
import { toast, useToastStore } from '@/stores/toast-store';
|
||||
|
||||
function Toasts() {
|
||||
const toasts = useToastStore((s) => s.toasts);
|
||||
const removeToast = useToastStore((s) => s.removeToast);
|
||||
return <ToastContainer toasts={toasts} onClose={removeToast} />;
|
||||
}
|
||||
|
||||
// The toasts themselves, not the live region that reads them out.
|
||||
const toasts = () => within(document.querySelector('[data-toast-container]') as HTMLElement);
|
||||
const pressFocusShortcut = () =>
|
||||
fireEvent.keyDown(window, { key: 'N', code: 'KeyN', altKey: true, shiftKey: true });
|
||||
|
||||
describe('toasts and the keyboard', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
useToastStore.setState({ toasts: [] });
|
||||
});
|
||||
const extra: HTMLElement[] = [];
|
||||
const add = <T extends HTMLElement>(el: T): T => {
|
||||
document.body.appendChild(el);
|
||||
extra.push(el);
|
||||
return el;
|
||||
};
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
for (const el of extra.splice(0)) el.remove();
|
||||
});
|
||||
|
||||
it('holds the countdown while the focus is inside the toast', () => {
|
||||
render(<Toasts />);
|
||||
const onClick = vi.fn();
|
||||
act(() => { toast.success('Email archived', { action: { label: 'Undo', onClick }, duration: 5000 }); });
|
||||
const undo = screen.getByRole('button', { name: 'Undo' });
|
||||
act(() => { undo.focus(); });
|
||||
act(() => { vi.advanceTimersByTime(20000); });
|
||||
expect(toasts().getByText('Email archived')).toBeInTheDocument();
|
||||
|
||||
// Focus leaves: the rest of the time runs out.
|
||||
act(() => { undo.blur(); });
|
||||
act(() => { vi.advanceTimersByTime(6000); });
|
||||
expect(toasts().queryByText('Email archived')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not hold a toast whose action ends at a fixed time', () => {
|
||||
render(<Toasts />);
|
||||
act(() => {
|
||||
toast.info('Sending', { action: { label: 'Undo', onClick: vi.fn() }, duration: 5000, pauseOnHover: false });
|
||||
});
|
||||
act(() => { screen.getByRole('button', { name: 'Undo' }).focus(); });
|
||||
act(() => { vi.advanceTimersByTime(6000); });
|
||||
expect(toasts().queryByText('Sending')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('moves the focus to the newest toast\'s action with Alt+Shift+N, and back when it closes', () => {
|
||||
const before = document.createElement('button');
|
||||
before.textContent = 'Message';
|
||||
add(before);
|
||||
before.focus();
|
||||
render(<Toasts />);
|
||||
const onClick = vi.fn();
|
||||
act(() => { toast.info('Older'); });
|
||||
act(() => { toast.success('Email deleted', { action: { label: 'Undo', onClick } }); });
|
||||
|
||||
pressFocusShortcut();
|
||||
expect(document.activeElement).toBe(screen.getByRole('button', { name: 'Undo' }));
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Undo' }));
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
expect(document.activeElement).toBe(before);
|
||||
});
|
||||
|
||||
it('closes the focused toast with Escape without the page hearing it', () => {
|
||||
const pageEscape = vi.fn();
|
||||
window.addEventListener('keydown', pageEscape);
|
||||
render(<Toasts />);
|
||||
act(() => { toast.success('Saved'); });
|
||||
pressFocusShortcut();
|
||||
pageEscape.mockClear();
|
||||
fireEvent.keyDown(document.activeElement!, { key: 'Escape' });
|
||||
act(() => { vi.advanceTimersByTime(400); });
|
||||
expect(toasts().queryByText('Saved')).not.toBeInTheDocument();
|
||||
expect(pageEscape).not.toHaveBeenCalled();
|
||||
window.removeEventListener('keydown', pageEscape);
|
||||
});
|
||||
|
||||
it('leaves the focus alone while a modal dialog is open', () => {
|
||||
const dialog = document.createElement('div');
|
||||
dialog.setAttribute('aria-modal', 'true');
|
||||
const inside = document.createElement('button');
|
||||
dialog.appendChild(inside);
|
||||
add(dialog);
|
||||
inside.focus();
|
||||
render(<Toasts />);
|
||||
act(() => { toast.success('Saved', { action: { label: 'Undo', onClick: vi.fn() } }); });
|
||||
pressFocusShortcut();
|
||||
expect(document.activeElement).toBe(inside);
|
||||
});
|
||||
});
|
||||
+83
-9
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState, useCallback, useRef } from "react";
|
||||
import { useEffect, useState, useCallback, useRef, useId } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { X, CheckCircle, AlertCircle, Info, AlertTriangle, Loader2 } from "@/components/icons";
|
||||
@@ -55,6 +55,21 @@ interface ToastProps {
|
||||
onClose: (id: string) => void;
|
||||
/** Kept out of sight for now (a menu is open over it): the countdown waits. */
|
||||
held?: boolean;
|
||||
/** The toast goes away with the keyboard focus in it: put the focus back. */
|
||||
onFocusLost?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jumps to the newest toast from anywhere (Alt+Shift+N), so its Undo can be
|
||||
* reached without tabbing through the page. Listed in lib/keyboard-shortcuts.
|
||||
*/
|
||||
export function isFocusToastShortcut(e: KeyboardEvent): boolean {
|
||||
return e.altKey && e.shiftKey && !e.ctrlKey && !e.metaKey && e.code === "KeyN";
|
||||
}
|
||||
|
||||
/** A modal dialog is open: keys and focus belong to it. */
|
||||
function modalOpen(): boolean {
|
||||
return document.querySelector('[aria-modal="true"]') !== null;
|
||||
}
|
||||
|
||||
const icons = {
|
||||
@@ -83,7 +98,7 @@ const progressBarStyles = {
|
||||
// A sideways swipe this far (px) on a touch screen dismisses the toast.
|
||||
const SWIPE_DISMISS_DISTANCE = 72;
|
||||
|
||||
export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
export function ToastItem({ toast, onClose, held = false, onFocusLost }: ToastProps) {
|
||||
const tCommon = useTranslations("common");
|
||||
const Icon = icons[toast.type];
|
||||
const [exiting, setExiting] = useState(false);
|
||||
@@ -91,7 +106,14 @@ export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
const [dragX, setDragX] = useState(0);
|
||||
const [flungTo, setFlungTo] = useState<number | null>(null);
|
||||
const swipeRef = useRef<{ id: number; x: number; y: number; horizontal: boolean | null } | null>(null);
|
||||
// Swiping holds the countdown; so do the pointer over the toast and the
|
||||
// keyboard focus in it (2.2.1), unless the action stops working at a fixed
|
||||
// time (pauseOnHover: false).
|
||||
const [paused, setPaused] = useState(false);
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const [focused, setFocused] = useState(false);
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
const titleId = useId();
|
||||
const remainingRef = useRef(toast.duration ?? 5000);
|
||||
const startRef = useRef(Date.now());
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
@@ -106,8 +128,10 @@ export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
|
||||
const dismiss = useCallback(() => {
|
||||
setExiting(true);
|
||||
// Removing the toast would drop the focus onto <body>.
|
||||
if (rootRef.current?.contains(document.activeElement)) onFocusLost?.();
|
||||
setTimeout(() => onClose(toast.id), 280);
|
||||
}, [onClose, toast.id]);
|
||||
}, [onClose, toast.id, onFocusLost]);
|
||||
|
||||
const dismissByUser = useCallback(() => {
|
||||
try {
|
||||
@@ -118,7 +142,8 @@ export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
dismiss();
|
||||
}, [toast, dismiss]);
|
||||
|
||||
const waiting = paused || held;
|
||||
const canPause = toast.pauseOnHover !== false;
|
||||
const waiting = paused || held || (canPause && (hovered || focused));
|
||||
useEffect(() => {
|
||||
if (!toast.duration || toast.duration <= 0 || isProgress) return;
|
||||
|
||||
@@ -217,8 +242,22 @@ export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
onPointerMove={onPointerMove}
|
||||
onPointerUp={endSwipe}
|
||||
onPointerCancel={endSwipe}
|
||||
onMouseEnter={() => { if (toast.pauseOnHover !== false) setPaused(true); }}
|
||||
onMouseLeave={() => setPaused(false)}
|
||||
ref={rootRef}
|
||||
role="group"
|
||||
aria-labelledby={titleId}
|
||||
tabIndex={-1}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={(e) => {
|
||||
if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setFocused(false);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key !== "Escape") return;
|
||||
// The toast's, not the page's Escape (closing the open message).
|
||||
e.stopPropagation();
|
||||
dismissByUser();
|
||||
}}
|
||||
onClick={() => {
|
||||
if (swiped) return;
|
||||
if (toast.onClick && !toast.action) {
|
||||
@@ -238,7 +277,7 @@ export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 min-w-0 pt-px">
|
||||
<p className="text-[13.5px] font-medium text-foreground leading-snug">{toast.title}</p>
|
||||
<p id={titleId} className="text-[13.5px] font-medium text-foreground leading-snug">{toast.title}</p>
|
||||
{toast.message && (
|
||||
<p className="text-[12.5px] mt-0.5 text-muted-foreground leading-snug">{toast.message}</p>
|
||||
)}
|
||||
@@ -261,6 +300,7 @@ export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
{/* Close button. Phones swipe the toast away instead. */}
|
||||
<button
|
||||
type="button"
|
||||
data-toast-close=""
|
||||
aria-label={tCommon("close")}
|
||||
title={tCommon("close")}
|
||||
onClick={(e) => {
|
||||
@@ -300,7 +340,7 @@ export function ToastItem({ toast, onClose, held = false }: ToastProps) {
|
||||
className={cn("h-full opacity-60", progressBarStyles[toast.type])}
|
||||
style={{
|
||||
animation: `toast-progress ${toast.duration}ms linear forwards`,
|
||||
animationPlayState: paused ? "paused" : "running",
|
||||
animationPlayState: waiting ? "paused" : "running",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -318,11 +358,44 @@ export function ToastContainer({ toasts, onClose }: { toasts: Toast[]; onClose:
|
||||
const menuOpen = useContextMenuOpen();
|
||||
const phone = useMediaQuery("(max-width: 639px)");
|
||||
const held = menuOpen && phone;
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
// Where the focus was before the shortcut moved it into a toast.
|
||||
const returnFocusRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
const hasToasts = toasts.length > 0;
|
||||
useEffect(() => {
|
||||
if (!hasToasts) return;
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (!isFocusToastShortcut(e) || modalOpen()) return;
|
||||
const items = containerRef.current?.querySelectorAll<HTMLElement>(".toast-item");
|
||||
const newest = items?.[items.length - 1];
|
||||
if (!newest) return;
|
||||
e.preventDefault();
|
||||
const active = document.activeElement as HTMLElement | null;
|
||||
if (active && active !== document.body && !containerRef.current?.contains(active)) {
|
||||
returnFocusRef.current = active;
|
||||
}
|
||||
// Its first action (Undo), else the close button, else the toast.
|
||||
const target =
|
||||
newest.querySelector<HTMLElement>("button:not([data-toast-close])") ??
|
||||
Array.from(newest.querySelectorAll<HTMLElement>("button[data-toast-close]")).find((b) => b.offsetParent !== null || b.getClientRects().length > 0) ??
|
||||
newest;
|
||||
target.focus();
|
||||
};
|
||||
window.addEventListener("keydown", onKeyDown);
|
||||
return () => window.removeEventListener("keydown", onKeyDown);
|
||||
}, [hasToasts]);
|
||||
|
||||
const returnFocus = useCallback(() => {
|
||||
const back = returnFocusRef.current;
|
||||
returnFocusRef.current = null;
|
||||
if (back && back.isConnected) back.focus();
|
||||
}, []);
|
||||
|
||||
if (!mounted) return null;
|
||||
|
||||
return createPortal(
|
||||
@@ -341,6 +414,7 @@ export function ToastContainer({ toasts, onClose }: { toasts: Toast[]; onClose:
|
||||
// Not a live region: the toast store reads each toast out through
|
||||
// lib/announce (errors assertively). A labelled region while toasts
|
||||
// are up, so screen reader users can find them.
|
||||
ref={containerRef}
|
||||
data-toast-container=""
|
||||
role={toasts.length > 0 ? "region" : undefined}
|
||||
aria-label={toasts.length > 0 ? tCenter("title") : undefined}
|
||||
@@ -348,7 +422,7 @@ export function ToastContainer({ toasts, onClose }: { toasts: Toast[]; onClose:
|
||||
>
|
||||
{toasts.map((toast) => (
|
||||
<div key={toast.id} style={{ pointerEvents: "auto" }}>
|
||||
<ToastItem toast={toast} onClose={onClose} held={held} />
|
||||
<ToastItem toast={toast} onClose={onClose} held={held} onFocusLost={returnFocus} />
|
||||
</div>
|
||||
))}
|
||||
</div>,
|
||||
|
||||
@@ -34,6 +34,8 @@ export const GENERAL_SHORTCUTS: readonly ShortcutEntry[] = [
|
||||
{ key: "Mod + K", description: "command_palette.open", shell: "standard" },
|
||||
{ key: "?", description: "shortcuts.global.help" },
|
||||
{ key: "Alt + Shift + A", description: "shortcuts.global.accessibility_panel" },
|
||||
// components/ui/toast.tsx (isFocusToastShortcut)
|
||||
{ key: "Alt + Shift + N", description: "shortcuts.global.focus_notification" },
|
||||
];
|
||||
|
||||
/** An app's sections with the general keys added (see GENERAL_SHORTCUTS). */
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "إدارة القواعد",
|
||||
"senders_count": "{count, plural, one {مرسل واحد} two {مرسلَين} few {# مرسلين} many {# مرسلًا} other {# مرسل}}",
|
||||
"cross_account": "حدد رسائل من حساب واحد",
|
||||
"opaque_hint": "تم تعديل مرشحاتك يدويًا. افتح إعدادات المرشحات"
,
|
||||
"loading": "جارٍ تحميل القواعد…",
|
||||
"load_failed": "تعذّر تحميل القواعد",
|
||||
"none": "لا توجد قواعد بعد",
|
||||
"new_mail_only": "للرسائل الجديدة فقط",
|
||||
"running": "جارٍ تشغيل «{name}» على {folder}…"
|
||||
"opaque_hint": "تم تعديل مرشحاتك يدويًا. افتح إعدادات المرشحات"
,
|
||||
"loading": "جارٍ تحميل القواعد…",
|
||||
"load_failed": "تعذّر تحميل القواعد",
|
||||
"none": "لا توجد قواعد بعد",
|
||||
"new_mail_only": "للرسائل الجديدة فقط",
|
||||
"running": "جارٍ تشغيل «{name}» على {folder}…"
|
||||
},
|
||||
"find_emails_from": "البحث عن رسائل من {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "تحديد الكل",
|
||||
"global_search": "البحث في كل شيء",
|
||||
"extend_selection": "توسيع التحديد لأسفل / لأعلى",
|
||||
"accessibility_panel": "فتح خيارات إمكانية الوصول"
|
||||
"accessibility_panel": "فتح خيارات إمكانية الوصول",
|
||||
"focus_notification": "الانتقال إلى أحدث إشعار"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "توسيع/طي المحادثة",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Gestiona les regles",
|
||||
"senders_count": "{count, plural, one {# remitent} other {# remitents}}",
|
||||
"cross_account": "Selecciona missatges d'un sol compte",
|
||||
"opaque_hint": "Els teus filtres s'han editat a mà. Obre la configuració dels filtres"
,
|
||||
"loading": "S'estan carregant les regles…",
|
||||
"load_failed": "No s'han pogut carregar les regles",
|
||||
"none": "Encara no hi ha regles",
|
||||
"new_mail_only": "Només per a missatges nous",
|
||||
"running": "S'està executant «{name}» a {folder}…"
|
||||
"opaque_hint": "Els teus filtres s'han editat a mà. Obre la configuració dels filtres"
,
|
||||
"loading": "S'estan carregant les regles…",
|
||||
"load_failed": "No s'han pogut carregar les regles",
|
||||
"none": "Encara no hi ha regles",
|
||||
"new_mail_only": "Només per a missatges nous",
|
||||
"running": "S'està executant «{name}» a {folder}…"
|
||||
},
|
||||
"find_emails_from": "Cerca correus de {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Selecciona-ho tot",
|
||||
"global_search": "Cerca-ho tot",
|
||||
"extend_selection": "Amplia la selecció cap avall / amunt",
|
||||
"accessibility_panel": "Obre les opcions d'accessibilitat"
|
||||
"accessibility_panel": "Obre les opcions d'accessibilitat",
|
||||
"focus_notification": "Ves a la notificació més recent"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Desplega/replega el fil",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Spravovat pravidla",
|
||||
"senders_count": "{count, plural, one {# odesílatele} few {# odesílatelů} many {# odesílatele} other {# odesílatelů}}",
|
||||
"cross_account": "Vyberte zprávy z jednoho účtu",
|
||||
"opaque_hint": "Vaše filtry byly upraveny ručně. Otevřete nastavení filtrů"
,
|
||||
"loading": "Načítání pravidel…",
|
||||
"load_failed": "Pravidla se nepodařilo načíst",
|
||||
"none": "Zatím žádná pravidla",
|
||||
"new_mail_only": "Pouze pro nové zprávy",
|
||||
"running": "Spouštění „{name}“ ve složce {folder}…"
|
||||
"opaque_hint": "Vaše filtry byly upraveny ručně. Otevřete nastavení filtrů"
,
|
||||
"loading": "Načítání pravidel…",
|
||||
"load_failed": "Pravidla se nepodařilo načíst",
|
||||
"none": "Zatím žádná pravidla",
|
||||
"new_mail_only": "Pouze pro nové zprávy",
|
||||
"running": "Spouštění „{name}“ ve složce {folder}…"
|
||||
},
|
||||
"find_emails_from": "Najít e-maily od {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Vybrat vše",
|
||||
"global_search": "Hledat ve všem",
|
||||
"extend_selection": "Rozšířit výběr dolů / nahoru",
|
||||
"accessibility_panel": "Otevřít možnosti přístupnosti"
|
||||
"accessibility_panel": "Otevřít možnosti přístupnosti",
|
||||
"focus_notification": "Přejít na nejnovější oznámení"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Rozbalit/sbalit vlákno",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Administrer regler",
|
||||
"senders_count": "{count, plural, one {# afsender} other {# afsendere}}",
|
||||
"cross_account": "Vælg beskeder fra én konto",
|
||||
"opaque_hint": "Dine filtre er redigeret manuelt. Åbn filterindstillingerne"
,
|
||||
"loading": "Indlæser regler…",
|
||||
"load_failed": "Reglerne kunne ikke indlæses",
|
||||
"none": "Ingen regler endnu",
|
||||
"new_mail_only": "Kun for nye beskeder",
|
||||
"running": "Kører „{name}“ på {folder}…"
|
||||
"opaque_hint": "Dine filtre er redigeret manuelt. Åbn filterindstillingerne"
,
|
||||
"loading": "Indlæser regler…",
|
||||
"load_failed": "Reglerne kunne ikke indlæses",
|
||||
"none": "Ingen regler endnu",
|
||||
"new_mail_only": "Kun for nye beskeder",
|
||||
"running": "Kører „{name}“ på {folder}…"
|
||||
},
|
||||
"find_emails_from": "Find e-mails fra {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Vælg alle",
|
||||
"global_search": "Søg i alt",
|
||||
"extend_selection": "Udvid markering ned / op",
|
||||
"accessibility_panel": "Åbn indstillinger for tilgængelighed"
|
||||
"accessibility_panel": "Åbn indstillinger for tilgængelighed",
|
||||
"focus_notification": "Gå til den seneste notifikation"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Udvid/skjul tråd",
|
||||
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Alle auswählen",
|
||||
"global_search": "Alles durchsuchen",
|
||||
"extend_selection": "Auswahl nach unten / oben erweitern",
|
||||
"accessibility_panel": "Optionen zur Barrierefreiheit öffnen"
|
||||
"accessibility_panel": "Optionen zur Barrierefreiheit öffnen",
|
||||
"focus_notification": "Zur neuesten Benachrichtigung springen"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Unterhaltung erweitern/einklappen",
|
||||
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Select all",
|
||||
"global_search": "Search everything",
|
||||
"extend_selection": "Extend selection down / up",
|
||||
"accessibility_panel": "Open the accessibility options"
|
||||
"accessibility_panel": "Open the accessibility options",
|
||||
"focus_notification": "Go to the latest notification"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Expand/collapse thread",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Administrar reglas",
|
||||
"senders_count": "{count, plural, one {# remitente} other {# remitentes}}",
|
||||
"cross_account": "Selecciona mensajes de una sola cuenta",
|
||||
"opaque_hint": "Tus filtros se editaron a mano. Abre la configuración de filtros"
,
|
||||
"loading": "Cargando reglas…",
|
||||
"load_failed": "No se pudieron cargar las reglas",
|
||||
"none": "Aún no hay reglas",
|
||||
"new_mail_only": "Solo para mensajes nuevos",
|
||||
"running": "Ejecutando «{name}» en {folder}…"
|
||||
"opaque_hint": "Tus filtros se editaron a mano. Abre la configuración de filtros"
,
|
||||
"loading": "Cargando reglas…",
|
||||
"load_failed": "No se pudieron cargar las reglas",
|
||||
"none": "Aún no hay reglas",
|
||||
"new_mail_only": "Solo para mensajes nuevos",
|
||||
"running": "Ejecutando «{name}» en {folder}…"
|
||||
},
|
||||
"find_emails_from": "Buscar correos de {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Seleccionar todo",
|
||||
"global_search": "Buscar en todo",
|
||||
"extend_selection": "Ampliar la selección hacia abajo / arriba",
|
||||
"accessibility_panel": "Abrir las opciones de accesibilidad"
|
||||
"accessibility_panel": "Abrir las opciones de accesibilidad",
|
||||
"focus_notification": "Ir a la notificación más reciente"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Expandir/contraer conversación",
|
||||
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Vali kõik",
|
||||
"global_search": "Otsi kõike",
|
||||
"extend_selection": "Laienda valikut alla / üles",
|
||||
"accessibility_panel": "Ava juurdepääsetavuse valikud"
|
||||
"accessibility_panel": "Ava juurdepääsetavuse valikud",
|
||||
"focus_notification": "Mine viimase teavituse juurde"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Ava/sulge vestlus",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "مدیریت قانونها",
|
||||
"senders_count": "{count, plural, one {# فرستنده} other {# فرستنده}}",
|
||||
"cross_account": "پیامهایی از یک حساب انتخاب کنید",
|
||||
"opaque_hint": "فیلترهای شما دستی ویرایش شدهاند. تنظیمات فیلترها را باز کنید"
,
|
||||
"loading": "در حال بارگذاری قوانین…",
|
||||
"load_failed": "بارگذاری قوانین ممکن نشد",
|
||||
"none": "هنوز قانونی وجود ندارد",
|
||||
"new_mail_only": "فقط برای پیامهای جدید",
|
||||
"running": "در حال اجرای «{name}» روی {folder}…"
|
||||
"opaque_hint": "فیلترهای شما دستی ویرایش شدهاند. تنظیمات فیلترها را باز کنید"
,
|
||||
"loading": "در حال بارگذاری قوانین…",
|
||||
"load_failed": "بارگذاری قوانین ممکن نشد",
|
||||
"none": "هنوز قانونی وجود ندارد",
|
||||
"new_mail_only": "فقط برای پیامهای جدید",
|
||||
"running": "در حال اجرای «{name}» روی {folder}…"
|
||||
},
|
||||
"find_emails_from": "یافتن ایمیلهای {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "انتخاب همه",
|
||||
"global_search": "جستجو در همه جا",
|
||||
"extend_selection": "گسترش انتخاب به پایین / بالا",
|
||||
"accessibility_panel": "باز کردن گزینههای دسترسپذیری"
|
||||
"accessibility_panel": "باز کردن گزینههای دسترسپذیری",
|
||||
"focus_notification": "رفتن به آخرین اعلان"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "باز/بسته کردن رشته",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Gérer les règles",
|
||||
"senders_count": "{count, plural, one {# expéditeur} other {# expéditeurs}}",
|
||||
"cross_account": "Sélectionnez des messages d'un seul compte",
|
||||
"opaque_hint": "Vos filtres ont été modifiés à la main. Ouvrez les réglages des filtres"
,
|
||||
"loading": "Chargement des règles…",
|
||||
"load_failed": "Impossible de charger les règles",
|
||||
"none": "Aucune règle pour l'instant",
|
||||
"new_mail_only": "Uniquement pour les nouveaux messages",
|
||||
"running": "Exécution de « {name} » sur {folder}…"
|
||||
"opaque_hint": "Vos filtres ont été modifiés à la main. Ouvrez les réglages des filtres"
,
|
||||
"loading": "Chargement des règles…",
|
||||
"load_failed": "Impossible de charger les règles",
|
||||
"none": "Aucune règle pour l'instant",
|
||||
"new_mail_only": "Uniquement pour les nouveaux messages",
|
||||
"running": "Exécution de « {name} » sur {folder}…"
|
||||
},
|
||||
"find_emails_from": "Rechercher les e-mails de {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Tout sélectionner",
|
||||
"global_search": "Tout rechercher",
|
||||
"extend_selection": "Étendre la sélection vers le bas / le haut",
|
||||
"accessibility_panel": "Ouvrir les options d'accessibilité"
|
||||
"accessibility_panel": "Ouvrir les options d'accessibilité",
|
||||
"focus_notification": "Aller à la dernière notification"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Développer/réduire la conversation",
|
||||
|
||||
@@ -3366,12 +3366,12 @@
|
||||
"manage": "ניהול כללים",
|
||||
"senders_count": "{count, plural, one {שולח אחד} other {# שולחים}}",
|
||||
"cross_account": "בחר הודעות מחשבון אחד",
|
||||
"opaque_hint": "המסננים שלך נערכו ידנית. פתח את הגדרות המסננים"
,
|
||||
"loading": "טוען כללים…",
|
||||
"load_failed": "לא ניתן לטעון את הכללים",
|
||||
"none": "אין עדיין כללים",
|
||||
"new_mail_only": "רק להודעות חדשות",
|
||||
"running": "מריץ את „{name}“ על {folder}…"
|
||||
"opaque_hint": "המסננים שלך נערכו ידנית. פתח את הגדרות המסננים"
,
|
||||
"loading": "טוען כללים…",
|
||||
"load_failed": "לא ניתן לטעון את הכללים",
|
||||
"none": "אין עדיין כללים",
|
||||
"new_mail_only": "רק להודעות חדשות",
|
||||
"running": "מריץ את „{name}“ על {folder}…"
|
||||
},
|
||||
"find_emails_from": "חיפוש הודעות מ{name}"
|
||||
},
|
||||
@@ -3414,7 +3414,8 @@
|
||||
"select_all": "בחר הכל",
|
||||
"global_search": "חיפוש בכל מקום",
|
||||
"extend_selection": "הרחבת הבחירה למטה / למעלה",
|
||||
"accessibility_panel": "פתיחת אפשרויות הנגישות"
|
||||
"accessibility_panel": "פתיחת אפשרויות הנגישות",
|
||||
"focus_notification": "מעבר להתראה האחרונה"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "הרחב/כווץ את השרשור",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Szabályok kezelése",
|
||||
"senders_count": "{count, plural, one {# feladó} other {# feladó}}",
|
||||
"cross_account": "Egyetlen fiók üzeneteit válaszd ki",
|
||||
"opaque_hint": "A szűrőidet kézzel szerkesztették. Nyisd meg a szűrőbeállításokat"
,
|
||||
"loading": "Szabályok betöltése…",
|
||||
"load_failed": "Nem sikerült betölteni a szabályokat",
|
||||
"none": "Még nincsenek szabályok",
|
||||
"new_mail_only": "Csak új üzenetekre",
|
||||
"running": "„{name}” futtatása itt: {folder}…"
|
||||
"opaque_hint": "A szűrőidet kézzel szerkesztették. Nyisd meg a szűrőbeállításokat"
,
|
||||
"loading": "Szabályok betöltése…",
|
||||
"load_failed": "Nem sikerült betölteni a szabályokat",
|
||||
"none": "Még nincsenek szabályok",
|
||||
"new_mail_only": "Csak új üzenetekre",
|
||||
"running": "„{name}” futtatása itt: {folder}…"
|
||||
},
|
||||
"find_emails_from": "{name} e-mailjeinek keresése"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Összes kijelölése",
|
||||
"global_search": "Keresés mindenben",
|
||||
"extend_selection": "Kijelölés bővítése lefelé / felfelé",
|
||||
"accessibility_panel": "Kisegítő lehetőségek megnyitása"
|
||||
"accessibility_panel": "Kisegítő lehetőségek megnyitása",
|
||||
"focus_notification": "Ugrás a legújabb értesítésre"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Beszélgetés kibontása/összecsukása",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Gestisci regole",
|
||||
"senders_count": "{count, plural, one {# mittente} other {# mittenti}}",
|
||||
"cross_account": "Seleziona messaggi di un solo account",
|
||||
"opaque_hint": "I tuoi filtri sono stati modificati a mano. Apri le impostazioni dei filtri"
,
|
||||
"loading": "Caricamento delle regole…",
|
||||
"load_failed": "Impossibile caricare le regole",
|
||||
"none": "Nessuna regola",
|
||||
"new_mail_only": "Solo per i nuovi messaggi",
|
||||
"running": "Esecuzione di «{name}» su {folder}…"
|
||||
"opaque_hint": "I tuoi filtri sono stati modificati a mano. Apri le impostazioni dei filtri"
,
|
||||
"loading": "Caricamento delle regole…",
|
||||
"load_failed": "Impossibile caricare le regole",
|
||||
"none": "Nessuna regola",
|
||||
"new_mail_only": "Solo per i nuovi messaggi",
|
||||
"running": "Esecuzione di «{name}» su {folder}…"
|
||||
},
|
||||
"find_emails_from": "Trova email da {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Seleziona tutto",
|
||||
"global_search": "Cerca ovunque",
|
||||
"extend_selection": "Estendi la selezione in basso / in alto",
|
||||
"accessibility_panel": "Apri le opzioni di accessibilità"
|
||||
"accessibility_panel": "Apri le opzioni di accessibilità",
|
||||
"focus_notification": "Vai all'ultima notifica"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Espandi/comprimi conversazione",
|
||||
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "すべて選択",
|
||||
"global_search": "すべてを検索",
|
||||
"extend_selection": "選択範囲を下 / 上に広げる",
|
||||
"accessibility_panel": "アクセシビリティのオプションを開く"
|
||||
"accessibility_panel": "アクセシビリティのオプションを開く",
|
||||
"focus_notification": "最新の通知に移動"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "スレッドの展開/折りたたみ",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "규칙 관리",
|
||||
"senders_count": "{count, plural, other {보낸 사람 #명}}",
|
||||
"cross_account": "한 계정의 메일만 선택하세요",
|
||||
"opaque_hint": "필터가 직접 편집되었어요. 필터 설정을 여세요"
,
|
||||
"loading": "규칙을 불러오는 중…",
|
||||
"load_failed": "규칙을 불러올 수 없습니다",
|
||||
"none": "아직 규칙이 없습니다",
|
||||
"new_mail_only": "새 메시지에만 적용",
|
||||
"running": "{folder}에서 \"{name}\" 실행 중…"
|
||||
"opaque_hint": "필터가 직접 편집되었어요. 필터 설정을 여세요"
,
|
||||
"loading": "규칙을 불러오는 중…",
|
||||
"load_failed": "규칙을 불러올 수 없습니다",
|
||||
"none": "아직 규칙이 없습니다",
|
||||
"new_mail_only": "새 메시지에만 적용",
|
||||
"running": "{folder}에서 \"{name}\" 실행 중…"
|
||||
},
|
||||
"find_emails_from": "{name}님이 보낸 이메일 찾기"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "모두 선택",
|
||||
"global_search": "전체 검색",
|
||||
"extend_selection": "선택 범위를 아래 / 위로 확장",
|
||||
"accessibility_panel": "접근성 옵션 열기"
|
||||
"accessibility_panel": "접근성 옵션 열기",
|
||||
"focus_notification": "최근 알림으로 이동"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "대화 펼치기/접기",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Pārvaldīt noteikumus",
|
||||
"senders_count": "{count, plural, zero {# sūtītājiem} one {# sūtītāja} other {# sūtītājiem}}",
|
||||
"cross_account": "Izvēlieties vēstules no viena konta",
|
||||
"opaque_hint": "Jūsu filtri ir rediģēti manuāli. Atveriet filtru iestatījumus"
,
|
||||
"loading": "Ielādē kārtulas…",
|
||||
"load_failed": "Neizdevās ielādēt kārtulas",
|
||||
"none": "Vēl nav kārtulu",
|
||||
"new_mail_only": "Tikai jaunām ziņām",
|
||||
"running": "Izpilda “{name}” mapē {folder}…"
|
||||
"opaque_hint": "Jūsu filtri ir rediģēti manuāli. Atveriet filtru iestatījumus"
,
|
||||
"loading": "Ielādē kārtulas…",
|
||||
"load_failed": "Neizdevās ielādēt kārtulas",
|
||||
"none": "Vēl nav kārtulu",
|
||||
"new_mail_only": "Tikai jaunām ziņām",
|
||||
"running": "Izpilda “{name}” mapē {folder}…"
|
||||
},
|
||||
"find_emails_from": "Atrast e-pastus no {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Atlasīt visas",
|
||||
"global_search": "Meklēt visā",
|
||||
"extend_selection": "Paplašināt atlasi uz leju / uz augšu",
|
||||
"accessibility_panel": "Atvērt pieejamības opcijas"
|
||||
"accessibility_panel": "Atvērt pieejamības opcijas",
|
||||
"focus_notification": "Pāriet uz jaunāko paziņojumu"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Izvērst/sairt sarunu",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Дүрмүүдийг удирдах",
|
||||
"senders_count": "{count, plural, one {# илгээгч} other {# илгээгч}}",
|
||||
"cross_account": "Нэг бүртгэлийн захиануудыг сонгоно уу",
|
||||
"opaque_hint": "Таны шүүлтүүрийг гараар засварласан байна. Шүүлтүүрийн тохиргоог нээнэ үү"
,
|
||||
"loading": "Дүрмүүдийг ачаалж байна…",
|
||||
"load_failed": "Дүрмүүдийг ачаалж чадсангүй",
|
||||
"none": "Одоогоор дүрэм алга",
|
||||
"new_mail_only": "Зөвхөн шинэ мессежүүдэд",
|
||||
"running": "{folder} дээр \"{name}\"-г ажиллуулж байна…"
|
||||
"opaque_hint": "Таны шүүлтүүрийг гараар засварласан байна. Шүүлтүүрийн тохиргоог нээнэ үү"
,
|
||||
"loading": "Дүрмүүдийг ачаалж байна…",
|
||||
"load_failed": "Дүрмүүдийг ачаалж чадсангүй",
|
||||
"none": "Одоогоор дүрэм алга",
|
||||
"new_mail_only": "Зөвхөн шинэ мессежүүдэд",
|
||||
"running": "{folder} дээр \"{name}\"-г ажиллуулж байна…"
|
||||
},
|
||||
"find_emails_from": "{name}-с ирсэн имэйлүүдийг хайх"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Бүгдийг сонго",
|
||||
"global_search": "Бүгдийг хайх",
|
||||
"extend_selection": "Сонголтыг доош / дээш өргөтгөх",
|
||||
"accessibility_panel": "Хүртээмжийн сонголтуудыг нээх"
|
||||
"accessibility_panel": "Хүртээмжийн сонголтуудыг нээх",
|
||||
"focus_notification": "Хамгийн сүүлийн мэдэгдэл рүү очих"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Хэлхээсийг дэлгэх/хумих",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Administrer regler",
|
||||
"senders_count": "{count, plural, one {# avsender} other {# avsendere}}",
|
||||
"cross_account": "Velg meldinger fra én konto",
|
||||
"opaque_hint": "Filtrene dine er redigert for hånd. Åpne filterinnstillingene"
,
|
||||
"loading": "Laster inn regler…",
|
||||
"load_failed": "Kunne ikke laste inn reglene",
|
||||
"none": "Ingen regler ennå",
|
||||
"new_mail_only": "Bare for nye meldinger",
|
||||
"running": "Kjører «{name}» på {folder}…"
|
||||
"opaque_hint": "Filtrene dine er redigert for hånd. Åpne filterinnstillingene"
,
|
||||
"loading": "Laster inn regler…",
|
||||
"load_failed": "Kunne ikke laste inn reglene",
|
||||
"none": "Ingen regler ennå",
|
||||
"new_mail_only": "Bare for nye meldinger",
|
||||
"running": "Kjører «{name}» på {folder}…"
|
||||
},
|
||||
"find_emails_from": "Finn e-poster fra {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Velg alle",
|
||||
"global_search": "Søk i alt",
|
||||
"extend_selection": "Utvid markeringen ned / opp",
|
||||
"accessibility_panel": "Åpne alternativer for tilgjengelighet"
|
||||
"accessibility_panel": "Åpne alternativer for tilgjengelighet",
|
||||
"focus_notification": "Gå til det nyeste varselet"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Utvid eller fold sammen tråden",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Regels beheren",
|
||||
"senders_count": "{count, plural, one {# afzender} other {# afzenders}}",
|
||||
"cross_account": "Selecteer berichten uit één account",
|
||||
"opaque_hint": "Je filters zijn met de hand bewerkt. Open de filterinstellingen"
,
|
||||
"loading": "Regels laden…",
|
||||
"load_failed": "De regels konden niet worden geladen",
|
||||
"none": "Nog geen regels",
|
||||
"new_mail_only": "Alleen voor nieuwe berichten",
|
||||
"running": "\"{name}\" wordt uitgevoerd op {folder}…"
|
||||
"opaque_hint": "Je filters zijn met de hand bewerkt. Open de filterinstellingen"
,
|
||||
"loading": "Regels laden…",
|
||||
"load_failed": "De regels konden niet worden geladen",
|
||||
"none": "Nog geen regels",
|
||||
"new_mail_only": "Alleen voor nieuwe berichten",
|
||||
"running": "\"{name}\" wordt uitgevoerd op {folder}…"
|
||||
},
|
||||
"find_emails_from": "E-mails van {name} zoeken"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Alles selecteren",
|
||||
"global_search": "Alles doorzoeken",
|
||||
"extend_selection": "Selectie omlaag / omhoog uitbreiden",
|
||||
"accessibility_panel": "Toegankelijkheidsopties openen"
|
||||
"accessibility_panel": "Toegankelijkheidsopties openen",
|
||||
"focus_notification": "Naar de nieuwste melding gaan"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Gesprek uitklappen/inklappen",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Zarządzaj regułami",
|
||||
"senders_count": "{count, plural, one {# nadawcy} few {# nadawców} many {# nadawców} other {# nadawcy}}",
|
||||
"cross_account": "Wybierz wiadomości z jednego konta",
|
||||
"opaque_hint": "Twoje filtry zostały edytowane ręcznie. Otwórz ustawienia filtrów"
,
|
||||
"loading": "Wczytywanie reguł…",
|
||||
"load_failed": "Nie udało się wczytać reguł",
|
||||
"none": "Brak reguł",
|
||||
"new_mail_only": "Tylko dla nowych wiadomości",
|
||||
"running": "Uruchamianie „{name}” w folderze {folder}…"
|
||||
"opaque_hint": "Twoje filtry zostały edytowane ręcznie. Otwórz ustawienia filtrów"
,
|
||||
"loading": "Wczytywanie reguł…",
|
||||
"load_failed": "Nie udało się wczytać reguł",
|
||||
"none": "Brak reguł",
|
||||
"new_mail_only": "Tylko dla nowych wiadomości",
|
||||
"running": "Uruchamianie „{name}” w folderze {folder}…"
|
||||
},
|
||||
"find_emails_from": "Znajdź e-maile od {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Zaznacz wszystko",
|
||||
"global_search": "Szukaj wszędzie",
|
||||
"extend_selection": "Rozszerz zaznaczenie w dół / w górę",
|
||||
"accessibility_panel": "Otwórz opcje dostępności"
|
||||
"accessibility_panel": "Otwórz opcje dostępności",
|
||||
"focus_notification": "Przejdź do najnowszego powiadomienia"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Rozwiń/zwiń wątek",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Gerenciar regras",
|
||||
"senders_count": "{count, plural, one {# remetente} other {# remetentes}}",
|
||||
"cross_account": "Selecione mensagens de uma única conta",
|
||||
"opaque_hint": "Seus filtros foram editados manualmente. Abra as configurações de filtros"
,
|
||||
"loading": "A carregar regras…",
|
||||
"load_failed": "Não foi possível carregar as regras",
|
||||
"none": "Ainda não há regras",
|
||||
"new_mail_only": "Apenas para mensagens novas",
|
||||
"running": "A executar \"{name}\" em {folder}…"
|
||||
"opaque_hint": "Seus filtros foram editados manualmente. Abra as configurações de filtros"
,
|
||||
"loading": "A carregar regras…",
|
||||
"load_failed": "Não foi possível carregar as regras",
|
||||
"none": "Ainda não há regras",
|
||||
"new_mail_only": "Apenas para mensagens novas",
|
||||
"running": "A executar \"{name}\" em {folder}…"
|
||||
},
|
||||
"find_emails_from": "Encontrar e-mails de {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Selecionar todos",
|
||||
"global_search": "Pesquisar em tudo",
|
||||
"extend_selection": "Expandir a seleção para baixo / cima",
|
||||
"accessibility_panel": "Abrir as opções de acessibilidade"
|
||||
"accessibility_panel": "Abrir as opções de acessibilidade",
|
||||
"focus_notification": "Ir para a notificação mais recente"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Expandir/recolher conversa",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Gestionați regulile",
|
||||
"senders_count": "{count, plural, one {# expeditor} few {# expeditori} other {# de expeditori}}",
|
||||
"cross_account": "Selectați mesaje dintr-un singur cont",
|
||||
"opaque_hint": "Filtrele dvs. au fost editate manual. Deschideți setările filtrelor"
,
|
||||
"loading": "Se încarcă regulile…",
|
||||
"load_failed": "Regulile nu au putut fi încărcate",
|
||||
"none": "Nicio regulă încă",
|
||||
"new_mail_only": "Doar pentru mesajele noi",
|
||||
"running": "Se rulează „{name}” în {folder}…"
|
||||
"opaque_hint": "Filtrele dvs. au fost editate manual. Deschideți setările filtrelor"
,
|
||||
"loading": "Se încarcă regulile…",
|
||||
"load_failed": "Regulile nu au putut fi încărcate",
|
||||
"none": "Nicio regulă încă",
|
||||
"new_mail_only": "Doar pentru mesajele noi",
|
||||
"running": "Se rulează „{name}” în {folder}…"
|
||||
},
|
||||
"find_emails_from": "Găsește e-mailurile de la {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Selectează tot",
|
||||
"global_search": "Caută în tot",
|
||||
"extend_selection": "Extinde selecția în jos / în sus",
|
||||
"accessibility_panel": "Deschide opțiunile de accesibilitate"
|
||||
"accessibility_panel": "Deschide opțiunile de accesibilitate",
|
||||
"focus_notification": "Mergi la cea mai recentă notificare"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Extindeți/reduceți firul de discuție",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Управление правилами",
|
||||
"senders_count": "{count, plural, one {# отправителя} few {# отправителей} many {# отправителей} other {# отправителя}}",
|
||||
"cross_account": "Выберите письма из одной учётной записи",
|
||||
"opaque_hint": "Ваши фильтры отредактированы вручную. Откройте настройки фильтров"
,
|
||||
"loading": "Загрузка правил…",
|
||||
"load_failed": "Не удалось загрузить правила",
|
||||
"none": "Правил пока нет",
|
||||
"new_mail_only": "Только для новых писем",
|
||||
"running": "Выполняется «{name}» в папке {folder}…"
|
||||
"opaque_hint": "Ваши фильтры отредактированы вручную. Откройте настройки фильтров"
,
|
||||
"loading": "Загрузка правил…",
|
||||
"load_failed": "Не удалось загрузить правила",
|
||||
"none": "Правил пока нет",
|
||||
"new_mail_only": "Только для новых писем",
|
||||
"running": "Выполняется «{name}» в папке {folder}…"
|
||||
},
|
||||
"find_emails_from": "Найти письма от {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Выбрать все",
|
||||
"global_search": "Искать везде",
|
||||
"extend_selection": "Расширить выделение вниз / вверх",
|
||||
"accessibility_panel": "Открыть параметры специальных возможностей"
|
||||
"accessibility_panel": "Открыть параметры специальных возможностей",
|
||||
"focus_notification": "Перейти к последнему уведомлению"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Развернуть/свернуть цепочку",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Spravovať pravidlá",
|
||||
"senders_count": "{count, plural, one {# odosielateľa} few {# odosielateľov} many {# odosielateľa} other {# odosielateľov}}",
|
||||
"cross_account": "Vyberte správy z jedného účtu",
|
||||
"opaque_hint": "Vaše filtre boli upravené ručne. Otvorte nastavenia filtrov"
,
|
||||
"loading": "Načítavajú sa pravidlá…",
|
||||
"load_failed": "Pravidlá sa nepodarilo načítať",
|
||||
"none": "Zatiaľ žiadne pravidlá",
|
||||
"new_mail_only": "Len pre nové správy",
|
||||
"running": "Spúšťa sa „{name}“ v priečinku {folder}…"
|
||||
"opaque_hint": "Vaše filtre boli upravené ručne. Otvorte nastavenia filtrov"
,
|
||||
"loading": "Načítavajú sa pravidlá…",
|
||||
"load_failed": "Pravidlá sa nepodarilo načítať",
|
||||
"none": "Zatiaľ žiadne pravidlá",
|
||||
"new_mail_only": "Len pre nové správy",
|
||||
"running": "Spúšťa sa „{name}“ v priečinku {folder}…"
|
||||
},
|
||||
"find_emails_from": "Nájsť e-maily od {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Vybrať všetko",
|
||||
"global_search": "Hľadať všade",
|
||||
"extend_selection": "Rozšíriť výber nadol / nahor",
|
||||
"accessibility_panel": "Otvoriť možnosti prístupnosti"
|
||||
"accessibility_panel": "Otvoriť možnosti prístupnosti",
|
||||
"focus_notification": "Prejsť na najnovšie upozornenie"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Rozbaliť/zbaliť vlákno",
|
||||
|
||||
@@ -776,7 +776,8 @@
|
||||
"select_all": "เลือกทั้งหมด",
|
||||
"global_search": "ค้นหาทุกรายการ",
|
||||
"extend_selection": "ขยายการเลือกลง / ขึ้น",
|
||||
"accessibility_panel": "เปิดตัวเลือกการเข้าถึง"
|
||||
"accessibility_panel": "เปิดตัวเลือกการเข้าถึง",
|
||||
"focus_notification": "ไปที่การแจ้งเตือนล่าสุด"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "ขยาย/ย่อการสนทนา",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Kuralları yönet",
|
||||
"senders_count": "{count, plural, one {# gönderen} other {# gönderen}}",
|
||||
"cross_account": "Tek bir hesaptan iletiler seçin",
|
||||
"opaque_hint": "Filtreleriniz elle düzenlenmiş. Filtre ayarlarını açın"
,
|
||||
"loading": "Kurallar yükleniyor…",
|
||||
"load_failed": "Kurallar yüklenemedi",
|
||||
"none": "Henüz kural yok",
|
||||
"new_mail_only": "Yalnızca yeni iletiler için",
|
||||
"running": "\"{name}\" {folder} klasöründe çalıştırılıyor…"
|
||||
"opaque_hint": "Filtreleriniz elle düzenlenmiş. Filtre ayarlarını açın"
,
|
||||
"loading": "Kurallar yükleniyor…",
|
||||
"load_failed": "Kurallar yüklenemedi",
|
||||
"none": "Henüz kural yok",
|
||||
"new_mail_only": "Yalnızca yeni iletiler için",
|
||||
"running": "\"{name}\" {folder} klasöründe çalıştırılıyor…"
|
||||
},
|
||||
"find_emails_from": "{name} adlı kişiden gelen e-postaları bul"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Tümünü seç",
|
||||
"global_search": "Her yerde ara",
|
||||
"extend_selection": "Seçimi aşağı / yukarı genişlet",
|
||||
"accessibility_panel": "Erişilebilirlik seçeneklerini aç"
|
||||
"accessibility_panel": "Erişilebilirlik seçeneklerini aç",
|
||||
"focus_notification": "En son bildirime git"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "İleti dizisini genişlet/daralt",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "Керувати правилами",
|
||||
"senders_count": "{count, plural, one {# відправника} few {# відправників} many {# відправників} other {# відправника}}",
|
||||
"cross_account": "Виберіть листи з одного облікового запису",
|
||||
"opaque_hint": "Ваші фільтри відредаговано вручну. Відкрийте налаштування фільтрів"
,
|
||||
"loading": "Завантаження правил…",
|
||||
"load_failed": "Не вдалося завантажити правила",
|
||||
"none": "Правил поки немає",
|
||||
"new_mail_only": "Лише для нових листів",
|
||||
"running": "Виконується «{name}» у теці {folder}…"
|
||||
"opaque_hint": "Ваші фільтри відредаговано вручну. Відкрийте налаштування фільтрів"
,
|
||||
"loading": "Завантаження правил…",
|
||||
"load_failed": "Не вдалося завантажити правила",
|
||||
"none": "Правил поки немає",
|
||||
"new_mail_only": "Лише для нових листів",
|
||||
"running": "Виконується «{name}» у теці {folder}…"
|
||||
},
|
||||
"find_emails_from": "Знайти листи від {name}"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "Вибрати все",
|
||||
"global_search": "Шукати скрізь",
|
||||
"extend_selection": "Розширити виділення вниз / вгору",
|
||||
"accessibility_panel": "Відкрити параметри доступності"
|
||||
"accessibility_panel": "Відкрити параметри доступності",
|
||||
"focus_notification": "Перейти до останнього сповіщення"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "Розгорнути/згорнути ланцюжок",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "管理規則",
|
||||
"senders_count": "{count, plural, other {# 位寄件者}}",
|
||||
"cross_account": "請選取同一個帳號中的郵件",
|
||||
"opaque_hint": "你的篩選規則曾被手動編輯。請開啟篩選規則設定"
,
|
||||
"loading": "正在載入規則…",
|
||||
"load_failed": "無法載入規則",
|
||||
"none": "尚無規則",
|
||||
"new_mail_only": "僅限新郵件",
|
||||
"running": "正在 {folder} 中執行「{name}」…"
|
||||
"opaque_hint": "你的篩選規則曾被手動編輯。請開啟篩選規則設定"
,
|
||||
"loading": "正在載入規則…",
|
||||
"load_failed": "無法載入規則",
|
||||
"none": "尚無規則",
|
||||
"new_mail_only": "僅限新郵件",
|
||||
"running": "正在 {folder} 中執行「{name}」…"
|
||||
},
|
||||
"find_emails_from": "尋找來自 {name} 的郵件"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "全部選取",
|
||||
"global_search": "全域搜尋",
|
||||
"extend_selection": "向下 / 向上擴展選取",
|
||||
"accessibility_panel": "開啟無障礙選項"
|
||||
"accessibility_panel": "開啟無障礙選項",
|
||||
"focus_notification": "前往最新通知"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "展開/收合對話串",
|
||||
|
||||
@@ -3400,12 +3400,12 @@
|
||||
"manage": "管理规则",
|
||||
"senders_count": "{count, plural, other {# 个发件人}}",
|
||||
"cross_account": "请选择同一账户中的邮件",
|
||||
"opaque_hint": "你的过滤器已被手动编辑。请打开过滤器设置"␍,
|
||||
"loading": "正在加载规则…",
|
||||
"load_failed": "无法加载规则",
|
||||
"none": "暂无规则",
|
||||
"new_mail_only": "仅限新邮件",
|
||||
"running": "正在 {folder} 中运行“{name}”…"
|
||||
"opaque_hint": "你的过滤器已被手动编辑。请打开过滤器设置"␍,
|
||||
"loading": "正在加载规则…",
|
||||
"load_failed": "无法加载规则",
|
||||
"none": "暂无规则",
|
||||
"new_mail_only": "仅限新邮件",
|
||||
"running": "正在 {folder} 中运行“{name}”…"
|
||||
},
|
||||
"find_emails_from": "查找来自 {name} 的邮件"
|
||||
},
|
||||
@@ -3496,7 +3496,8 @@
|
||||
"select_all": "全选",
|
||||
"global_search": "全局搜索",
|
||||
"extend_selection": "向下 / 向上扩展选择",
|
||||
"accessibility_panel": "打开无障碍选项"
|
||||
"accessibility_panel": "打开无障碍选项",
|
||||
"focus_notification": "转到最新通知"
|
||||
},
|
||||
"threads": {
|
||||
"expand_collapse": "展开/折叠会话",
|
||||
|
||||
Reference in New Issue
Block a user