From fe4f809092fc95b3c8d59592feadcae8e24852da Mon Sep 17 00:00:00 2001
From: Linus Rath <139418639+rathlinus@users.noreply.github.com>
Date: Wed, 14 Oct 2026 03:00:46 +0200
Subject: [PATCH] fix: keep a plugin side panel from squeezing the message too
narrow to read
---
.../viewer-plugin-panel-width.test.tsx | 78 +++++++++++++++++++
components/email/email-viewer.tsx | 41 ++++++++--
locales/ar/common.json | 4 +-
locales/ca/common.json | 4 +-
locales/cs/common.json | 4 +-
locales/da/common.json | 4 +-
locales/de/common.json | 22 +++---
locales/en/common.json | 22 +++---
locales/es/common.json | 4 +-
locales/fa/common.json | 4 +-
locales/fr/common.json | 4 +-
locales/he/common.json | 4 +-
locales/hu/common.json | 4 +-
locales/it/common.json | 4 +-
locales/ja/common.json | 4 +-
locales/ko/common.json | 4 +-
locales/lv/common.json | 4 +-
locales/mn/common.json | 4 +-
locales/nb/common.json | 4 +-
locales/nl/common.json | 4 +-
locales/pl/common.json | 4 +-
locales/pt/common.json | 4 +-
locales/ro/common.json | 4 +-
locales/ru/common.json | 4 +-
locales/sk/common.json | 4 +-
locales/tr/common.json | 4 +-
locales/uk/common.json | 4 +-
locales/zh-TW/common.json | 4 +-
locales/zh/common.json | 4 +-
29 files changed, 212 insertions(+), 51 deletions(-)
create mode 100644 components/email/__tests__/viewer-plugin-panel-width.test.tsx
diff --git a/components/email/__tests__/viewer-plugin-panel-width.test.tsx b/components/email/__tests__/viewer-plugin-panel-width.test.tsx
new file mode 100644
index 000000000..a16703c47
--- /dev/null
+++ b/components/email/__tests__/viewer-plugin-panel-width.test.tsx
@@ -0,0 +1,78 @@
+import { render, screen, act, fireEvent } from '@testing-library/react';
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import React from 'react';
+import type { Email, Mailbox } from '@/lib/jmap/types';
+
+// With a plugin panel open at 280 px next to a 300 px message (three panes
+// on a laptop), the subject broke after every few letters. The panel now
+// starts collapsed when it would leave the message under 480 px.
+
+vi.mock('@/hooks/use-media-query', () => ({
+ useDeviceDetection: () => ({ isMobile: false, isTablet: false, isDesktop: true }),
+ useMediaQuery: () => false,
+}));
+vi.mock('@/components/tour/tour-provider', () => ({
+ useTour: () => ({ activeTour: null, startTour: vi.fn(), endTour: vi.fn(), registerStep: vi.fn() }),
+}));
+vi.mock('@/components/plugins/plugin-slot', () => ({
+ PluginSlot: ({ name }: { name: string }) => React.createElement('div', { 'data-testid': `slot-${name}` }),
+}));
+vi.mock('@/hooks/use-plugin-slot-offers', () => ({
+ usePluginSlotOffers: (slot: string) => (slot === 'email-detail-sidebar' ? [{ pluginId: 'notes', order: 100 }] : []),
+}));
+
+let reportWidth = 0;
+const observers: Array<(entries: Array<{ contentRect: { width: number } }>) => void> = [];
+class FakeResizeObserver {
+ constructor(private cb: (entries: Array<{ contentRect: { width: number } }>) => void) { observers.push(cb); }
+ observe() { this.cb([{ contentRect: { width: reportWidth } }]); }
+ unobserve() {}
+ disconnect() {}
+}
+vi.stubGlobal('ResizeObserver', FakeResizeObserver);
+
+const { EmailViewer } = await import('../email-viewer');
+
+const mailboxes = [
+ { id: 'inbox', name: 'Inbox', role: 'inbox', parentId: null, myRights: { mayAddItems: true } },
+] as unknown as Mailbox[];
+const email = {
+ id: 'e1', blobId: 'b1', threadId: 't1', mailboxIds: { inbox: true }, keywords: { $seen: true },
+ from: [{ name: 'Alice', email: 'alice@example.com' }], to: [], subject: 'Hello', receivedAt: '2026-01-01T00:00:00Z',
+ preview: '', hasAttachment: false, size: 1, textBody: [], htmlBody: [], attachments: [], bodyValues: {},
+} as unknown as Email;
+
+function renderViewer() {
+ return render();
+}
+
+beforeEach(() => {
+ localStorage.clear();
+ observers.length = 0;
+});
+
+describe('plugin detail panel and narrow messages', () => {
+ it('starts collapsed when it would leave the message too narrow', () => {
+ reportWidth = 640;
+ renderViewer();
+
+ expect(screen.queryByTestId('slot-email-detail-sidebar')).not.toBeInTheDocument();
+ expect(screen.getByLabelText('plugin_panel_show')).toBeInTheDocument();
+ });
+
+ it('opens anyway when the user asks', () => {
+ reportWidth = 640;
+ renderViewer();
+
+ act(() => { fireEvent.click(screen.getByLabelText('plugin_panel_show')); });
+
+ expect(screen.getByTestId('slot-email-detail-sidebar')).toBeInTheDocument();
+ });
+
+ it('is open when there is room', () => {
+ reportWidth = 1100;
+ renderViewer();
+
+ expect(screen.getByTestId('slot-email-detail-sidebar')).toBeInTheDocument();
+ });
+});
diff --git a/components/email/email-viewer.tsx b/components/email/email-viewer.tsx
index 030af2e87..8fc8e9118 100644
--- a/components/email/email-viewer.tsx
+++ b/components/email/email-viewer.tsx
@@ -961,6 +961,9 @@ function DetailsCategorySlot({ email, category }: { email: EmailReadView | null;
return ;
}
+/** Narrowest the message may get next to a plugin panel before the panel collapses. */
+const MIN_READER_WIDTH = 480;
+
function SidebarSection({ icon: Icon, title, children }: { icon: React.ComponentType<{ className?: string }>; title: string; children: React.ReactNode }) {
return (
@@ -1422,6 +1425,25 @@ export function EmailViewer({
} catch { return 280; }
});
const detailSidebarWidthRef = useRef(detailSidebarWidth);
+ // The panel takes its width from the message. When that would leave the
+ // message too narrow to read (three panes on a laptop), the panel starts
+ // collapsed; opening it anyway is still the user's call.
+ const viewerRootRef = useRef
(null);
+ const [viewerWidth, setViewerWidth] = useState(0);
+ const [detailSidebarForcedOpen, setDetailSidebarForcedOpen] = useState(false);
+ useEffect(() => {
+ if (!hasDetailSidebar || typeof ResizeObserver === 'undefined') return;
+ const el = viewerRootRef.current;
+ if (!el) return;
+ const ro = new ResizeObserver((entries) => {
+ const width = Math.round(entries[0]?.contentRect.width ?? 0);
+ setViewerWidth(width);
+ });
+ ro.observe(el);
+ return () => ro.disconnect();
+ }, [hasDetailSidebar]);
+ const readerTooNarrow = viewerWidth > 0 && viewerWidth - detailSidebarWidth < MIN_READER_WIDTH;
+ const sidebarCollapsed = detailSidebarCollapsed || (readerTooNarrow && !detailSidebarForcedOpen);
useEffect(() => {
try { localStorage.setItem('emailDetailSidebarCollapsed', detailSidebarCollapsed ? '1' : '0'); } catch { /* ignore */ }
@@ -3993,6 +4015,7 @@ export function EmailViewer({
return (
@@ -6073,20 +6096,23 @@ export function EmailViewer({
{hasDetailSidebar && !isMobile && (
<>
{/* Collapse toggle when sidebar is collapsed */}
- {detailSidebarCollapsed && (
+ {sidebarCollapsed && (
)}
- {!detailSidebarCollapsed && (
+ {!sidebarCollapsed && (
<>
{ detailSidebarWidthRef.current = detailSidebarWidth; }}
@@ -6105,9 +6131,12 @@ export function EmailViewer({
diff --git a/locales/ar/common.json b/locales/ar/common.json
index 8ffea83c2..24f3f9268 100644
--- a/locales/ar/common.json
+++ b/locales/ar/common.json
@@ -620,7 +620,9 @@
"copied": "تم نسخ الرمز",
"copy_failed": "تعذّر نسخ الرمز"
},
- "mv_position": "{index} من {total}"
+ "mv_position": "{index} من {total}",
+ "plugin_panel_show": "إظهار لوحة الإضافة",
+ "plugin_panel_hide": "إخفاء لوحة الإضافة"
},
"email_composer": {
"minimize": "تصغير",
diff --git a/locales/ca/common.json b/locales/ca/common.json
index 5531a18fe..d9ea2a1b8 100644
--- a/locales/ca/common.json
+++ b/locales/ca/common.json
@@ -620,7 +620,9 @@
"copied": "Codi copiat",
"copy_failed": "No s'ha pogut copiar el codi"
},
- "mv_position": "{index} de {total}"
+ "mv_position": "{index} de {total}",
+ "plugin_panel_show": "Mostra el tauler del connector",
+ "plugin_panel_hide": "Amaga el tauler del connector"
},
"email_composer": {
"minimize": "Minimitza",
diff --git a/locales/cs/common.json b/locales/cs/common.json
index c618351a8..aec9ada4e 100644
--- a/locales/cs/common.json
+++ b/locales/cs/common.json
@@ -620,7 +620,9 @@
"copied": "Kód zkopírován",
"copy_failed": "Kód se nepodařilo zkopírovat"
},
- "mv_position": "{index} z {total}"
+ "mv_position": "{index} z {total}",
+ "plugin_panel_show": "Zobrazit panel pluginu",
+ "plugin_panel_hide": "Skrýt panel pluginu"
},
"email_composer": {
"minimize": "Minimalizovat",
diff --git a/locales/da/common.json b/locales/da/common.json
index d263b1602..e099ca36a 100644
--- a/locales/da/common.json
+++ b/locales/da/common.json
@@ -620,7 +620,9 @@
"copied": "Kode kopieret",
"copy_failed": "Koden kunne ikke kopieres"
},
- "mv_position": "{index} af {total}"
+ "mv_position": "{index} af {total}",
+ "plugin_panel_show": "Vis pluginpanel",
+ "plugin_panel_hide": "Skjul pluginpanel"
},
"email_composer": {
"minimize": "Minimer",
diff --git a/locales/de/common.json b/locales/de/common.json
index 12eb3a71a..2ba2ed0de 100644
--- a/locales/de/common.json
+++ b/locales/de/common.json
@@ -359,15 +359,15 @@
"external_content_warning": "Bilder und externe Inhalte wurden blockiert",
"load_external_content": "Bilder laden",
"trust_sender": "Diesem Absender immer vertrauen",
- "sender_check": {
- "unverified_label": "Absender nicht bestätigt",
- "failed_label": "Absenderprüfung fehlgeschlagen",
- "unverified": "Diese Nachricht gibt vor, von {domain} zu kommen, aber nichts bestätigt das. Sie trägt keine gültige Signatur von {domain} und kam nicht von einem Server, den {domain} zulässt.",
- "unverified_sent_from": "Diese Nachricht gibt vor, von {domain} zu kommen, wurde aber von {host} verschickt und trägt keine gültige Signatur von {domain}.",
- "failed": "Diese Nachricht gibt vor, von {domain} zu kommen, hat aber die Absenderprüfung dieser Domain nicht bestanden. Sie ist möglicherweise gefälscht.",
- "failed_sent_from": "Diese Nachricht gibt vor, von {domain} zu kommen, wurde aber von {host} verschickt und hat die Absenderprüfung von {domain} nicht bestanden. Sie ist möglicherweise gefälscht.",
- "caution": "Seien Sie vorsichtig mit Links, Anhängen und Fragen nach Passwörtern oder Zahlungsdaten."
- },
+ "sender_check": {
+ "unverified_label": "Absender nicht bestätigt",
+ "failed_label": "Absenderprüfung fehlgeschlagen",
+ "unverified": "Diese Nachricht gibt vor, von {domain} zu kommen, aber nichts bestätigt das. Sie trägt keine gültige Signatur von {domain} und kam nicht von einem Server, den {domain} zulässt.",
+ "unverified_sent_from": "Diese Nachricht gibt vor, von {domain} zu kommen, wurde aber von {host} verschickt und trägt keine gültige Signatur von {domain}.",
+ "failed": "Diese Nachricht gibt vor, von {domain} zu kommen, hat aber die Absenderprüfung dieser Domain nicht bestanden. Sie ist möglicherweise gefälscht.",
+ "failed_sent_from": "Diese Nachricht gibt vor, von {domain} zu kommen, wurde aber von {host} verschickt und hat die Absenderprüfung von {domain} nicht bestanden. Sie ist möglicherweise gefälscht.",
+ "caution": "Seien Sie vorsichtig mit Links, Anhängen und Fragen nach Passwörtern oder Zahlungsdaten."
+ },
"back_to_list": "Zurück zur Liste",
"view_contact": "Kontakt anzeigen",
"message_details": "Nachrichtendetails",
@@ -620,7 +620,9 @@
"copied": "Code kopiert",
"copy_failed": "Code konnte nicht kopiert werden"
},
- "mv_position": "{index} von {total}"
+ "mv_position": "{index} von {total}",
+ "plugin_panel_show": "Plugin-Bereich einblenden",
+ "plugin_panel_hide": "Plugin-Bereich ausblenden"
},
"email_composer": {
"minimize": "Minimieren",
diff --git a/locales/en/common.json b/locales/en/common.json
index 685016f2d..942d372a4 100644
--- a/locales/en/common.json
+++ b/locales/en/common.json
@@ -359,15 +359,15 @@
"external_content_warning": "Images and external content have been blocked",
"load_external_content": "Load images",
"trust_sender": "Always trust this sender",
- "sender_check": {
- "unverified_label": "Unverified sender",
- "failed_label": "Sender check failed",
- "unverified": "This message claims to be from {domain}, but nothing confirms that. It has no valid signature from {domain} and didn't come from a server {domain} authorizes.",
- "unverified_sent_from": "This message claims to be from {domain}, but it was sent from {host} and has no valid signature from {domain}.",
- "failed": "This message claims to be from {domain}, but it failed that domain's sender checks. It may be forged.",
- "failed_sent_from": "This message claims to be from {domain}, but it was sent from {host} and failed {domain}'s sender checks. It may be forged.",
- "caution": "Be careful with links, attachments and requests for passwords or payment details."
- },
+ "sender_check": {
+ "unverified_label": "Unverified sender",
+ "failed_label": "Sender check failed",
+ "unverified": "This message claims to be from {domain}, but nothing confirms that. It has no valid signature from {domain} and didn't come from a server {domain} authorizes.",
+ "unverified_sent_from": "This message claims to be from {domain}, but it was sent from {host} and has no valid signature from {domain}.",
+ "failed": "This message claims to be from {domain}, but it failed that domain's sender checks. It may be forged.",
+ "failed_sent_from": "This message claims to be from {domain}, but it was sent from {host} and failed {domain}'s sender checks. It may be forged.",
+ "caution": "Be careful with links, attachments and requests for passwords or payment details."
+ },
"back_to_list": "Back to list",
"view_contact": "View contact",
"message_details": "Message Details",
@@ -620,7 +620,9 @@
"copied": "Code copied",
"copy_failed": "Could not copy the code"
},
- "mv_position": "{index} of {total}"
+ "mv_position": "{index} of {total}",
+ "plugin_panel_show": "Show plugin panel",
+ "plugin_panel_hide": "Hide plugin panel"
},
"email_composer": {
"minimize": "Minimize",
diff --git a/locales/es/common.json b/locales/es/common.json
index 603052683..4a7136e37 100644
--- a/locales/es/common.json
+++ b/locales/es/common.json
@@ -620,7 +620,9 @@
"copied": "Código copiado",
"copy_failed": "No se pudo copiar el código"
},
- "mv_position": "{index} de {total}"
+ "mv_position": "{index} de {total}",
+ "plugin_panel_show": "Mostrar el panel del complemento",
+ "plugin_panel_hide": "Ocultar el panel del complemento"
},
"email_composer": {
"minimize": "Minimizar",
diff --git a/locales/fa/common.json b/locales/fa/common.json
index 6726945b8..2343dac11 100644
--- a/locales/fa/common.json
+++ b/locales/fa/common.json
@@ -620,7 +620,9 @@
"copied": "کد کپی شد",
"copy_failed": "کپی کد ممکن نشد"
},
- "mv_position": "{index} از {total}"
+ "mv_position": "{index} از {total}",
+ "plugin_panel_show": "نمایش پنل افزونه",
+ "plugin_panel_hide": "پنهان کردن پنل افزونه"
},
"email_composer": {
"minimize": "کوچک کردن",
diff --git a/locales/fr/common.json b/locales/fr/common.json
index 27ed6886d..3527665e8 100644
--- a/locales/fr/common.json
+++ b/locales/fr/common.json
@@ -620,7 +620,9 @@
"copied": "Code copié",
"copy_failed": "Impossible de copier le code"
},
- "mv_position": "{index} sur {total}"
+ "mv_position": "{index} sur {total}",
+ "plugin_panel_show": "Afficher le panneau du plugin",
+ "plugin_panel_hide": "Masquer le panneau du plugin"
},
"email_composer": {
"minimize": "Réduire",
diff --git a/locales/he/common.json b/locales/he/common.json
index f1f7fdfcb..10b638bb2 100644
--- a/locales/he/common.json
+++ b/locales/he/common.json
@@ -585,7 +585,9 @@
"copied": "הקוד הועתק",
"copy_failed": "לא ניתן להעתיק את הקוד"
},
- "mv_position": "{index} מתוך {total}"
+ "mv_position": "{index} מתוך {total}",
+ "plugin_panel_show": "הצגת חלונית התוסף",
+ "plugin_panel_hide": "הסתרת חלונית התוסף"
},
"email_composer": {
"minimize": "מזעור",
diff --git a/locales/hu/common.json b/locales/hu/common.json
index b2b779e6f..550c4292e 100644
--- a/locales/hu/common.json
+++ b/locales/hu/common.json
@@ -620,7 +620,9 @@
"copied": "Kód másolva",
"copy_failed": "Nem sikerült másolni a kódot"
},
- "mv_position": "{index} / {total}"
+ "mv_position": "{index} / {total}",
+ "plugin_panel_show": "Bővítménypanel megjelenítése",
+ "plugin_panel_hide": "Bővítménypanel elrejtése"
},
"email_composer": {
"minimize": "Kis méret",
diff --git a/locales/it/common.json b/locales/it/common.json
index beb5e13a9..a738930ef 100644
--- a/locales/it/common.json
+++ b/locales/it/common.json
@@ -620,7 +620,9 @@
"copied": "Codice copiato",
"copy_failed": "Impossibile copiare il codice"
},
- "mv_position": "{index} di {total}"
+ "mv_position": "{index} di {total}",
+ "plugin_panel_show": "Mostra il pannello del plugin",
+ "plugin_panel_hide": "Nascondi il pannello del plugin"
},
"email_composer": {
"minimize": "Riduci a icona",
diff --git a/locales/ja/common.json b/locales/ja/common.json
index 5288d58b1..b97e9101e 100644
--- a/locales/ja/common.json
+++ b/locales/ja/common.json
@@ -620,7 +620,9 @@
"copied": "コードをコピーしました",
"copy_failed": "コードをコピーできませんでした"
},
- "mv_position": "{index} / {total}"
+ "mv_position": "{index} / {total}",
+ "plugin_panel_show": "プラグインパネルを表示",
+ "plugin_panel_hide": "プラグインパネルを隠す"
},
"email_composer": {
"minimize": "最小化",
diff --git a/locales/ko/common.json b/locales/ko/common.json
index 0ce740141..195cf5797 100644
--- a/locales/ko/common.json
+++ b/locales/ko/common.json
@@ -620,7 +620,9 @@
"copied": "코드를 복사했습니다",
"copy_failed": "코드를 복사할 수 없습니다"
},
- "mv_position": "{index} / {total}"
+ "mv_position": "{index} / {total}",
+ "plugin_panel_show": "플러그인 패널 표시",
+ "plugin_panel_hide": "플러그인 패널 숨기기"
},
"email_composer": {
"minimize": "최소화",
diff --git a/locales/lv/common.json b/locales/lv/common.json
index bc8638beb..cf298dfeb 100644
--- a/locales/lv/common.json
+++ b/locales/lv/common.json
@@ -620,7 +620,9 @@
"copied": "Kods nokopēts",
"copy_failed": "Neizdevās nokopēt kodu"
},
- "mv_position": "{index} no {total}"
+ "mv_position": "{index} no {total}",
+ "plugin_panel_show": "Rādīt spraudņa paneli",
+ "plugin_panel_hide": "Slēpt spraudņa paneli"
},
"email_composer": {
"minimize": "Minimizēt",
diff --git a/locales/mn/common.json b/locales/mn/common.json
index 97b68f571..21ba2eed0 100644
--- a/locales/mn/common.json
+++ b/locales/mn/common.json
@@ -620,7 +620,9 @@
"copied": "Код хуулагдлаа",
"copy_failed": "Кодыг хуулж чадсангүй"
},
- "mv_position": "{total}-с {index}"
+ "mv_position": "{total}-с {index}",
+ "plugin_panel_show": "Залгаасын самбарыг харуулах",
+ "plugin_panel_hide": "Залгаасын самбарыг нуух"
},
"email_composer": {
"minimize": "Багасгах",
diff --git a/locales/nb/common.json b/locales/nb/common.json
index c042d86d2..0ea3afcd0 100644
--- a/locales/nb/common.json
+++ b/locales/nb/common.json
@@ -620,7 +620,9 @@
"copied": "Kode kopiert",
"copy_failed": "Kunne ikke kopiere koden"
},
- "mv_position": "{index} av {total}"
+ "mv_position": "{index} av {total}",
+ "plugin_panel_show": "Vis tilleggspanel",
+ "plugin_panel_hide": "Skjul tilleggspanel"
},
"email_composer": {
"minimize": "Minimer",
diff --git a/locales/nl/common.json b/locales/nl/common.json
index 4b2213065..12acefe93 100644
--- a/locales/nl/common.json
+++ b/locales/nl/common.json
@@ -620,7 +620,9 @@
"copied": "Code gekopieerd",
"copy_failed": "Kan de code niet kopiëren"
},
- "mv_position": "{index} van {total}"
+ "mv_position": "{index} van {total}",
+ "plugin_panel_show": "Plug-inpaneel tonen",
+ "plugin_panel_hide": "Plug-inpaneel verbergen"
},
"email_composer": {
"minimize": "Minimaliseren",
diff --git a/locales/pl/common.json b/locales/pl/common.json
index d396f0356..c0d941186 100644
--- a/locales/pl/common.json
+++ b/locales/pl/common.json
@@ -620,7 +620,9 @@
"copied": "Skopiowano kod",
"copy_failed": "Nie udało się skopiować kodu"
},
- "mv_position": "{index} z {total}"
+ "mv_position": "{index} z {total}",
+ "plugin_panel_show": "Pokaż panel wtyczki",
+ "plugin_panel_hide": "Ukryj panel wtyczki"
},
"email_composer": {
"minimize": "Minimalizuj",
diff --git a/locales/pt/common.json b/locales/pt/common.json
index 7cd725830..4b0c0702b 100644
--- a/locales/pt/common.json
+++ b/locales/pt/common.json
@@ -620,7 +620,9 @@
"copied": "Código copiado",
"copy_failed": "Não foi possível copiar o código"
},
- "mv_position": "{index} de {total}"
+ "mv_position": "{index} de {total}",
+ "plugin_panel_show": "Mostrar o painel do plugin",
+ "plugin_panel_hide": "Ocultar o painel do plugin"
},
"email_composer": {
"minimize": "Minimizar",
diff --git a/locales/ro/common.json b/locales/ro/common.json
index c71303c6b..9252a4761 100644
--- a/locales/ro/common.json
+++ b/locales/ro/common.json
@@ -620,7 +620,9 @@
"copied": "Cod copiat",
"copy_failed": "Codul nu a putut fi copiat"
},
- "mv_position": "{index} din {total}"
+ "mv_position": "{index} din {total}",
+ "plugin_panel_show": "Afișează panoul pluginului",
+ "plugin_panel_hide": "Ascunde panoul pluginului"
},
"email_composer": {
"minimize": "Minimizează",
diff --git a/locales/ru/common.json b/locales/ru/common.json
index 4596ec388..359f85ecb 100644
--- a/locales/ru/common.json
+++ b/locales/ru/common.json
@@ -620,7 +620,9 @@
"copied": "Код скопирован",
"copy_failed": "Не удалось скопировать код"
},
- "mv_position": "{index} из {total}"
+ "mv_position": "{index} из {total}",
+ "plugin_panel_show": "Показать панель плагина",
+ "plugin_panel_hide": "Скрыть панель плагина"
},
"email_composer": {
"minimize": "Свернуть",
diff --git a/locales/sk/common.json b/locales/sk/common.json
index 22f4c5530..e63d2a6e9 100644
--- a/locales/sk/common.json
+++ b/locales/sk/common.json
@@ -620,7 +620,9 @@
"copied": "Kód skopírovaný",
"copy_failed": "Kód sa nepodarilo skopírovať"
},
- "mv_position": "{index} z {total}"
+ "mv_position": "{index} z {total}",
+ "plugin_panel_show": "Zobraziť panel doplnku",
+ "plugin_panel_hide": "Skryť panel doplnku"
},
"email_composer": {
"minimize": "Minimalizovať",
diff --git a/locales/tr/common.json b/locales/tr/common.json
index acf237629..18127549b 100644
--- a/locales/tr/common.json
+++ b/locales/tr/common.json
@@ -620,7 +620,9 @@
"copied": "Kod kopyalandı",
"copy_failed": "Kod kopyalanamadı"
},
- "mv_position": "{index} / {total}"
+ "mv_position": "{index} / {total}",
+ "plugin_panel_show": "Eklenti panelini göster",
+ "plugin_panel_hide": "Eklenti panelini gizle"
},
"email_composer": {
"minimize": "Simge durumuna küçült",
diff --git a/locales/uk/common.json b/locales/uk/common.json
index 8ce2a0b12..d28f9e356 100644
--- a/locales/uk/common.json
+++ b/locales/uk/common.json
@@ -620,7 +620,9 @@
"copied": "Код скопійовано",
"copy_failed": "Не вдалося скопіювати код"
},
- "mv_position": "{index} з {total}"
+ "mv_position": "{index} з {total}",
+ "plugin_panel_show": "Показати панель плагіна",
+ "plugin_panel_hide": "Сховати панель плагіна"
},
"email_composer": {
"minimize": "Згорнути",
diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json
index 1415806e0..787a71aba 100644
--- a/locales/zh-TW/common.json
+++ b/locales/zh-TW/common.json
@@ -620,7 +620,9 @@
"copied": "驗證碼已複製",
"copy_failed": "無法複製驗證碼"
},
- "mv_position": "第 {index} 封,共 {total} 封"
+ "mv_position": "第 {index} 封,共 {total} 封",
+ "plugin_panel_show": "顯示外掛程式面板",
+ "plugin_panel_hide": "隱藏外掛程式面板"
},
"email_composer": {
"minimize": "最小化",
diff --git a/locales/zh/common.json b/locales/zh/common.json
index 10342d03d..ec47531a7 100644
--- a/locales/zh/common.json
+++ b/locales/zh/common.json
@@ -620,7 +620,9 @@
"copied": "验证码已复制",
"copy_failed": "无法复制验证码"
},
- "mv_position": "第 {index} 封,共 {total} 封"
+ "mv_position": "第 {index} 封,共 {total} 封",
+ "plugin_panel_show": "显示插件面板",
+ "plugin_panel_hide": "隐藏插件面板"
},
"email_composer": {
"minimize": "最小化",