diff --git a/components/layout/__tests__/sidebar-your-folders.test.tsx b/components/layout/__tests__/sidebar-your-folders.test.tsx new file mode 100644 index 000000000..b53d31e78 --- /dev/null +++ b/components/layout/__tests__/sidebar-your-folders.test.tsx @@ -0,0 +1,150 @@ +import { render, screen, fireEvent, cleanup } from '@testing-library/react'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; +import type { Mailbox } from '@/lib/jmap/types'; + +// #1205: the folders the user made get a "Your folders" section of their own +// below the system folders, instead of being mixed in with Inbox, Sent and +// Trash. Users with no folders of their own see no change. + +vi.mock('@/components/plugins/plugin-slot', () => ({ PluginSlot: () => null })); +vi.mock('@/components/tour/tour-provider', () => ({ + useTour: () => ({ startTour: vi.fn(), resetTourCompletion: vi.fn(), activeTour: null, endTour: vi.fn(), registerStep: vi.fn() }), +})); +vi.mock('@/contexts/drag-drop-context', () => ({ + useDragDropContext: () => ({ isDragging: false }), +})); +vi.mock('@/hooks/use-mailbox-drop', () => ({ + useMailboxDrop: () => ({ dropHandlers: {}, isValidDropTarget: false, isInvalidDropTarget: false }), +})); +vi.mock('@/hooks/use-tag-drop', () => ({ + useTagDrop: () => ({ dropHandlers: {}, isValidDropTarget: false }), +})); +vi.mock('../account-switcher', () => ({ AccountSwitcher: () => null })); + +const { Sidebar } = await import('../sidebar'); +const { useSettingsStore } = await import('@/stores/settings-store'); +const { useUIStore } = await import('@/stores/ui-store'); +const { useAccountStore } = await import('@/stores/account-store'); +const { useAuthStore } = await import('@/stores/auth-store'); + +const box = (id: string, name: string, role: string | null, sortOrder: number, parentId: string | null = null) => + ({ id, name, role, parentId, totalEmails: 0, unreadEmails: 0, sortOrder, myRights: { mayAddItems: true } }); + +const systemOnly = [ + box('inbox', 'Inbox', 'inbox', 0), + box('drafts', 'Drafts', 'drafts', 1), + box('sent', 'Sent', 'sent', 2), + box('trash', 'Trash', 'trash', 3), +]; +const withCustom = [ + ...systemOnly, + box('receipts', 'Receipts', null, 4), + box('projects', 'Projects', null, 5), + box('inbox-sub', 'Newsletters', null, 6, 'inbox'), +] as unknown as Mailbox[]; + +const folderRow = (name: string) => document.querySelector(`[data-folder-name="${name}"]`); +const inYourFolders = (name: string) => + document.querySelector(`[data-testid="section-your-folders"] [data-folder-name="${name}"]`); + +describe('Sidebar "Your folders" section (#1205)', () => { + beforeEach(() => { + localStorage.clear(); + useUIStore.setState({ sidebarCollapsed: false } as never); + useAccountStore.setState({ accounts: [] } as never); + useSettingsStore.setState({ + emailKeywords: [], + enableUnifiedMailbox: false, + hideAccountSwitcher: true, + } as never); + }); + + it('lists the folders you made under their own heading, apart from the system folders', () => { + render(); + + expect(screen.getByText('your_folders')).toBeInTheDocument(); + expect(inYourFolders('Receipts')).not.toBeNull(); + expect(inYourFolders('Projects')).not.toBeNull(); + for (const name of ['Inbox', 'Drafts', 'Sent', 'Trash']) { + expect(folderRow(name)).not.toBeNull(); + expect(inYourFolders(name)).toBeNull(); + } + // The system folders all come before the first folder of your own. + const rows = [...document.querySelectorAll('[data-folder-name]')].map((r) => r.getAttribute('data-folder-name')); + expect(rows.indexOf('Trash')).toBeLessThan(rows.indexOf('Receipts')); + }); + + it('keeps a folder nested under a system folder with its parent', () => { + localStorage.setItem('expandedMailboxes', JSON.stringify(['inbox'])); + render(); + + expect(folderRow('Newsletters')).not.toBeNull(); + expect(inYourFolders('Newsletters')).toBeNull(); + }); + + it('shows no section when there are no folders of your own', () => { + render(); + + expect(screen.queryByText('your_folders')).toBeNull(); + expect(document.querySelector('[data-testid="section-your-folders"]')).toBeNull(); + expect(folderRow('Trash')).not.toBeNull(); + }); + + it('collapses on its own and remembers it', () => { + render(); + + fireEvent.click(screen.getByText('your_folders')); + expect(folderRow('Receipts')).toBeNull(); + // The system folders are untouched. + expect(folderRow('Inbox')).not.toBeNull(); + + cleanup(); + render(); + expect(screen.getByText('your_folders')).toBeInTheDocument(); + expect(folderRow('Receipts')).toBeNull(); + + fireEvent.click(screen.getByText('your_folders')); + expect(folderRow('Receipts')).not.toBeNull(); + }); + + it('creates a new folder from the heading', () => { + const onCreateFolder = vi.fn(); + render(); + + fireEvent.click(screen.getByLabelText('create_folder')); + expect(onCreateFolder).toHaveBeenCalledTimes(1); + // The click does not also fold the section away. + expect(folderRow('Receipts')).not.toBeNull(); + }); + + it('leaves Mountain View with its Labels list', () => { + render(); + + expect(screen.queryByText('your_folders')).toBeNull(); + expect(document.querySelector('[data-mv-labels] [data-folder-name="Receipts"]')).not.toBeNull(); + }); + + it('splits every account group in the Pro layout', () => { + const account = (id: string) => ({ + id, label: `${id}@example.com`, email: `${id}@example.com`, username: `${id}@example.com`, + cookieSlot: id === 'a' ? 0 : 1, isConnected: true, + }); + useAccountStore.setState({ accounts: [account('a'), account('b')] } as never); + useAuthStore.setState({ activeAccountId: 'a' } as never); + const other = [box('b-inbox', 'Inbox', 'inbox', 0), box('b-clients', 'Clients', null, 1)] as unknown as Mailbox[]; + + render( + , + ); + + expect(screen.getAllByText('your_folders')).toHaveLength(2); + expect(inYourFolders('Receipts')).not.toBeNull(); + expect(inYourFolders('Clients')).not.toBeNull(); + expect(inYourFolders('Inbox')).toBeNull(); + + // Each account's section folds on its own. + fireEvent.click(screen.getByTestId('section-your-folders-header-b')); + expect(folderRow('Clients')).toBeNull(); + expect(folderRow('Receipts')).not.toBeNull(); + }); +}); diff --git a/components/layout/sidebar.tsx b/components/layout/sidebar.tsx index 4a11dc6fa..6991daabd 100644 --- a/components/layout/sidebar.tsx +++ b/components/layout/sidebar.tsx @@ -447,6 +447,11 @@ function SidebarRow({ ); } +/** A folder the server gave a role (inbox, sent, trash...), as opposed to one the user made. */ +const isSystemFolder = (node: MailboxNode) => !!node.role; +/** Key of the single-account "Your folders" section in the collapsed set. */ +const OWN_FOLDERS_KEY = '__own__'; + function SidebarSectionHeader({ label, expanded, @@ -460,12 +465,16 @@ function SidebarSectionHeader({ testId, onContextMenu, status, + onAdd, + addTitle, }: { label: string; expanded: boolean; onToggle: () => void; onSettings?: () => void; settingsTitle?: string; + onAdd?: () => void; + addTitle?: string; isCollapsed: boolean; first?: boolean; icon?: ReactNode; @@ -508,6 +517,28 @@ function SidebarSectionHeader({ {label} {status} + {onAdd && ( + { + e.stopPropagation(); + onAdd(); + }} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + e.stopPropagation(); + onAdd(); + } + }} + className="ms-auto p-1 rounded text-muted-foreground/70 hover:text-foreground hover:bg-muted transition-colors cursor-pointer" + title={addTitle} + aria-label={addTitle} + > + + + )} {onSettings && ( @@ -966,6 +997,15 @@ function SidebarImpl({ } catch { /* fall through */ } return new Set(); }); + // "Your folders" sections the user has collapsed: OWN_FOLDERS_KEY for the + // single-account list, the accountId for each Pro account group. + const [collapsedCustomFolders, setCollapsedCustomFolders] = useState>(() => { + try { + const stored = localStorage.getItem('sidebarCollapsedCustomFolders'); + if (stored !== null) return new Set(JSON.parse(stored) as string[]); + } catch { /* fall through */ } + return new Set(); + }); const emailKeywords = useSettingsStore(s => s.emailKeywords); const nestedTags = useSettingsStore(s => s.nestedTags); const isEmbedded = useIsEmbedded(); @@ -1102,7 +1142,12 @@ function SidebarImpl({ const mvFlat = mvShell && !isCollapsed; const isPrimaryFolder = (node: MailboxNode) => node.role === 'inbox' || node.role === 'sent' || node.role === 'drafts'; - const primaryTree = mvFlat ? ownTree.filter(isPrimaryFolder) : ownTree; + // Everywhere else the folders the user made sit in a "Your folders" section + // of their own below the system folders (#1205). Folders nested under a + // system folder stay with their parent. With no folders of your own there is + // no section, so the list looks as it always did. + const primaryTree = mvFlat ? ownTree.filter(isPrimaryFolder) : ownTree.filter(isSystemFolder); + const customTree = mvFlat ? [] : ownTree.filter((node) => !isSystemFolder(node)); const secondaryTree = mvFlat ? ownTree.filter((node) => !isPrimaryFolder(node)) : []; // Of those, the system folders (archive, spam, trash...) go behind "More", // and the folders the user made are listed with the tags under "Labels", @@ -1185,6 +1230,59 @@ function SidebarImpl({ ); }; + // The "Your folders" section: the user's own top-level folders, under a + // heading of their own that collapses and offers to make a new one. + const renderCustomFolders = ( + key: string, + tree: MailboxNode[], + { + sub = false, + selected, + onSelect, + active = true, + dragAccountId, + }: { + sub?: boolean; + selected: string; + onSelect?: (mailboxId: string) => void; + active?: boolean; + dragAccountId?: string | null; + }, + ) => { + if (tree.length === 0) return null; + const expanded = !collapsedCustomFolders.has(key); + return ( + // A Pro account group already carries the folders menu for the whole group. +
+ toggleCustomFolders(key)} + onAdd={active && onCreateFolder ? () => onCreateFolder() : undefined} + addTitle={t("create_folder")} + isCollapsed={isCollapsed} + sub={sub} + testId={`section-your-folders-header-${key}`} + /> + {((expanded && !isCollapsed) || isCollapsed) && tree.map((node) => ( + + ))} +
+ ); + }; + const getUnifiedIcon = (role: UnifiedMailboxRole) => { switch (role) { case 'inbox': return Inbox; @@ -1278,6 +1376,14 @@ function SidebarImpl({ return next; }); }; + const toggleCustomFolders = (key: string) => { + setCollapsedCustomFolders((prev) => { + const next = new Set(prev); + if (next.has(key)) next.delete(key); else next.add(key); + try { localStorage.setItem('sidebarCollapsedCustomFolders', JSON.stringify(Array.from(next))); } catch { /* */ } + return next; + }); + }; // The tab now travels in the URL (#733) rather than through sessionStorage, // so a gear click is a link the user can also bookmark or share. It still @@ -1516,7 +1622,7 @@ function SidebarImpl({ ) : ( <> - {tree.map((node) => ( + {tree.filter(isSystemFolder).map((node) => ( ))} {isActive && !tree.some((node) => node.role === 'drafts') && renderScheduledRow(`scheduled-${account.id}`)} + {renderCustomFolders(account.id, tree.filter((node) => !isSystemFolder(node)), { + sub: true, + selected: selectedKeyword || !isViewing ? "" : selectedMailbox, + onSelect: (mailboxId) => onAccountMailboxSelect?.(isActive ? null : account.id, mailboxId), + active: isActive, + dragAccountId: isActive ? null : account.id, + })} )} @@ -1628,6 +1741,11 @@ function SidebarImpl({ )} + {!useMultiAccount && renderCustomFolders(OWN_FOLDERS_KEY, customTree, { + selected: selectedKeyword ? "" : selectedMailbox, + onSelect: onMailboxSelect, + })} + {mvFlat && !useMultiAccount && (
diff --git a/locales/ar/common.json b/locales/ar/common.json index 52e7c4ae3..6c101f061 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -142,6 +142,8 @@ "show_all_tags": "إظهار الكل ({count})", "show_fewer_tags": "إظهار أقل", "folders": "المجلدات", + "your_folders": "مجلداتك", + "create_folder": "إنشاء مجلد", "show_more": "المزيد", "show_fewer": "أقل", "shared": "مشترك", diff --git a/locales/ca/common.json b/locales/ca/common.json index b66f0d338..886564d80 100644 --- a/locales/ca/common.json +++ b/locales/ca/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Mostra-ho tot ({count})", "show_fewer_tags": "Mostra'n menys", "folders": "Carpetes", + "your_folders": "Les teves carpetes", + "create_folder": "Crea una carpeta", "show_more": "Més", "show_fewer": "Menys", "shared": "Compartit", diff --git a/locales/cs/common.json b/locales/cs/common.json index d9f14d837..b7f8ea9ba 100644 --- a/locales/cs/common.json +++ b/locales/cs/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Zobrazit vše ({count})", "show_fewer_tags": "Zobrazit méně", "folders": "Složky", + "your_folders": "Vaše složky", + "create_folder": "Vytvořit složku", "show_more": "Více", "show_fewer": "Méně", "shared": "Sdílené", diff --git a/locales/da/common.json b/locales/da/common.json index c406e216e..51c8ceec0 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Vis alle ({count})", "show_fewer_tags": "Vis færre", "folders": "Mapper", + "your_folders": "Dine mapper", + "create_folder": "Opret mappe", "show_more": "Mere", "show_fewer": "Mindre", "shared": "Delt", diff --git a/locales/de/common.json b/locales/de/common.json index df865c10d..de27864a8 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Alle anzeigen ({count})", "show_fewer_tags": "Weniger anzeigen", "folders": "Ordner", + "your_folders": "Eigene Ordner", + "create_folder": "Ordner erstellen", "show_more": "Mehr", "show_fewer": "Weniger", "mail": "E-Mail", diff --git a/locales/en/common.json b/locales/en/common.json index 89021953b..db28c520e 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Show all ({count})", "show_fewer_tags": "Show less", "folders": "Folders", + "your_folders": "Your folders", + "create_folder": "Create folder", "show_more": "More", "show_fewer": "Less", "shared": "Shared", diff --git a/locales/es/common.json b/locales/es/common.json index 451be606f..2abec1cfc 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Mostrar todo ({count})", "show_fewer_tags": "Mostrar menos", "folders": "Carpetas", + "your_folders": "Tus carpetas", + "create_folder": "Crear carpeta", "show_more": "Más", "show_fewer": "Menos", "mail": "Correo", diff --git a/locales/fa/common.json b/locales/fa/common.json index 2803e2e97..eae1ce922 100644 --- a/locales/fa/common.json +++ b/locales/fa/common.json @@ -142,6 +142,8 @@ "show_all_tags": "نمایش همه ({count})", "show_fewer_tags": "نمایش کمتر", "folders": "پوشه‌ها", + "your_folders": "پوشه‌های شما", + "create_folder": "ایجاد پوشه", "show_more": "بیشتر", "show_fewer": "کمتر", "shared": "اشتراکی", diff --git a/locales/fr/common.json b/locales/fr/common.json index ae4ea1299..87b1ff2ac 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Tout afficher ({count})", "show_fewer_tags": "Afficher moins", "folders": "Dossiers", + "your_folders": "Vos dossiers", + "create_folder": "Créer un dossier", "show_more": "Plus", "show_fewer": "Moins", "mail": "Messagerie", diff --git a/locales/he/common.json b/locales/he/common.json index 55f9c4739..82dcdf9e0 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -133,6 +133,8 @@ "show_all_tags": "הצג הכל ({count})", "show_fewer_tags": "הצג פחות", "folders": "תיקיות", + "your_folders": "התיקיות שלך", + "create_folder": "יצירת תיקייה", "show_more": "עוד", "show_fewer": "פחות", "mail": "דוֹאַר", diff --git a/locales/hu/common.json b/locales/hu/common.json index 5622e3d09..f74e81b4d 100644 --- a/locales/hu/common.json +++ b/locales/hu/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Összes megjelenítése ({count})", "show_fewer_tags": "Kevesebb megjelenítése", "folders": "Mappák", + "your_folders": "Saját mappák", + "create_folder": "Mappa létrehozása", "show_more": "Több", "show_fewer": "Kevesebb", "shared": "Megosztott", diff --git a/locales/it/common.json b/locales/it/common.json index 0bfa4e586..84510e66f 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Mostra tutto ({count})", "show_fewer_tags": "Mostra meno", "folders": "Cartelle", + "your_folders": "Le tue cartelle", + "create_folder": "Crea cartella", "show_more": "Altro", "show_fewer": "Riduci", "mail": "Posta", diff --git a/locales/ja/common.json b/locales/ja/common.json index 5285f6b64..47dda8a18 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -142,6 +142,8 @@ "show_all_tags": "すべて表示({count})", "show_fewer_tags": "表示を減らす", "folders": "フォルダ", + "your_folders": "マイフォルダ", + "create_folder": "フォルダを作成", "show_more": "もっと見る", "show_fewer": "折りたたむ", "mail": "メール", diff --git a/locales/ko/common.json b/locales/ko/common.json index 4946d2e3f..da0157508 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -142,6 +142,8 @@ "show_all_tags": "전체 보기({count})", "show_fewer_tags": "간략히 보기", "folders": "폴더", + "your_folders": "내 폴더", + "create_folder": "폴더 만들기", "show_more": "더보기", "show_fewer": "간략히", "mail": "메일", diff --git a/locales/lv/common.json b/locales/lv/common.json index dcd00a33d..4688d0c4a 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Rādīt visus ({count})", "show_fewer_tags": "Rādīt mazāk", "folders": "Mapes", + "your_folders": "Jūsu mapes", + "create_folder": "Izveidot mapi", "show_more": "Vairāk", "show_fewer": "Mazāk", "mail": "Pasts", diff --git a/locales/mn/common.json b/locales/mn/common.json index f90defdcc..d7d316662 100644 --- a/locales/mn/common.json +++ b/locales/mn/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Бүгдийг нь харуулах ({count})", "show_fewer_tags": "Бага харуулах", "folders": "Хавтас", + "your_folders": "Таны хавтаснууд", + "create_folder": "Хавтас үүсгэх", "show_more": "Илүү", "show_fewer": "Бага", "shared": "Хуваалцсан", diff --git a/locales/nb/common.json b/locales/nb/common.json index aaa8816da..ba60ece05 100644 --- a/locales/nb/common.json +++ b/locales/nb/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Vis alle ({count})", "show_fewer_tags": "Vis færre", "folders": "Mapper", + "your_folders": "Dine mapper", + "create_folder": "Opprett mappe", "show_more": "Mer", "show_fewer": "Mindre", "shared": "Delt", diff --git a/locales/nl/common.json b/locales/nl/common.json index bef09aa9b..c4665b4b8 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Alles tonen ({count})", "show_fewer_tags": "Minder tonen", "folders": "Mappen", + "your_folders": "Je mappen", + "create_folder": "Map maken", "show_more": "Meer", "show_fewer": "Minder", "mail": "E-mail", diff --git a/locales/pl/common.json b/locales/pl/common.json index a88c5b2b6..2f156f834 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Pokaż wszystkie ({count})", "show_fewer_tags": "Pokaż mniej", "folders": "Foldery", + "your_folders": "Twoje foldery", + "create_folder": "Utwórz folder", "show_more": "Więcej", "show_fewer": "Mniej", "mail": "Poczta", diff --git a/locales/pt/common.json b/locales/pt/common.json index 844ed196d..484f0e9a1 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Mostrar tudo ({count})", "show_fewer_tags": "Mostrar menos", "folders": "Pastas", + "your_folders": "As suas pastas", + "create_folder": "Criar pasta", "show_more": "Mais", "show_fewer": "Menos", "mail": "E-mail", diff --git a/locales/ro/common.json b/locales/ro/common.json index 0d346fba7..d7c130bf2 100644 --- a/locales/ro/common.json +++ b/locales/ro/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Afișează tot ({count})", "show_fewer_tags": "Afișează mai puține", "folders": "Dosare", + "your_folders": "Dosarele tale", + "create_folder": "Creează dosar", "show_more": "Mai multe", "show_fewer": "Mai puține", "shared": "Partajat", diff --git a/locales/ru/common.json b/locales/ru/common.json index 9c5b9a018..b01cc0775 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Показать все ({count})", "show_fewer_tags": "Показать меньше", "folders": "Папки", + "your_folders": "Ваши папки", + "create_folder": "Создать папку", "show_more": "Ещё", "show_fewer": "Свернуть", "mail": "Почта", diff --git a/locales/sk/common.json b/locales/sk/common.json index 7cc66a8f3..a57c46912 100644 --- a/locales/sk/common.json +++ b/locales/sk/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Zobraziť všetko ({count})", "show_fewer_tags": "Zobraziť menej", "folders": "Priečinky", + "your_folders": "Vaše priečinky", + "create_folder": "Vytvoriť priečinok", "show_more": "Viac", "show_fewer": "Menej", "shared": "Zdieľané", diff --git a/locales/tr/common.json b/locales/tr/common.json index e68ef8d08..e906053b8 100644 --- a/locales/tr/common.json +++ b/locales/tr/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Tümünü göster ({count})", "show_fewer_tags": "Daha az göster", "folders": "Klasörler", + "your_folders": "Klasörleriniz", + "create_folder": "Klasör oluştur", "show_more": "Diğer", "show_fewer": "Daha az", "shared": "Paylaşılan", diff --git a/locales/uk/common.json b/locales/uk/common.json index d83acfc7e..296480cb6 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -142,6 +142,8 @@ "show_all_tags": "Показати всі ({count})", "show_fewer_tags": "Показати менше", "folders": "Папки", + "your_folders": "Ваші теки", + "create_folder": "Створити теку", "show_more": "Більше", "show_fewer": "Менше", "mail": "Пошта", diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json index 5e5e562bd..edb372a62 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -142,6 +142,8 @@ "show_all_tags": "顯示全部({count})", "show_fewer_tags": "顯示較少", "folders": "信件匣", + "your_folders": "我的資料夾", + "create_folder": "建立資料夾", "show_more": "更多", "show_fewer": "收合", "shared": "共用", diff --git a/locales/zh/common.json b/locales/zh/common.json index deb193881..34fc9d1f0 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -142,6 +142,8 @@ "show_all_tags": "显示全部({count})", "show_fewer_tags": "收起", "folders": "文件夹", + "your_folders": "我的文件夹", + "create_folder": "新建文件夹", "show_more": "更多", "show_fewer": "收起", "mail": "邮件",