diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index 90ddd3f2..d3797799 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -24,6 +24,7 @@ import { useDeviceDetection } from "@/hooks/use-media-query"; import { useKeyboardShortcuts } from "@/hooks/use-keyboard-shortcuts"; import { useRefreshGesture } from "@/hooks/use-refresh-gesture"; import { useConfirmDialog } from "@/hooks/use-confirm-dialog"; +import { usePromptDialog } from "@/hooks/use-prompt-dialog"; import { useBrowserNavigation, type NavSnapshot } from "@/hooks/use-browser-navigation"; import { debug } from "@/lib/debug"; import { playNotificationSound } from "@/lib/notification-sound"; @@ -36,6 +37,7 @@ import { ComposerErrorFallback, } from "@/components/error"; import { ConfirmDialog } from "@/components/ui/confirm-dialog"; +import { PromptDialog } from "@/components/ui/prompt-dialog"; import { TotpReauthDialog } from "@/components/totp-reauth-dialog"; import { DragDropProvider } from "@/contexts/drag-drop-context"; import { isFilterEmpty, activeFilterCount } from "@/lib/jmap/search-utils"; @@ -68,6 +70,7 @@ export default function Home() { const [pendingDraft, setPendingDraft] = useState(null); const [composerSessionId, setComposerSessionId] = useState(0); const { dialogProps: confirmDialogProps, confirm: confirmDialog } = useConfirmDialog(); + const { dialogProps: promptDialogProps, prompt: promptDialog } = usePromptDialog(); const { showAppsModal, inlineApp, loadedApps, handleManageApps, handleInlineApp, closeInlineApp, closeAppsModal } = useSidebarApps(); const [initialCheckDone, setInitialCheckDone] = useState(() => useAuthStore.getState().isAuthenticated && !!useAuthStore.getState().client); const [showShortcutsModal, setShowShortcutsModal] = useState(false); @@ -1204,10 +1207,15 @@ export default function Home() { const handleCreateSubfolderFromContextMenu = async (parentId: string) => { if (!client) return; - const name = window.prompt(tCtxMenu('mailbox_context_menu.prompt_new_subfolder')); - if (!name || !name.trim()) return; + const name = await promptDialog({ + title: tCtxMenu('mailbox_context_menu.new_subfolder'), + message: tCtxMenu('mailbox_context_menu.prompt_new_subfolder'), + placeholder: tCtxMenu('mailbox_context_menu.placeholder_folder_name'), + confirmText: tCtxMenu('mailbox_context_menu.create'), + }); + if (!name) return; try { - await createMailbox(client, name.trim(), parentId); + await createMailbox(client, name, parentId); toast.success(tCtxMenu('mailbox_context_menu.toast_folder_created')); } catch { toast.error(tCtxMenu('mailbox_context_menu.toast_error_create')); @@ -1216,10 +1224,15 @@ export default function Home() { const handleCreateFolderFromContextMenu = async () => { if (!client) return; - const name = window.prompt(tCtxMenu('mailbox_context_menu.prompt_new_folder')); - if (!name || !name.trim()) return; + const name = await promptDialog({ + title: tCtxMenu('mailbox_context_menu.new_folder'), + message: tCtxMenu('mailbox_context_menu.prompt_new_folder'), + placeholder: tCtxMenu('mailbox_context_menu.placeholder_folder_name'), + confirmText: tCtxMenu('mailbox_context_menu.create'), + }); + if (!name) return; try { - await createMailbox(client, name.trim()); + await createMailbox(client, name); toast.success(tCtxMenu('mailbox_context_menu.toast_folder_created')); } catch { toast.error(tCtxMenu('mailbox_context_menu.toast_error_create')); @@ -1230,10 +1243,16 @@ export default function Home() { if (!client) return; const mailbox = mailboxes.find(mb => mb.id === mailboxId); if (!mailbox) return; - const name = window.prompt(tCtxMenu('mailbox_context_menu.prompt_rename'), mailbox.name); - if (!name || !name.trim() || name.trim() === mailbox.name) return; + const name = await promptDialog({ + title: tCtxMenu('mailbox_context_menu.rename'), + message: tCtxMenu('mailbox_context_menu.prompt_rename'), + placeholder: tCtxMenu('mailbox_context_menu.placeholder_folder_name'), + defaultValue: mailbox.name, + confirmText: tCtxMenu('mailbox_context_menu.rename_confirm'), + }); + if (!name || name === mailbox.name) return; try { - await renameMailbox(client, mailboxId, name.trim()); + await renameMailbox(client, mailboxId, name); toast.success(tCtxMenu('mailbox_context_menu.toast_folder_renamed')); } catch { toast.error(tCtxMenu('mailbox_context_menu.toast_error_rename')); @@ -2195,6 +2214,7 @@ export default function Home() { + diff --git a/components/ui/prompt-dialog.tsx b/components/ui/prompt-dialog.tsx new file mode 100644 index 00000000..48effdba --- /dev/null +++ b/components/ui/prompt-dialog.tsx @@ -0,0 +1,126 @@ +"use client"; + +import { useEffect, useId, useRef, useState } from "react"; +import { useFocusTrap } from "@/hooks/use-focus-trap"; +import { useTranslations } from "next-intl"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; + +interface PromptDialogProps { + isOpen: boolean; + onClose: () => void; + onSubmit: (value: string) => void; + title: string; + message?: string; + placeholder?: string; + defaultValue?: string; + confirmText?: string; + cancelText?: string; +} + +export function PromptDialog({ + isOpen, + onClose, + onSubmit, + title, + message, + placeholder, + defaultValue = "", + confirmText, + cancelText, +}: PromptDialogProps) { + const t = useTranslations("confirm_dialog"); + const id = useId(); + const [value, setValue] = useState(defaultValue); + const inputRef = useRef(null); + + const dialogRef = useFocusTrap({ + isActive: isOpen, + onEscape: onClose, + restoreFocus: true, + }); + + useEffect(() => { + if (isOpen) { + setValue(defaultValue); + const t = setTimeout(() => { + inputRef.current?.focus(); + inputRef.current?.select(); + }, 50); + return () => clearTimeout(t); + } + }, [isOpen, defaultValue]); + + useEffect(() => { + if (!isOpen) return; + + const handleBackdropClick = (e: MouseEvent) => { + if (dialogRef.current && !dialogRef.current.contains(e.target as Node)) { + onClose(); + } + }; + + document.addEventListener("mousedown", handleBackdropClick); + return () => document.removeEventListener("mousedown", handleBackdropClick); + }, [isOpen, onClose, dialogRef]); + + if (!isOpen) return null; + + const resolvedConfirmText = confirmText || t("confirm"); + const resolvedCancelText = cancelText || t("cancel"); + const trimmed = value.trim(); + const canSubmit = trimmed.length > 0; + + const handleSubmit = (e?: React.FormEvent) => { + e?.preventDefault(); + if (!canSubmit) return; + try { + onSubmit(trimmed); + } finally { + onClose(); + } + }; + + return ( +
+
+
+
+

+ {title} +

+ {message && ( +

{message}

+ )} + setValue(e.target.value)} + placeholder={placeholder} + className="mt-4" + /> +
+ +
+ + +
+
+
+
+ ); +} diff --git a/hooks/use-prompt-dialog.ts b/hooks/use-prompt-dialog.ts new file mode 100644 index 00000000..36df3225 --- /dev/null +++ b/hooks/use-prompt-dialog.ts @@ -0,0 +1,87 @@ +import { useState, useCallback, useRef, useEffect } from "react"; + +interface PromptDialogState { + isOpen: boolean; + title: string; + message?: string; + placeholder?: string; + defaultValue: string; + confirmText?: string; + cancelText?: string; + onSubmit: (value: string) => void; +} + +const INITIAL_STATE: PromptDialogState = { + isOpen: false, + title: "", + defaultValue: "", + onSubmit: () => {}, +}; + +interface PromptOptions { + title: string; + message?: string; + placeholder?: string; + defaultValue?: string; + confirmText?: string; + cancelText?: string; +} + +export function usePromptDialog() { + const [state, setState] = useState(INITIAL_STATE); + const resolveRef = useRef<((value: string | null) => void) | null>(null); + + useEffect(() => { + return () => { + if (resolveRef.current) { + resolveRef.current(null); + resolveRef.current = null; + } + }; + }, []); + + const prompt = useCallback( + (options: PromptOptions): Promise => { + return new Promise((resolve) => { + resolveRef.current = resolve; + setState({ + isOpen: true, + title: options.title, + message: options.message, + placeholder: options.placeholder, + defaultValue: options.defaultValue ?? "", + confirmText: options.confirmText, + cancelText: options.cancelText, + onSubmit: (value) => { + resolveRef.current = null; + resolve(value); + }, + }); + }); + }, + [] + ); + + const close = useCallback(() => { + if (resolveRef.current) { + resolveRef.current(null); + resolveRef.current = null; + } + setState(INITIAL_STATE); + }, []); + + return { + dialogProps: { + isOpen: state.isOpen, + onClose: close, + onSubmit: state.onSubmit, + title: state.title, + message: state.message, + placeholder: state.placeholder, + defaultValue: state.defaultValue, + confirmText: state.confirmText, + cancelText: state.cancelText, + }, + prompt, + }; +} diff --git a/locales/de/common.json b/locales/de/common.json index 129016cb..29d1b622 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -1605,9 +1605,12 @@ "mark_all_confirm_message": "Jede ungelesene Nachricht in deinem persönlichen Konto als gelesen markieren?", "delete_confirm_title": "Ordner löschen", "delete_confirm_message": "Den Ordner \"{name}\" dauerhaft löschen? Dies kann nicht rückgängig gemacht werden.", - "prompt_new_subfolder": "Name des neuen Unterordners:", - "prompt_new_folder": "Name des neuen Ordners:", - "prompt_rename": "Ordner umbenennen in:", + "prompt_new_subfolder": "Gib einen Namen für den neuen Unterordner ein.", + "prompt_new_folder": "Gib einen Namen für den neuen Ordner ein.", + "prompt_rename": "Gib einen neuen Namen für diesen Ordner ein.", + "placeholder_folder_name": "Ordnername", + "create": "Erstellen", + "rename_confirm": "Umbenennen", "toast_marked_read": "Ordner als gelesen markiert", "toast_marked_read_count": "{count, plural, one {1 Nachricht} other {# Nachrichten}} als gelesen markiert", "toast_already_read": "Keine ungelesenen Nachrichten", diff --git a/locales/en/common.json b/locales/en/common.json index 47777a38..23618207 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -1609,9 +1609,12 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", diff --git a/locales/es/common.json b/locales/es/common.json index b9f6d301..77d94863 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Atajos de Teclado", diff --git a/locales/fr/common.json b/locales/fr/common.json index 83c8c8cc..34fc8281 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Raccourcis clavier", diff --git a/locales/it/common.json b/locales/it/common.json index 89f84974..85c99029 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Scorciatoie da tastiera", diff --git a/locales/ja/common.json b/locales/ja/common.json index bb24ed51..e7592ab0 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "キーボードショートカット", diff --git a/locales/ko/common.json b/locales/ko/common.json index 5f14da62..2aed2cc0 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "단축키", diff --git a/locales/lv/common.json b/locales/lv/common.json index cad72013..44da8b8d 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Īsinājumtaustiņi", diff --git a/locales/nl/common.json b/locales/nl/common.json index 223d59a7..44dd31af 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Sneltoetsen", diff --git a/locales/pl/common.json b/locales/pl/common.json index e1a644ac..f010cbe6 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Skróty klawiszowe", diff --git a/locales/pt/common.json b/locales/pt/common.json index 2a784b84..f903909e 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Atalhos de Teclado", diff --git a/locales/ru/common.json b/locales/ru/common.json index 036917a8..0969ec71 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Сочетания клавиш", diff --git a/locales/uk/common.json b/locales/uk/common.json index 3c25d6b5..3ea4da5c 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "Комбінації клавіш", diff --git a/locales/zh/common.json b/locales/zh/common.json index 474e8ef4..f4bb33ea 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -1605,9 +1605,9 @@ "mark_all_confirm_message": "Mark every unread message in your personal account as read?", "delete_confirm_title": "Delete folder", "delete_confirm_message": "Permanently delete the folder \"{name}\"? This action cannot be undone.", - "prompt_new_subfolder": "New subfolder name:", - "prompt_new_folder": "New folder name:", - "prompt_rename": "Rename folder to:", + "prompt_new_subfolder": "Enter a name for the new subfolder.", + "prompt_new_folder": "Enter a name for the new folder.", + "prompt_rename": "Enter a new name for this folder.", "toast_marked_read": "Folder marked as read", "toast_marked_read_count": "Marked {count, plural, one {1 message} other {# messages}} as read", "toast_already_read": "No unread messages", @@ -1622,7 +1622,10 @@ "toast_error_rename": "Failed to rename folder", "toast_error_delete": "Failed to delete folder", "toast_error_delete_has_children": "Folder has subfolders. Remove them first.", - "toast_error_delete_has_email": "Folder is not empty. Empty it first." + "toast_error_delete_has_email": "Folder is not empty. Empty it first.", + "placeholder_folder_name": "Folder name", + "create": "Create", + "rename_confirm": "Rename" }, "shortcuts": { "title": "键盘快捷键",