diff --git a/components/mail/__tests__/mail-app-return-to-list.test.tsx b/components/mail/__tests__/mail-app-return-to-list.test.tsx
index 6f64a44b3..84b280902 100644
--- a/components/mail/__tests__/mail-app-return-to-list.test.tsx
+++ b/components/mail/__tests__/mail-app-return-to-list.test.tsx
@@ -273,6 +273,75 @@ describe.each([
});
});
+// With the list beside the reading pane (split, horizontal) the setting,
+// while nobody has changed it, opens the next message instead, as Outlook
+// does. A choice the user made wins, on every layout and device.
+describe('Archive with the list beside the reading pane', () => {
+ beforeEach(() => {
+ useSettingsStore.setState({ interfaceLayout: 'default', mailLayout: 'split', explicitSettings: [] } as never);
+ useEmailStore.setState({ listRows: null } as never);
+ });
+
+ it('opens the next message while the setting is untouched', async () => {
+ render();
+ fireEvent.click(await screen.findByText('stub archive', {}, { timeout: 5000 }));
+ await waitFor(() => expect(client.moveEmail).toHaveBeenCalledWith('m1', 'archive', undefined));
+ await waitFor(() => expect(selectedId()).toBe('m2'));
+ });
+
+ it('opens the next row in the order the list shows', async () => {
+ useEmailStore.setState({
+ listRows: [{ key: 'm1', members: ['m1'] }, { key: 'm3', members: ['m3'] }, { key: 'm2', members: ['m2'] }],
+ } as never);
+ render();
+ fireEvent.click(await screen.findByText('stub archive', {}, { timeout: 5000 }));
+ await waitFor(() => expect(client.moveEmail).toHaveBeenCalledWith('m1', 'archive', undefined));
+ await waitFor(() => expect(selectedId()).toBe('m3'));
+ expect(opened).not.toContain('m2');
+ });
+
+ it('goes back to the list when the user switched the setting on', async () => {
+ useSettingsStore.setState({ returnToListAfterAction: true, explicitSettings: ['returnToListAfterAction'] } as never);
+ render();
+ fireEvent.click(await screen.findByText('stub archive', {}, { timeout: 5000 }));
+ await waitFor(() => expect(useEmailStore.getState().emails.map((e) => e.id)).toEqual(['m2', 'm3']));
+ expect(selectedId()).toBeNull();
+ expect(opened).not.toContain('m2');
+ });
+
+ it('opens the archived message again on Undo', async () => {
+ client.restoreEmails = vi.fn().mockResolvedValue(undefined);
+ useEmailStore.setState({
+ refreshCurrentMailbox: vi.fn(async () => { useEmailStore.setState({ emails: inbox() } as never); }),
+ } as never);
+ render();
+ fireEvent.click(await screen.findByText('stub archive', {}, { timeout: 5000 }));
+ await waitFor(() => expect(selectedId()).toBe('m2'));
+ const archived = await waitFor(() => {
+ const found = useToastStore.getState().toasts.find((toast) => toast.title === 'notifications.email_archived');
+ expect(found?.action).toBeTruthy();
+ return found!;
+ });
+ act(() => { archived.action!.onClick(); });
+ await waitFor(() => expect(client.restoreEmails).toHaveBeenCalled());
+ await waitFor(() => expect(selectedId()).toBe('m1'));
+ });
+});
+
+describe('Delete with the list beside the reading pane', () => {
+ beforeEach(() => {
+ useSettingsStore.setState({ interfaceLayout: 'default', mailLayout: 'horizontal', explicitSettings: [] } as never);
+ useEmailStore.setState({ listRows: null } as never);
+ });
+
+ it('opens the next message while the setting is untouched', async () => {
+ render();
+ fireEvent.click(await screen.findByText('stub delete', {}, { timeout: 5000 }));
+ await waitFor(() => expect(client.moveToTrash).toHaveBeenCalled());
+ await waitFor(() => expect(selectedId()).toBe('m2'));
+ });
+});
+
describe('A list collapsed under an open message (focused layout)', () => {
const list = () => screen.getByText('message list').closest('section')!;
diff --git a/components/mail/mail-app.tsx b/components/mail/mail-app.tsx
index d3275629a..93e103158 100644
--- a/components/mail/mail-app.tsx
+++ b/components/mail/mail-app.tsx
@@ -81,6 +81,7 @@ import { cn, formatDateTime, getMailboxPath } from "@/lib/utils";
import { localizeMailboxName } from "@/lib/mailbox-label";
import { KEYWORD_PREFIX, KEYWORD_PREFIX_LEGACY, emailKeyFor, groupEmailsByThread, threadKeyFor } from "@/lib/thread-utils";
import { stepListEmail } from "@/lib/list-step";
+import { listBesideReader, returnToListAfterAction } from "@/lib/return-to-list";
import { resolveThreadRoute } from "@/lib/thread-routing";
import {
ErrorBoundary,
@@ -3341,12 +3342,41 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
// holds (a quick filter dropped it) stays selected: the store finds it
// through the selection (#695), and with no row to go on from it opens
// nothing after it anyway. (#1458)
+ //
+ // Left alone, the setting follows the layout (lib/return-to-list): with the
+ // list beside the reading pane the next message opens instead, as in
+ // Outlook. With the conversation in the reading pane that is the next
+ // conversation down the list (the one above at the end), as its row opens it.
+ const returnsToList = () => returnToListAfterAction(
+ !fullscreenReading && listBesideReader({ mailLayout, interfaceLayout, isMobile, isTablet }),
+ );
const leaveIfOpen = (email: Email) => {
- const { selectedEmail: open, emails: rows } = useEmailStore.getState();
+ const { selectedEmail: open, emails: rows, listRows } = useEmailStore.getState();
const key = emailKeyFor(email);
if (!open || emailKeyFor(open) !== key || (mvShell && cursorOnly)) return;
if (!rows.some((row) => emailKeyFor(row) === key)) return;
- if (useSettingsStore.getState().returnToListAfterAction) handleMobileBack();
+ if (returnsToList()) {
+ handleMobileBack();
+ return;
+ }
+ if (!paneConversationView || !listRows) return;
+ const below = stepListEmail(rows, key, 1, listRows);
+ const next = below && emailKeyFor(below) !== key ? below : stepListEmail(rows, key, -1, listRows);
+ if (!next || emailKeyFor(next) === key || threadKeyFor(next) === threadKeyFor(email)) return;
+ handleMobileBack();
+ void handleEmailSelect(next);
+ };
+ // Undo puts back the message that was open, and opens it again, where it
+ // was open in the reading pane. Phones stay in the list.
+ const reopenEmailRef = useRef<((email: Email) => Promise) | null>(null);
+ const reopenAfterUndo = (email: Email) => {
+ const { selectedEmail: open } = useEmailStore.getState();
+ if (isMobile || !open || emailKeyFor(open) !== emailKeyFor(email)) return undefined;
+ const key = emailKeyFor(email);
+ return () => {
+ const restored = useEmailStore.getState().emails.find((e) => emailKeyFor(e) === key);
+ if (restored) void reopenEmailRef.current?.(restored);
+ };
};
const handleDelete = async (emailToDelete: Email | null = selectedEmail) => {
@@ -3390,6 +3420,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
return;
}
+ const reopen = reopenAfterUndo(emailToDelete);
leaveIfOpen(emailToDelete);
// The store's delete reads the "Delete action" setting: move to the
@@ -3398,7 +3429,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
try {
// false: a plugin stopped it and said why, so no "deleted" here.
if (await deleteEmail(client, emailToDelete.id, isInTrash, emailKeyFor(emailToDelete))) {
- toastWithUndo(t('notifications.email_deleted'), undoMoveAction(client, restore, undo));
+ toastWithUndo(t('notifications.email_deleted'), undoMoveAction(client, restore, undo, undefined, reopen));
}
} catch (error) {
console.error("Failed to delete email:", error);
@@ -3498,6 +3529,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
}
let restore: EmailRestoreBatch[] | null = null;
+ const reopen = reopenAfterUndo(emailToArchive);
leaveIfOpen(emailToArchive);
const archived = await moveThreadToMailbox(client, emailToArchive.id, destination.id, emailKeyFor(emailToArchive), (batches) => { restore = batches; });
if (!archived) return;
@@ -3509,7 +3541,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
setConversationEmails([]);
}
- toastWithUndo(t('notifications.email_archived'), undoMoveAction(client, restore, undo));
+ toastWithUndo(t('notifications.email_archived'), undoMoveAction(client, restore, undo, undefined, reopen));
void refreshMailboxes();
} catch (error) {
console.error("Failed to archive email:", error);
@@ -5044,6 +5076,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
};
pluginOpenEmailRef.current = handleEmailSelect;
+ reopenEmailRef.current = handleEmailSelect;
// Handle back navigation from viewer on mobile.
// Reset to list state directly. We can't just call window.history.back()
@@ -6099,7 +6132,7 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
// Marking the open message unread returns to the list
// (Gmail-style, gated on returnToListAfterAction). Staying
// in the reading pane would just re-mark it read on view.
- if (!read && useSettingsStore.getState().returnToListAfterAction) {
+ if (!read && returnsToList()) {
handleMobileBack();
}
}
diff --git a/components/settings/accessibility-settings.tsx b/components/settings/accessibility-settings.tsx
index 3f6f606e2..515d9ea2e 100644
--- a/components/settings/accessibility-settings.tsx
+++ b/components/settings/accessibility-settings.tsx
@@ -12,6 +12,7 @@ import { useNoThirdPartyTraffic } from '@/hooks/use-third-party-mode';
import { openKeyboardShortcuts } from '@/lib/app-commands';
import { voicesForLocale } from '@/lib/read-aloud';
import { useSpeechVoices } from '@/hooks/use-read-aloud';
+import { useReturnToListAfterAction } from '@/hooks/use-return-to-list';
import { NOTIFICATION_SOUNDS, playNotificationSound, type NotificationSoundChoice } from '@/lib/notification-sound';
import {
ACCESSIBILITY_KEYS,
@@ -73,6 +74,8 @@ export function AccessibilitySettings() {
const [resetDone, setResetDone] = useState(false);
const locale = useLocale();
const speechVoices = useSpeechVoices();
+ // As it applies in this layout: left alone, it follows the layout.
+ const returnToList = useReturnToListAfterAction();
const toastMin = getRestriction('toastDuration')?.min;
const allowsValue = (key: string, value: unknown) =>
@@ -502,7 +505,7 @@ export function AccessibilitySettings() {
)}
- set('returnToListAfterAction', checked)} />
+ set('returnToListAfterAction', checked)} />
diff --git a/components/settings/reading-settings.tsx b/components/settings/reading-settings.tsx
index 0b5cf8222..3f9518ce5 100644
--- a/components/settings/reading-settings.tsx
+++ b/components/settings/reading-settings.tsx
@@ -11,6 +11,7 @@ import { usePolicyStore } from '@/stores/policy-store';
import { useContactStore } from '@/stores/contact-store';
import { useAuthStore } from '@/stores/auth-store';
import { useRemoteContentBlockedByOrg } from '@/hooks/use-third-party-mode';
+import { useReturnToListAfterAction } from '@/hooks/use-return-to-list';
/**
* The Reading page: the open message. Opening it, how its body is drawn,
@@ -26,12 +27,14 @@ export function ReadingSettings() {
const tLock = useTranslations('remote_content_lock');
const t = useTranslations('settings.email_behavior');
const tPage = useTranslations('settings.reading_page');
+ const tPane = useTranslations('conversation_pane');
+ // As it applies in this layout: left alone, it follows the layout.
+ const returnToList = useReturnToListAfterAction();
const [showTrustedModal, setShowTrustedModal] = useState(false);
const { isSettingLocked, isSettingHidden, isFeatureEnabled } = usePolicyStore();
const {
markAsReadDelay,
- returnToListAfterAction,
mailAttachmentAction,
attachmentPosition,
hideInlineImageAttachments,
@@ -78,9 +81,14 @@ export function ReadingSettings() {
)}
-
+
updateSetting('returnToListAfterAction', checked)}
/>
diff --git a/hooks/use-return-to-list.ts b/hooks/use-return-to-list.ts
new file mode 100644
index 000000000..321dfeee0
--- /dev/null
+++ b/hooks/use-return-to-list.ts
@@ -0,0 +1,28 @@
+"use client";
+
+import { useSettingsStore } from "@/stores/settings-store";
+import { usePolicyStore } from "@/stores/policy-store";
+import { useDeviceDetection } from "@/hooks/use-media-query";
+import { effectiveReturnToList, listBesideReader, returnToListSetByPolicy } from "@/lib/return-to-list";
+
+/**
+ * The "Return to list after…" switch as it applies on this device and in this
+ * layout (lib/return-to-list), and whether that comes from the layout because
+ * nobody has set it yet.
+ */
+export function useReturnToListAfterAction(): { checked: boolean; followsLayout: boolean } {
+ const { isMobile, isTablet } = useDeviceDetection();
+ const value = useSettingsStore((s) => s.returnToListAfterAction);
+ const explicitSettings = useSettingsStore((s) => s.explicitSettings);
+ const mailLayout = useSettingsStore((s) => s.mailLayout);
+ const interfaceLayout = useSettingsStore((s) => s.interfaceLayout);
+ const simpleMode = useSettingsStore((s) => s.simpleMode);
+ // Re-read when the policy arrives or changes.
+ usePolicyStore((s) => s.policy);
+ const policySet = returnToListSetByPolicy();
+ const besideReader = listBesideReader({ mailLayout, interfaceLayout, simpleMode, isMobile, isTablet });
+ return {
+ checked: effectiveReturnToList({ returnToListAfterAction: value, explicitSettings }, besideReader, policySet),
+ followsLayout: !policySet && !explicitSettings.includes("returnToListAfterAction"),
+ };
+}
diff --git a/lib/__tests__/return-to-list.test.ts b/lib/__tests__/return-to-list.test.ts
new file mode 100644
index 000000000..a19b16d2b
--- /dev/null
+++ b/lib/__tests__/return-to-list.test.ts
@@ -0,0 +1,41 @@
+import { describe, it, expect } from 'vitest';
+import { effectiveReturnToList, listBesideReader } from '../return-to-list';
+
+// "Return to list after…": left alone it follows the layout (next message
+// with the list beside the reader, back to the list elsewhere); set by the
+// user or the admin, it decides everywhere.
+
+const untouched = { returnToListAfterAction: true, explicitSettings: [] as string[] };
+const chosen = (value: boolean) => ({ returnToListAfterAction: value, explicitSettings: ['returnToListAfterAction'] });
+
+describe('listBesideReader', () => {
+ const desktop = { isMobile: false, isTablet: false, interfaceLayout: 'default' as const };
+ it('is true for the split and horizontal layouts on a desktop', () => {
+ expect(listBesideReader({ ...desktop, mailLayout: 'split' })).toBe(true);
+ expect(listBesideReader({ ...desktop, mailLayout: 'horizontal' })).toBe(true);
+ });
+ it('is false where the message takes the list’s place', () => {
+ expect(listBesideReader({ ...desktop, mailLayout: 'focus' })).toBe(false);
+ expect(listBesideReader({ ...desktop, mailLayout: 'split', interfaceLayout: 'mountain-view' })).toBe(false);
+ expect(listBesideReader({ ...desktop, mailLayout: 'split', simpleMode: true })).toBe(false);
+ expect(listBesideReader({ ...desktop, mailLayout: 'split', isMobile: true })).toBe(false);
+ expect(listBesideReader({ ...desktop, mailLayout: 'split', isTablet: true })).toBe(false);
+ });
+});
+
+describe('effectiveReturnToList', () => {
+ it('opens the next message beside the reader while nobody set it', () => {
+ expect(effectiveReturnToList(untouched, true, false)).toBe(false);
+ });
+ it('goes back to the list elsewhere while nobody set it', () => {
+ expect(effectiveReturnToList(untouched, false, false)).toBe(true);
+ });
+ it('follows the user’s choice on every layout', () => {
+ expect(effectiveReturnToList(chosen(true), true, false)).toBe(true);
+ expect(effectiveReturnToList(chosen(false), false, false)).toBe(false);
+ });
+ it('follows an admin preset or lock', () => {
+ expect(effectiveReturnToList(untouched, true, true)).toBe(true);
+ expect(effectiveReturnToList({ ...untouched, returnToListAfterAction: false }, false, true)).toBe(false);
+ });
+});
diff --git a/lib/email-action-toast.ts b/lib/email-action-toast.ts
index 663a3b417..02d987771 100644
--- a/lib/email-action-toast.ts
+++ b/lib/email-action-toast.ts
@@ -166,13 +166,14 @@ export async function setSelectionTagWithUndo(
*
* `receipts` (filled while the move runs) name the messages it took to
* another account: Undo moves those back, the same way, into the folders
- * their restore points name (undoMove).
+ * their restore points name (undoMove). `onUndone` runs once they are back.
*/
export function undoMoveAction(
client: IJMAPClient | null | undefined,
batches: EmailRestoreBatch[] | null | undefined,
labels: UndoLabels,
receipts?: CrossAccountMoveReceipt[],
+ onUndone?: () => void,
): UndoToastAction | undefined {
if (!client || !batches || !batches.some(b => b.points.length > 0)) return undefined;
return {
@@ -183,6 +184,7 @@ export function undoMoveAction(
try {
await useEmailStore.getState().undoMove(client, batches, receipts ?? []);
toast.success(labels.done);
+ onUndone?.();
} catch (error) {
console.error("Failed to undo:", error);
toast.error(labels.failed);
diff --git a/lib/return-to-list.ts b/lib/return-to-list.ts
new file mode 100644
index 000000000..f33055bcb
--- /dev/null
+++ b/lib/return-to-list.ts
@@ -0,0 +1,50 @@
+import { effectiveMailLayout, useSettingsStore, type InterfaceLayout, type MailLayout } from '@/stores/settings-store';
+import { usePolicyStore } from '@/stores/policy-store';
+
+const KEY = 'returnToListAfterAction';
+
+/**
+ * Whether the message list and the reading pane are on screen side by side:
+ * the split and horizontal layouts on a desktop. Phones, tablets, the focused
+ * layout, Simple mode and Mountain View put the message in the list's place.
+ */
+export function listBesideReader(opts: {
+ mailLayout: MailLayout;
+ interfaceLayout: InterfaceLayout;
+ simpleMode?: boolean;
+ isMobile: boolean;
+ isTablet: boolean;
+}): boolean {
+ if (opts.isMobile || opts.isTablet) return false;
+ return effectiveMailLayout(opts.mailLayout, opts.interfaceLayout, opts.simpleMode) !== 'focus';
+}
+
+/**
+ * "Return to list after delete, archive, move or mark unread", as it applies
+ * here. Set by the user (on any device: the choice syncs) or by the admin
+ * policy, the setting decides. Left alone, it follows the layout: with the
+ * list beside the reading pane the next message opens, as in Outlook, so a
+ * folder is worked through with e, e, e; where the message takes the list's
+ * place it goes back to the list. Each device judges its own layout.
+ */
+export function effectiveReturnToList(
+ settings: { returnToListAfterAction: boolean; explicitSettings: readonly string[] },
+ besideReader: boolean,
+ policySet: boolean,
+): boolean {
+ if (policySet || settings.explicitSettings.includes(KEY)) return settings.returnToListAfterAction;
+ return besideReader ? false : settings.returnToListAfterAction;
+}
+
+/** Whether the admin policy presets or locks the setting. */
+export function returnToListSetByPolicy(): boolean {
+ const policy = usePolicyStore.getState();
+ const defaults = policy.policy?.defaults;
+ return (!!defaults && Object.prototype.hasOwnProperty.call(defaults, KEY)) || policy.isSettingLocked(KEY);
+}
+
+/** The setting as it applies now, read at the moment of the action. */
+export function returnToListAfterAction(besideReader: boolean): boolean {
+ return effectiveReturnToList(useSettingsStore.getState(), besideReader, returnToListSetByPolicy());
+}
+
diff --git a/locales/ar/common.json b/locales/ar/common.json
index b2bc4e274..8c8405c01 100644
--- a/locales/ar/common.json
+++ b/locales/ar/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "طي المحادثة: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, zero {عرض # رسالة أقدم} one {عرض رسالة أقدم واحدة} two {عرض رسالتين أقدم} few {عرض # رسائل أقدم} many {عرض # رسالة أقدم} other {عرض # رسالة أقدم}}"
+ "show_older": "{count, plural, zero {عرض # رسالة أقدم} one {عرض رسالة أقدم واحدة} two {عرض رسالتين أقدم} few {عرض # رسائل أقدم} many {عرض # رسالة أقدم} other {عرض # رسالة أقدم}}",
+ "return_to_list_follows_layout": "ما لم تغيّره، يتبع هذا التخطيط: متوقف عندما تكون القائمة والرسالة جنبًا إلى جنب، ومفعّل في غير ذلك."
},
"identities": {
"modal_title": "إدارة هويات الإرسال",
diff --git a/locales/ca/common.json b/locales/ca/common.json
index 40ad249c3..cafa38091 100644
--- a/locales/ca/common.json
+++ b/locales/ca/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Replega la conversa: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Mostra # missatge anterior} other {Mostra # missatges anteriors}}"
+ "show_older": "{count, plural, one {Mostra # missatge anterior} other {Mostra # missatges anteriors}}",
+ "return_to_list_follows_layout": "Mentre no ho canviïs, segueix el disseny: desactivat quan la llista i el missatge són l'un al costat de l'altre, activat en els altres casos."
},
"identities": {
"modal_title": "Gestiona les identitats d'enviament",
diff --git a/locales/cs/common.json b/locales/cs/common.json
index 8a997fe35..a5fcd86e4 100644
--- a/locales/cs/common.json
+++ b/locales/cs/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Sbalit konverzaci: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Zobrazit # starší zprávu} few {Zobrazit # starší zprávy} many {Zobrazit # starší zprávy} other {Zobrazit # starších zpráv}}"
+ "show_older": "{count, plural, one {Zobrazit # starší zprávu} few {Zobrazit # starší zprávy} many {Zobrazit # starší zprávy} other {Zobrazit # starších zpráv}}",
+ "return_to_list_follows_layout": "Dokud to nezměníte, řídí se to rozvržením: vypnuto, když jsou seznam a zpráva vedle sebe, jinak zapnuto."
},
"identities": {
"modal_title": "Správa identit odesílatele",
diff --git a/locales/da/common.json b/locales/da/common.json
index 34186500f..bf7e32cc4 100644
--- a/locales/da/common.json
+++ b/locales/da/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Skjul samtale: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Vis # ældre besked} other {Vis # ældre beskeder}}"
+ "show_older": "{count, plural, one {Vis # ældre besked} other {Vis # ældre beskeder}}",
+ "return_to_list_follows_layout": "Indtil du ændrer det, følger det layoutet: fra, når listen og beskeden står side om side, ellers til."
},
"identities": {
"modal_title": "Administrér afsenderidentiteter",
diff --git a/locales/de/common.json b/locales/de/common.json
index d59fe5f83..da7a123ff 100644
--- a/locales/de/common.json
+++ b/locales/de/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Konversation zuklappen: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {# ältere Nachricht anzeigen} other {# ältere Nachrichten anzeigen}}"
+ "show_older": "{count, plural, one {# ältere Nachricht anzeigen} other {# ältere Nachrichten anzeigen}}",
+ "return_to_list_follows_layout": "Solange Sie es nicht ändern, richtet sich das nach dem Layout: aus, wenn Liste und Nachricht nebeneinander stehen, sonst an."
},
"identities": {
"modal_title": "Sendeidentitäten verwalten",
diff --git a/locales/en/common.json b/locales/en/common.json
index ee5c9a417..bdc783836 100644
--- a/locales/en/common.json
+++ b/locales/en/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Collapse conversation: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Show # older message} other {Show # older messages}}"
+ "show_older": "{count, plural, one {Show # older message} other {Show # older messages}}",
+ "return_to_list_follows_layout": "Until you change it, this follows the layout: off when the list and the message are side by side, on otherwise."
},
"identities": {
"modal_title": "Manage sending identities",
diff --git a/locales/es/common.json b/locales/es/common.json
index 4f17170ac..e29fba479 100644
--- a/locales/es/common.json
+++ b/locales/es/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Contraer conversación: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Mostrar # mensaje anterior} other {Mostrar # mensajes anteriores}}"
+ "show_older": "{count, plural, one {Mostrar # mensaje anterior} other {Mostrar # mensajes anteriores}}",
+ "return_to_list_follows_layout": "Mientras no lo cambies, sigue el diseño: desactivado cuando la lista y el mensaje están uno al lado del otro, activado en los demás casos."
},
"identities": {
"modal_title": "Administrar Identidades de Envío",
diff --git a/locales/et/common.json b/locales/et/common.json
index 093b43f0a..b6230b0df 100644
--- a/locales/et/common.json
+++ b/locales/et/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Sulge vestlus: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Näita # vanemat sõnumit} other {Näita # vanemat sõnumit}}"
+ "show_older": "{count, plural, one {Näita # vanemat sõnumit} other {Näita # vanemat sõnumit}}",
+ "return_to_list_follows_layout": "Kuni te seda ei muuda, järgib see paigutust: väljas, kui loend ja sõnum on kõrvuti, muidu sees."
},
"identities": {
"modal_title": "Halda saatja identiteete",
diff --git a/locales/fa/common.json b/locales/fa/common.json
index 625dfe66a..8acc6a0dc 100644
--- a/locales/fa/common.json
+++ b/locales/fa/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "جمع کردن مکالمه: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {نمایش # پیام قدیمیتر} other {نمایش # پیام قدیمیتر}}"
+ "show_older": "{count, plural, one {نمایش # پیام قدیمیتر} other {نمایش # پیام قدیمیتر}}",
+ "return_to_list_follows_layout": "تا وقتی آن را تغییر ندهید، از چیدمان پیروی میکند: وقتی فهرست و پیام کنار هم هستند خاموش، در غیر این صورت روشن."
},
"identities": {
"modal_title": "مدیریت هویتهای ارسال",
diff --git a/locales/fr/common.json b/locales/fr/common.json
index dfb97587f..8fbf87d51 100644
--- a/locales/fr/common.json
+++ b/locales/fr/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Réduire la conversation: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Afficher # message plus ancien} other {Afficher # messages plus anciens}}"
+ "show_older": "{count, plural, one {Afficher # message plus ancien} other {Afficher # messages plus anciens}}",
+ "return_to_list_follows_layout": "Tant que vous ne le modifiez pas, ce réglage suit la disposition : désactivé quand la liste et le message sont côte à côte, activé sinon."
},
"identities": {
"modal_title": "Gérer les identités d'envoi",
diff --git a/locales/he/common.json b/locales/he/common.json
index 78173a829..9892d2813 100644
--- a/locales/he/common.json
+++ b/locales/he/common.json
@@ -3664,7 +3664,8 @@
"collapse_named": "כווץ את השיחה: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {הצגת הודעה ישנה אחת} two {הצגת שתי הודעות ישנות} other {הצגת # הודעות ישנות}}"
+ "show_older": "{count, plural, one {הצגת הודעה ישנה אחת} two {הצגת שתי הודעות ישנות} other {הצגת # הודעות ישנות}}",
+ "return_to_list_follows_layout": "כל עוד לא תשנו זאת, זה נקבע לפי הפריסה: כבוי כשהרשימה וההודעה זו לצד זו, ופועל בכל מצב אחר."
},
"identities": {
"modal_title": "ניהול זהויות שליחה",
diff --git a/locales/hu/common.json b/locales/hu/common.json
index 1b29ecf12..5d1e83f08 100644
--- a/locales/hu/common.json
+++ b/locales/hu/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Beszélgetés összecsukása: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {# régebbi üzenet megjelenítése} other {# régebbi üzenet megjelenítése}}"
+ "show_older": "{count, plural, one {# régebbi üzenet megjelenítése} other {# régebbi üzenet megjelenítése}}",
+ "return_to_list_follows_layout": "Amíg nem módosítja, az elrendezést követi: ki van kapcsolva, ha a lista és az üzenet egymás mellett van, egyébként be."
},
"identities": {
"modal_title": "Küldő azonosságok kezelése",
diff --git a/locales/it/common.json b/locales/it/common.json
index 557adfd78..d1e9d7bc0 100644
--- a/locales/it/common.json
+++ b/locales/it/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Comprimi conversazione: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Mostra # messaggio precedente} other {Mostra # messaggi precedenti}}"
+ "show_older": "{count, plural, one {Mostra # messaggio precedente} other {Mostra # messaggi precedenti}}",
+ "return_to_list_follows_layout": "Finché non lo modifichi, segue il layout: disattivato quando l'elenco e il messaggio sono affiancati, attivato negli altri casi."
},
"identities": {
"modal_title": "Gestisci identità di invio",
diff --git a/locales/ja/common.json b/locales/ja/common.json
index ed70f18de..1d5a322f4 100644
--- a/locales/ja/common.json
+++ b/locales/ja/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "会話を折りたたむ: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, other {以前のメッセージを # 件表示}}"
+ "show_older": "{count, plural, other {以前のメッセージを # 件表示}}",
+ "return_to_list_follows_layout": "変更するまでは、レイアウトに合わせて切り替わります。一覧とメッセージが横に並ぶ場合はオフ、それ以外はオンです。"
},
"identities": {
"modal_title": "送信者情報を管理",
diff --git a/locales/ko/common.json b/locales/ko/common.json
index f7a56f155..73e70e37b 100644
--- a/locales/ko/common.json
+++ b/locales/ko/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "대화 접기: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, other {이전 메시지 #개 보기}}"
+ "show_older": "{count, plural, other {이전 메시지 #개 보기}}",
+ "return_to_list_follows_layout": "변경하기 전까지는 레이아웃을 따릅니다. 목록과 메시지가 나란히 있으면 꺼지고, 그 밖에는 켜집니다."
},
"identities": {
"modal_title": "보내는 사람 관리",
diff --git a/locales/lv/common.json b/locales/lv/common.json
index 76422c867..540a5447b 100644
--- a/locales/lv/common.json
+++ b/locales/lv/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Sairt sarunu: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, zero {Rādīt # vecākas ziņas} one {Rādīt # vecāku ziņu} other {Rādīt # vecākas ziņas}}"
+ "show_older": "{count, plural, zero {Rādīt # vecākas ziņas} one {Rādīt # vecāku ziņu} other {Rādīt # vecākas ziņas}}",
+ "return_to_list_follows_layout": "Kamēr to nemaināt, tas seko izkārtojumam: izslēgts, ja saraksts un ziņa ir blakus, citādi ieslēgts."
},
"identities": {
"modal_title": "Pārvaldīt sūtītāja identitātes",
diff --git a/locales/mn/common.json b/locales/mn/common.json
index 959626386..76b03b40c 100644
--- a/locales/mn/common.json
+++ b/locales/mn/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Харилцан яриаг хураах: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Өмнөх # захиа харуулах} other {Өмнөх # захиа харуулах}}"
+ "show_older": "{count, plural, one {Өмнөх # захиа харуулах} other {Өмнөх # захиа харуулах}}",
+ "return_to_list_follows_layout": "Та өөрчлөхөөс нааш энэ нь байрлалаас хамаарна: жагсаалт ба захиа зэрэгцэн байвал унтраалттай, бусад үед асаалттай."
},
"identities": {
"modal_title": "Илгээж буй таниулбаруудыг удирдах",
diff --git a/locales/nb/common.json b/locales/nb/common.json
index be28a77a1..d49859663 100644
--- a/locales/nb/common.json
+++ b/locales/nb/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Fold sammen samtalen: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Vis # eldre melding} other {Vis # eldre meldinger}}"
+ "show_older": "{count, plural, one {Vis # eldre melding} other {Vis # eldre meldinger}}",
+ "return_to_list_follows_layout": "Inntil du endrer det, følger det oppsettet: av når listen og meldingen står side om side, ellers på."
},
"identities": {
"modal_title": "Administrer avsenderidentiteter",
diff --git a/locales/nl/common.json b/locales/nl/common.json
index 78360310b..453708b0e 100644
--- a/locales/nl/common.json
+++ b/locales/nl/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Gesprek inklappen: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {# ouder bericht tonen} other {# oudere berichten tonen}}"
+ "show_older": "{count, plural, one {# ouder bericht tonen} other {# oudere berichten tonen}}",
+ "return_to_list_follows_layout": "Zolang je het niet wijzigt, volgt dit de indeling: uit als de lijst en het bericht naast elkaar staan, anders aan."
},
"identities": {
"modal_title": "Verzendidentiteiten beheren",
diff --git a/locales/pl/common.json b/locales/pl/common.json
index 122ee9b3b..a1966800e 100644
--- a/locales/pl/common.json
+++ b/locales/pl/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Zwiń konwersację: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Pokaż # starszą wiadomość} few {Pokaż # starsze wiadomości} many {Pokaż # starszych wiadomości} other {Pokaż # starszej wiadomości}}"
+ "show_older": "{count, plural, one {Pokaż # starszą wiadomość} few {Pokaż # starsze wiadomości} many {Pokaż # starszych wiadomości} other {Pokaż # starszej wiadomości}}",
+ "return_to_list_follows_layout": "Dopóki tego nie zmienisz, ustawienie zależy od układu: wyłączone, gdy lista i wiadomość są obok siebie, w innych przypadkach włączone."
},
"identities": {
"modal_title": "Zarządzaj tożsamościami nadawcy",
diff --git a/locales/pt/common.json b/locales/pt/common.json
index 115f3dd10..6a9ec6cd6 100644
--- a/locales/pt/common.json
+++ b/locales/pt/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Recolher conversa: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Mostrar # mensagem anterior} other {Mostrar # mensagens anteriores}}"
+ "show_older": "{count, plural, one {Mostrar # mensagem anterior} other {Mostrar # mensagens anteriores}}",
+ "return_to_list_follows_layout": "Enquanto não alterar, segue o layout: desligado quando a lista e a mensagem estão lado a lado, ligado nos outros casos."
},
"identities": {
"modal_title": "Gerenciar Identidades de Envio",
diff --git a/locales/ro/common.json b/locales/ro/common.json
index 9affac340..db173df66 100644
--- a/locales/ro/common.json
+++ b/locales/ro/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Ascunde conversația: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Afișează # mesaj mai vechi} few {Afișează # mesaje mai vechi} other {Afișează # de mesaje mai vechi}}"
+ "show_older": "{count, plural, one {Afișează # mesaj mai vechi} few {Afișează # mesaje mai vechi} other {Afișează # de mesaje mai vechi}}",
+ "return_to_list_follows_layout": "Cât timp nu îl modificați, urmează aspectul: dezactivat când lista și mesajul sunt unul lângă altul, activat în rest."
},
"identities": {
"modal_title": "Gestionarea identităților de expediere",
diff --git a/locales/ru/common.json b/locales/ru/common.json
index c7477e0e3..1a38fa1b6 100644
--- a/locales/ru/common.json
+++ b/locales/ru/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Свернуть разговор: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Показать # более раннее письмо} few {Показать # более ранних письма} many {Показать # более ранних писем} other {Показать # более раннего письма}}"
+ "show_older": "{count, plural, one {Показать # более раннее письмо} few {Показать # более ранних письма} many {Показать # более ранних писем} other {Показать # более раннего письма}}",
+ "return_to_list_follows_layout": "Пока вы это не измените, настройка зависит от макета: выключена, когда список и письмо стоят рядом, в остальных случаях включена."
},
"identities": {
"modal_title": "Управление идентификациями отправителя",
diff --git a/locales/sk/common.json b/locales/sk/common.json
index 855ed2980..157bce03b 100644
--- a/locales/sk/common.json
+++ b/locales/sk/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Zbaliť konverzáciu: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Zobraziť # staršiu správu} few {Zobraziť # staršie správy} many {Zobraziť # staršej správy} other {Zobraziť # starších správ}}"
+ "show_older": "{count, plural, one {Zobraziť # staršiu správu} few {Zobraziť # staršie správy} many {Zobraziť # staršej správy} other {Zobraziť # starších správ}}",
+ "return_to_list_follows_layout": "Kým to nezmeníte, riadi sa to rozložením: vypnuté, keď sú zoznam a správa vedľa seba, inak zapnuté."
},
"identities": {
"modal_title": "Správa identít odosielateľa",
diff --git a/locales/th/common.json b/locales/th/common.json
index 7be585856..fed7cae1c 100644
--- a/locales/th/common.json
+++ b/locales/th/common.json
@@ -614,7 +614,8 @@
"collapse_named": "ย่อการสนทนา: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, other {แสดงข้อความก่อนหน้า # ฉบับ}}"
+ "show_older": "{count, plural, other {แสดงข้อความก่อนหน้า # ฉบับ}}",
+ "return_to_list_follows_layout": "จนกว่าคุณจะเปลี่ยน ค่านี้จะเป็นไปตามเลย์เอาต์: ปิดเมื่อรายการและข้อความอยู่เคียงข้างกัน และเปิดในกรณีอื่น"
},
"notifications": {
"email_sent": "ส่งอีเมลแล้ว",
diff --git a/locales/tr/common.json b/locales/tr/common.json
index cdd2c6f4e..f78660132 100644
--- a/locales/tr/common.json
+++ b/locales/tr/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Konuşmayı daralt: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {# eski iletiyi göster} other {# eski iletiyi göster}}"
+ "show_older": "{count, plural, one {# eski iletiyi göster} other {# eski iletiyi göster}}",
+ "return_to_list_follows_layout": "Siz değiştirene kadar bu ayar düzene göre belirlenir: liste ve ileti yan yanaysa kapalı, değilse açık."
},
"identities": {
"modal_title": "Gönderme Kimliklerini Yönet",
diff --git a/locales/uk/common.json b/locales/uk/common.json
index 3cea7cf24..a4dbb9f74 100644
--- a/locales/uk/common.json
+++ b/locales/uk/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "Згорнути бесіду: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, one {Показати # давніший лист} few {Показати # давніші листи} many {Показати # давніших листів} other {Показати # давнішого листа}}"
+ "show_older": "{count, plural, one {Показати # давніший лист} few {Показати # давніші листи} many {Показати # давніших листів} other {Показати # давнішого листа}}",
+ "return_to_list_follows_layout": "Поки ви це не зміните, налаштування залежить від макета: вимкнено, коли список і лист розташовані поруч, в інших випадках увімкнено."
},
"identities": {
"modal_title": "Керування ідентифікаторами надсилання",
diff --git a/locales/vi/common.json b/locales/vi/common.json
index a31ecfdb3..358ab13ce 100644
--- a/locales/vi/common.json
+++ b/locales/vi/common.json
@@ -3779,7 +3779,8 @@
"collapse_named": "Thu gọn cuộc trò chuyện: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, other {Hiện # thư cũ hơn}}"
+ "show_older": "{count, plural, other {Hiện # thư cũ hơn}}",
+ "return_to_list_follows_layout": "Cho đến khi bạn thay đổi, cài đặt này theo bố cục: tắt khi danh sách và thư nằm cạnh nhau, bật trong các trường hợp khác."
},
"identities": {
"modal_title": "Quản lý danh tính gửi thư",
diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json
index 1cc124fc6..fc3074406 100644
--- a/locales/zh-TW/common.json
+++ b/locales/zh-TW/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "收合對話串: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, other {顯示 # 封較早的郵件}}"
+ "show_older": "{count, plural, other {顯示 # 封較早的郵件}}",
+ "return_to_list_follows_layout": "在您變更之前,此項會依版面配置而定:清單與郵件並排顯示時關閉,其他情況下開啟。"
},
"identities": {
"modal_title": "管理寄件身分",
diff --git a/locales/zh/common.json b/locales/zh/common.json
index 23cecd720..d3c3d661c 100644
--- a/locales/zh/common.json
+++ b/locales/zh/common.json
@@ -3767,7 +3767,8 @@
"collapse_named": "折叠会话: {subject}"
},
"conversation_pane": {
- "show_older": "{count, plural, other {显示 # 封较早的邮件}}"
+ "show_older": "{count, plural, other {显示 # 封较早的邮件}}",
+ "return_to_list_follows_layout": "在你更改之前,此项随布局而定:列表和邮件并排显示时关闭,其他情况下开启。"
},
"identities": {
"modal_title": "管理发送身份",