fix: show folder names in the phone folder settings and move the row actions into a menu

This commit is contained in:
Linus Rath
2026-10-28 02:43:29 +01:00
parent dc0fe7d980
commit 0f1d226d4c
31 changed files with 289 additions and 36 deletions
@@ -0,0 +1,73 @@
import { fireEvent, render, screen, within } from '@testing-library/react';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { FolderSettings } from '../folder-settings';
import { useEmailStore } from '@/stores/email-store';
import { useAuthStore } from '@/stores/auth-store';
import { useSettingsStore } from '@/stores/settings-store';
import type { Mailbox } from '@/lib/jmap/types';
// On the phone the counter select and the row's icon buttons left no room
// for the folder name. They sit behind a ⋮ there, which right-click opens
// too, and the name keeps its full text in a tooltip.
vi.mock('../settings-section', async (importOriginal) => ({
...(await importOriginal<typeof import('../settings-section')>()),
SettingsSection: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
}));
const rights = {
mayReadItems: true, mayAddItems: true, mayRemoveItems: true, maySetSeen: true, maySetKeywords: true,
mayCreateChild: true, mayRename: true, mayDelete: true, maySubmit: true,
};
function makeMailbox(overrides: Partial<Mailbox>): Mailbox {
return {
id: 'mb', name: 'Folder', sortOrder: 0, totalEmails: 0, unreadEmails: 0, totalThreads: 0, unreadThreads: 0,
myRights: rights, isSubscribed: true, isShared: false, ...overrides,
} as Mailbox;
}
describe('FolderSettings row actions menu', () => {
beforeEach(() => {
useAuthStore.setState({ client: null } as never);
useSettingsStore.setState({ folderCountModes: {} } as never);
useEmailStore.setState({
mailboxes: [makeMailbox({ id: 'projects', name: 'Projects with a long name' })],
fetchMailboxes: vi.fn(),
} as never);
});
it('opens the row actions from a named ⋮ and sets the counter from it', () => {
render(<FolderSettings />);
expect(screen.getByTitle('Projects with a long name')).toBeTruthy();
fireEvent.click(screen.getByRole('button', { name: 'actions' }));
const menu = screen.getByRole('menu');
expect(within(menu).getByRole('menuitem', { name: 'create_subfolder' })).toBeTruthy();
expect(within(menu).getByRole('menuitem', { name: 'rename' })).toBeTruthy();
expect(within(menu).getByRole('menuitem', { name: 'delete' })).toBeTruthy();
fireEvent.click(within(menu).getByRole('menuitem', { name: 'counter' }));
fireEvent.click(screen.getByRole('menuitem', { name: 'count_mode_none' }));
expect(useSettingsStore.getState().folderCountModes).toEqual({ projects: 'none' });
});
it('opens the same menu on right-click and starts renaming from it', () => {
render(<FolderSettings />);
fireEvent.contextMenu(screen.getByTitle('Projects with a long name'), { clientX: 20, clientY: 20 });
fireEvent.click(screen.getByRole('menuitem', { name: 'rename' }));
expect((screen.getByDisplayValue('Projects with a long name') as HTMLInputElement).tagName).toBe('INPUT');
});
it('names the expand toggle of a folder with subfolders', () => {
useEmailStore.setState({
mailboxes: [
makeMailbox({ id: 'p', name: 'Parent' }),
makeMailbox({ id: 'c', name: 'Child', parentId: 'p' }),
],
} as never);
render(<FolderSettings />);
const toggle = screen.getByRole('button', { name: 'expand' });
expect(toggle.getAttribute('aria-expanded')).toBe('false');
});
});
+100 -36
View File
@@ -14,8 +14,12 @@ import {
Star, Heart, Bookmark, Tag, Flag, Briefcase, Users,
Bell, Zap, Globe, Lock, Eye, MessageSquare, Mail,
AlertTriangle, NotebookPen, CalendarClock, BellOff, CheckSquare, Square,
MoreVertical, Palette, ListOrdered,
type AppIcon,
} from '@/components/icons';
import { IconButton } from '@/components/ui/icon-button';
import { ContextMenu, ContextMenuItem, ContextMenuSeparator, ContextMenuSubMenu } from '@/components/ui/context-menu';
import { useContextMenu } from '@/hooks/use-context-menu';
import { cn, buildMailboxTree, flattenMailboxTree, type MailboxNode } from '@/lib/utils';
import { jmapErrorType } from '@/lib/jmap/jmap-error';
import {
@@ -201,6 +205,9 @@ export function FolderSettings() {
const [moveTarget, setMoveTarget] = useState('');
const [isMoving, setIsMoving] = useState(false);
// The row's actions: the ⋮ on the phone and right-click everywhere.
const { contextMenu, openContextMenu, openContextMenuFrom, closeContextMenu, menuRef } = useContextMenu<MailboxNode>();
const ownMailboxes = mailboxes.filter(mb => !mb.isShared);
const folderTree = buildMailboxTree(ownMailboxes);
@@ -502,7 +509,7 @@ export function FolderSettings() {
return (
<div
className="flex items-center gap-2 mt-1 p-2.5 bg-muted/30 rounded-md border border-border"
style={{ marginLeft: depth * 16 }}
style={{ marginInlineStart: depth * 16 }}
>
<FolderPlus className="w-4 h-4 text-primary flex-shrink-0" />
<div className="flex-1 flex flex-col gap-1">
@@ -563,7 +570,7 @@ export function FolderSettings() {
if (editingId === mb.id) {
return (
<div key={mb.id}>
<div className="flex items-center gap-2 py-2 px-3" style={{ paddingLeft: 12 + depth * 16 }}>
<div className="flex items-center gap-2 py-2 px-3" style={{ paddingInlineStart: 12 + depth * 16 }}>
<Icon className="w-4 h-4 text-muted-foreground flex-shrink-0" />
<input
type="text"
@@ -600,7 +607,7 @@ export function FolderSettings() {
if (deletingId === mb.id) {
return (
<div key={mb.id}>
<div className="flex items-center gap-3 py-2.5 px-3 bg-destructive/5 rounded-md border border-destructive/20" style={{ marginLeft: depth * 16 }}>
<div className="flex items-center gap-3 py-2.5 px-3 bg-destructive/5 rounded-md border border-destructive/20" style={{ marginInlineStart: depth * 16 }}>
<Trash2 className="w-4 h-4 text-destructive flex-shrink-0" />
<p className="text-sm text-foreground flex-1">
{t('confirm_delete', { name: mb.name })}
@@ -628,10 +635,14 @@ export function FolderSettings() {
<SortableFolderRow id={mb.id} title={t('reorder')}>
<div
className={cn(
"flex items-center justify-between py-2 px-3 rounded-md hover:bg-muted/50",
isSelected && "bg-muted",
"flex items-center justify-between gap-1 py-2 px-3 rounded-md hover:bg-muted/50",
isSelected && "bg-selection",
)}
style={{ paddingLeft: 12 + depth * 16 }}
style={{ paddingInlineStart: 12 + depth * 16 }}
onContextMenu={(e) => {
if ((e.target as HTMLElement).closest('input, select')) return;
openContextMenu(e, mb);
}}
>
<div className="flex items-center gap-2.5 min-w-0">
{mb.myRights?.mayRename ? (
@@ -659,15 +670,17 @@ export function FolderSettings() {
)}
{/* Expand/collapse toggle for folders with children */}
{hasChildren ? (
<button
<IconButton
label={isExpanded ? t('collapse', { name: mb.name }) : t('expand', { name: mb.name })}
aria-expanded={isExpanded}
onClick={() => toggleExpanded(mb.id)}
className="p-0.5 text-muted-foreground hover:text-foreground rounded transition-colors flex-shrink-0"
className="h-5 w-5 text-muted-foreground flex-shrink-0"
>
{isExpanded
? <ChevronDown className="w-3.5 h-3.5" />
: <ChevronRight className="w-3.5 h-3.5" />
}
</button>
</IconButton>
) : (
<span className="w-4.5 flex-shrink-0" />
)}
@@ -707,7 +720,7 @@ export function FolderSettings() {
/>
)}
</div>
<span className="text-sm text-foreground truncate">{mb.name}</span>
<span className="text-sm text-foreground truncate" title={mb.name} dir="auto">{mb.name}</span>
{mb.role && (
<span className="text-xs px-1.5 py-0.5 rounded-full bg-primary/10 text-primary font-medium flex-shrink-0">
{t(`role_${mb.role}`)}
@@ -719,48 +732,49 @@ export function FolderSettings() {
</span>
)}
</div>
<div className="flex items-center gap-0.5">
{/* Phone: the counter and the row actions don't fit next to the
name, so they sit behind a ⋮ (right-click opens it too). */}
<IconButton
label={t('actions', { name: mb.name })}
className="sm:hidden flex-shrink-0 text-muted-foreground"
onClick={(e) => openContextMenuFrom(e.currentTarget, mb, 'end')}
>
<MoreVertical />
</IconButton>
<div className="hidden sm:flex items-center gap-0.5 flex-shrink-0">
<Select
value={folderCountModes?.[mb.id] ?? ''}
onChange={(value) => {
const { [mb.id]: _, ...rest } = folderCountModes ?? {};
updateSetting('folderCountModes', isFolderCountMode(value) ? { ...rest, [mb.id]: value } : rest);
}}
onChange={(value) => setCountMode(mb.id, value)}
ariaLabel={t('count_mode', { name: mb.name })}
className="px-1.5 py-0.5 text-xs max-w-[9rem]"
options={[
{ value: '', label: t('count_mode_default') },
{ value: 'unread', label: t('count_mode_unread') },
{ value: 'all', label: t('count_mode_all') },
{ value: 'none', label: t('count_mode_none') },
]}
options={countModeOptions}
/>
{mb.myRights?.mayCreateChild && (
<button
<IconButton
label={t('create_subfolder')}
onClick={() => startCreateSubfolder(mb.id)}
className="p-1.5 text-muted-foreground hover:text-foreground hover:bg-accent rounded-md transition-colors"
title={t('create_subfolder')}
className="text-muted-foreground"
>
<FolderPlus className="w-3.5 h-3.5" />
</button>
<FolderPlus />
</IconButton>
)}
{mb.myRights?.mayRename && (
<button
<IconButton
label={t('rename')}
onClick={() => startEdit(mb)}
className="p-1.5 text-muted-foreground hover:text-foreground hover:bg-accent rounded-md transition-colors"
title={t('rename')}
className="text-muted-foreground"
>
<Pencil className="w-3.5 h-3.5" />
</button>
<Pencil />
</IconButton>
)}
{mb.myRights?.mayDelete && !mb.role && (
<button
<IconButton
label={t('delete')}
onClick={() => setDeletingId(mb.id)}
className="p-1.5 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded-md transition-colors"
title={t('delete')}
className="text-muted-foreground hover:text-destructive hover:bg-destructive/10"
>
<Trash2 className="w-3.5 h-3.5" />
</button>
<Trash2 />
</IconButton>
)}
</div>
</div>
@@ -771,8 +785,58 @@ export function FolderSettings() {
);
};
const countModeOptions = [
{ value: '', label: t('count_mode_default') },
{ value: 'unread', label: t('count_mode_unread') },
{ value: 'all', label: t('count_mode_all') },
{ value: 'none', label: t('count_mode_none') },
];
const setCountMode = (id: string, value: string) => {
const { [id]: _, ...rest } = folderCountModes ?? {};
updateSetting('folderCountModes', isFolderCountMode(value) ? { ...rest, [id]: value } : rest);
};
const renderRowMenu = () => {
const mb = contextMenu.data;
if (!mb) return null;
const current = folderCountModes?.[mb.id] ?? '';
const run = (fn: () => void) => () => { closeContextMenu(); fn(); };
const canDelete = mb.myRights?.mayDelete && !mb.role;
return (
<ContextMenu ref={menuRef} isOpen={contextMenu.isOpen} position={contextMenu.position} onClose={closeContextMenu}>
{mb.myRights?.mayCreateChild && (
<ContextMenuItem icon={FolderPlus} label={t('create_subfolder')} onClick={run(() => startCreateSubfolder(mb.id))} />
)}
{mb.myRights?.mayRename && (
<ContextMenuItem icon={Pencil} label={t('rename')} onClick={run(() => startEdit(mb))} />
)}
{folderIconsAllowed && (
<ContextMenuItem icon={Palette} label={t('change_icon')} onClick={run(() => setIconPickerId(mb.id))} />
)}
<ContextMenuSubMenu icon={ListOrdered} label={t('counter')}>
{countModeOptions.map((option) => (
<ContextMenuItem
key={option.value}
icon={current === option.value ? Check : undefined}
label={option.label}
onClick={run(() => setCountMode(mb.id, option.value))}
/>
))}
</ContextMenuSubMenu>
{canDelete && (
<>
<ContextMenuSeparator />
<ContextMenuItem icon={Trash2} label={t('delete')} destructive onClick={run(() => setDeletingId(mb.id))} />
</>
)}
</ContextMenu>
);
};
return (
<div className="space-y-8">
{renderRowMenu()}
{/* Folder List - primary section */}
<SettingsSection id="folders" title={t('folder_list')} description={t('folder_list_description')}>
{selectedCount > 0 && (
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "اسم المجلد",
"rename": "إعادة تسمية",
"change_icon": "تغيير الأيقونة",
"actions": "إجراءات {name}",
"expand": "توسيع {name}",
"collapse": "طي {name}",
"counter": "العداد",
"count_mode": "العداد لـ {name}",
"count_mode_default": "العداد: افتراضي",
"count_mode_unread": "غير المقروءة فقط",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "Nom de la carpeta",
"rename": "Canvia el nom",
"change_icon": "Canvia la icona",
"actions": "Accions per a {name}",
"expand": "Desplega {name}",
"collapse": "Plega {name}",
"counter": "Comptador",
"count_mode": "Comptador per a {name}",
"count_mode_default": "Comptador: per defecte",
"count_mode_unread": "Només no llegits",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Název složky",
"rename": "Přejmenovat",
"change_icon": "Změnit ikonu",
"actions": "Akce pro {name}",
"expand": "Rozbalit {name}",
"collapse": "Sbalit {name}",
"counter": "Počítadlo",
"count_mode": "Počítadlo pro {name}",
"count_mode_default": "Počítadlo: výchozí",
"count_mode_unread": "Jen nepřečtené",
+4
View File
@@ -2095,6 +2095,10 @@
"new_folder_name": "Mappenavn",
"rename": "Omdøb",
"change_icon": "Skift ikon",
"actions": "Handlinger for {name}",
"expand": "Fold {name} ud",
"collapse": "Fold {name} sammen",
"counter": "Tæller",
"count_mode": "Tæller for {name}",
"count_mode_default": "Tæller: standard",
"count_mode_unread": "Kun ulæste",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Ordnername",
"rename": "Umbenennen",
"change_icon": "Symbol ändern",
"actions": "Aktionen für {name}",
"expand": "{name} aufklappen",
"collapse": "{name} zuklappen",
"counter": "Zähler",
"count_mode": "Zähler für {name}",
"count_mode_default": "Zähler: Standard",
"count_mode_unread": "Nur ungelesene",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "Folder name",
"rename": "Rename",
"change_icon": "Change icon",
"actions": "Actions for {name}",
"expand": "Expand {name}",
"collapse": "Collapse {name}",
"counter": "Counter",
"count_mode": "Counter for {name}",
"count_mode_default": "Counter: default",
"count_mode_unread": "Unread only",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Nombre de la carpeta",
"rename": "Renombrar",
"change_icon": "Cambiar icono",
"actions": "Acciones para {name}",
"expand": "Expandir {name}",
"collapse": "Contraer {name}",
"counter": "Contador",
"count_mode": "Contador de {name}",
"count_mode_default": "Contador: predeterminado",
"count_mode_unread": "Solo no leídos",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "Kausta nimi",
"rename": "Nimeta ümber",
"change_icon": "Muuda ikooni",
"actions": "Toimingud: {name}",
"expand": "Laienda: {name}",
"collapse": "Ahenda: {name}",
"counter": "Loendur",
"count_mode": "Kausta {name} loendur",
"count_mode_default": "Loendur: vaikimisi",
"count_mode_unread": "Ainult lugemata",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "نام پوشه",
"rename": "تغییر نام",
"change_icon": "تغییر آیکون",
"actions": "کارها برای {name}",
"expand": "باز کردن {name}",
"collapse": "بستن {name}",
"counter": "شمارنده",
"count_mode": "شمارنده برای {name}",
"count_mode_default": "شمارنده: پیش‌فرض",
"count_mode_unread": "فقط خوانده‌نشده",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Nom du dossier",
"rename": "Renommer",
"change_icon": "Changer l'icône",
"actions": "Actions pour {name}",
"expand": "Développer {name}",
"collapse": "Réduire {name}",
"counter": "Compteur",
"count_mode": "Compteur pour {name}",
"count_mode_default": "Compteur : par défaut",
"count_mode_unread": "Non lus uniquement",
+4
View File
@@ -2056,6 +2056,10 @@
"new_folder_name": "שם התיקיה",
"rename": "שנה שם",
"change_icon": "שנה סמל",
"actions": "פעולות עבור {name}",
"expand": "הרחבת {name}",
"collapse": "כיווץ {name}",
"counter": "מונה",
"count_mode": "מונה עבור {name}",
"count_mode_default": "מונה: ברירת מחדל",
"count_mode_unread": "רק שלא נקראו",
+4
View File
@@ -2095,6 +2095,10 @@
"new_folder_name": "Mappa neve",
"rename": "Átnevezés",
"change_icon": "Ikon módosítása",
"actions": "{name} – műveletek",
"expand": "{name} kibontása",
"collapse": "{name} összecsukása",
"counter": "Számláló",
"count_mode": "Számláló: {name}",
"count_mode_default": "Számláló: alapértelmezett",
"count_mode_unread": "Csak olvasatlan",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Nome della cartella",
"rename": "Rinomina",
"change_icon": "Cambia icona",
"actions": "Azioni per {name}",
"expand": "Espandi {name}",
"collapse": "Comprimi {name}",
"counter": "Contatore",
"count_mode": "Contatore per {name}",
"count_mode_default": "Contatore: predefinito",
"count_mode_unread": "Solo non letti",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "フォルダー名",
"rename": "名前を変更",
"change_icon": "アイコンを変更",
"actions": "{name} の操作",
"expand": "{name} を展開",
"collapse": "{name} を折りたたむ",
"counter": "カウンター",
"count_mode": "{name} のカウンター",
"count_mode_default": "カウンター: 既定",
"count_mode_unread": "未読のみ",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "폴더 이름",
"rename": "이름 바꾸기",
"change_icon": "아이콘 바꾸기",
"actions": "{name} 작업",
"expand": "{name} 펼치기",
"collapse": "{name} 접기",
"counter": "카운터",
"count_mode": "{name} 카운터",
"count_mode_default": "카운터: 기본값",
"count_mode_unread": "읽지 않음만",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Mapes nosaukums",
"rename": "Pārdēvēt",
"change_icon": "Mainīt ikonu",
"actions": "Darbības: {name}",
"expand": "Izvērst: {name}",
"collapse": "Sakļaut: {name}",
"counter": "Skaitītājs",
"count_mode": "Skaitītājs mapei {name}",
"count_mode_default": "Skaitītājs: noklusējums",
"count_mode_unread": "Tikai nelasītie",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "Хавтасны нэр",
"rename": "Нэрээ өөрчлөх",
"change_icon": " Дүрсийг өөрчлөх",
"actions": "{name}-ийн үйлдлүүд",
"expand": "{name}-ийг дэлгэх",
"collapse": "{name}-ийг хураах",
"counter": "Тоолуур",
"count_mode": "{name}-ийн тоолуур",
"count_mode_default": "Тоолуур: үндсэн",
"count_mode_unread": "Зөвхөн уншаагүй",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "Mappenavn",
"rename": "Gi nytt navn",
"change_icon": "Endre ikon",
"actions": "Handlinger for {name}",
"expand": "Vis innholdet i {name}",
"collapse": "Skjul innholdet i {name}",
"counter": "Teller",
"count_mode": "Teller for {name}",
"count_mode_default": "Teller: standard",
"count_mode_unread": "Bare uleste",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Mapnaam",
"rename": "Hernoemen",
"change_icon": "Pictogram wijzigen",
"actions": "Acties voor {name}",
"expand": "{name} uitvouwen",
"collapse": "{name} samenvouwen",
"counter": "Teller",
"count_mode": "Teller voor {name}",
"count_mode_default": "Teller: standaard",
"count_mode_unread": "Alleen ongelezen",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Nazwa folderu",
"rename": "Zmień nazwę",
"change_icon": "Zmień ikonę",
"actions": "Działania dla {name}",
"expand": "Rozwiń {name}",
"collapse": "Zwiń {name}",
"counter": "Licznik",
"count_mode": "Licznik dla {name}",
"count_mode_default": "Licznik: domyślny",
"count_mode_unread": "Tylko nieprzeczytane",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Nome da pasta",
"rename": "Renomear",
"change_icon": "Alterar ícone",
"actions": "Ações para {name}",
"expand": "Expandir {name}",
"collapse": "Recolher {name}",
"counter": "Contador",
"count_mode": "Contador de {name}",
"count_mode_default": "Contador: padrão",
"count_mode_unread": "Apenas não lidas",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "Numele folderului",
"rename": "Redenumire",
"change_icon": "Schimbă pictograma",
"actions": "Acțiuni pentru {name}",
"expand": "Extinde {name}",
"collapse": "Restrânge {name}",
"counter": "Contor",
"count_mode": "Contor pentru {name}",
"count_mode_default": "Contor: implicit",
"count_mode_unread": "Doar necitite",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Название папки",
"rename": "Переименовать",
"change_icon": "Изменить значок",
"actions": "Действия для «{name}»",
"expand": "Развернуть «{name}»",
"collapse": "Свернуть «{name}»",
"counter": "Счётчик",
"count_mode": "Счётчик для {name}",
"count_mode_default": "Счётчик: по умолчанию",
"count_mode_unread": "Только непрочитанные",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "Názov priečinka",
"rename": "Premenovať",
"change_icon": "Zmeniť ikonu",
"actions": "Akcie pre {name}",
"expand": "Rozbaliť {name}",
"collapse": "Zbaliť {name}",
"counter": "Počítadlo",
"count_mode": "Počítadlo pre {name}",
"count_mode_default": "Počítadlo: predvolené",
"count_mode_unread": "Len neprečítané",
+4
View File
@@ -3957,6 +3957,10 @@
"new_folder_name": "ชื่อโฟลเดอร์",
"rename": "เปลี่ยนชื่อ",
"change_icon": "เปลี่ยนไอคอน",
"actions": "การทำงานสำหรับ {name}",
"expand": "ขยาย {name}",
"collapse": "ยุบ {name}",
"counter": "ตัวนับ",
"count_mode": "ตัวนับสำหรับ {name}",
"count_mode_default": "ตัวนับ: ค่าเริ่มต้น",
"count_mode_unread": "เฉพาะที่ยังไม่ได้อ่าน",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Klasör adı",
"rename": "Yeniden Adlandır",
"change_icon": "Simgeyi değiştir",
"actions": "{name} için işlemler",
"expand": "{name} klasörünü genişlet",
"collapse": "{name} klasörünü daralt",
"counter": "Sayaç",
"count_mode": "{name} sayacı",
"count_mode_default": "Sayaç: varsayılan",
"count_mode_unread": "Yalnızca okunmamış",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "Назва папки",
"rename": "Перейменувати",
"change_icon": "Змінити значок",
"actions": "Дії для «{name}»",
"expand": "Розгорнути «{name}»",
"collapse": "Згорнути «{name}»",
"counter": "Лічильник",
"count_mode": "Лічильник для {name}",
"count_mode_default": "Лічильник: типово",
"count_mode_unread": "Лише непрочитані",
+4
View File
@@ -2099,6 +2099,10 @@
"new_folder_name": "信件匣名稱",
"rename": "重新命名",
"change_icon": "變更圖示",
"actions": "{name} 的動作",
"expand": "展開 {name}",
"collapse": "摺疊 {name}",
"counter": "計數",
"count_mode": "{name} 的計數",
"count_mode_default": "計數:預設",
"count_mode_unread": "僅未讀",
+4
View File
@@ -2092,6 +2092,10 @@
"new_folder_name": "文件夹名称",
"rename": "重命名",
"change_icon": "更改图标",
"actions": "{name} 的操作",
"expand": "展开 {name}",
"collapse": "折叠 {name}",
"counter": "计数",
"count_mode": "{name} 的计数",
"count_mode_default": "计数:默认",
"count_mode_unread": "仅未读",