Three strands that only make sense together, so they land together. Registration gate (migration 0016). POST /auth/register was open to anyone who could reach the port. Now the first account on an empty instance is always allowed, becomes the administrator, and closes registration behind itself; after that it takes an admin reopening it. The decision is made under a row lock on app_settings so two simultaneous first signups cannot both see an empty table and both claim administrator. Existing installs keep their oldest account as admin and start closed. Instance default quota (migration 0017). users.quota_bytes is snapshotted at creation from app_settings.default_quota_bytes, so changing the default affects later accounts only and never resizes a mailbox that exists. The panel is a separate app, not a page in the mail client. admin.html is its own Vite entry (5.8 KB next to the client's 1.7 MB; they share only the vendor chunk), with its own administrator sign-in. One nginx now serves two listeners: :80 is the mail client and 404s both /admin.html and /api/admin/*, :81 is the panel. docker-compose publishes them as WEB_PORT and ADMIN_PORT. The boundary is nginx refusing paths on one listener, not process isolation — CurrentAdmin still guards every admin route — so ADMIN_PORT must be restricted to the LAN, which the runbook now covers for both DSM and QNAP. Also QNAP: deploy/webmail.sh finds Container Station's docker under /share/*/.qpkg/container-station/bin, which is off an SSH session's PATH, before anything shells out to it. docs/nas-install.md gains a QuTS hero runbook (§2.6), splits the DSM firewall section into container-to-container (§8.1) and the egress case that makes account-add time out while autodiscovery appears to work (§8.2), and scopes both to Synology. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018SqJYt7jD7oUEkoY68sBZo
453 lines
20 KiB
TypeScript
453 lines
20 KiB
TypeScript
// English message catalog. Adding a locale = drop a sibling file with the same
|
||
// keys and register it in i18n/index.tsx. Keys are flat, dotted namespaces.
|
||
// Interpolate with {name} placeholders.
|
||
|
||
export const en = {
|
||
"common.appName": "Webmail",
|
||
"common.loading": "Loading…",
|
||
"common.cancel": "Cancel",
|
||
"common.save": "Save",
|
||
"common.saving": "Saving…",
|
||
"common.delete": "Delete",
|
||
"common.remove": "Remove",
|
||
"common.edit": "Edit",
|
||
"common.close": "Close",
|
||
"common.clear": "Clear",
|
||
"common.copy": "Copy",
|
||
"common.back": "Back",
|
||
"common.next": "Next",
|
||
"common.signOut": "Sign out",
|
||
"common.retry": "Retry",
|
||
"common.optional": "optional",
|
||
|
||
"auth.signInTitle": "Sign in",
|
||
"auth.registerTitle": "Create account",
|
||
"auth.handle": "Handle",
|
||
"auth.handlePlaceholder": "e.g. alice",
|
||
"auth.handleHint": "3–30 chars: a–z, 0–9, . _ -",
|
||
"auth.password": "Password",
|
||
"auth.passwordHint": "at least 8 characters",
|
||
"auth.totpCode": "2FA code",
|
||
"auth.totpPrompt": "Enter the 6-digit code from your authenticator app",
|
||
"auth.signIn": "Sign in",
|
||
"auth.signingIn": "Signing in…",
|
||
"auth.create": "Create account",
|
||
"auth.creating": "Creating…",
|
||
"auth.noAccount": "No account?",
|
||
"auth.haveAccount": "Already have an account?",
|
||
"auth.register": "Register",
|
||
"auth.checking": "Checking…",
|
||
"auth.firstUserTitle": "Create the administrator account",
|
||
"auth.firstUserHint":
|
||
"This is the first account on this server, so it becomes the administrator. Registration closes automatically once it exists.",
|
||
"auth.registrationClosedTitle": "Registration is closed",
|
||
"auth.registrationClosed":
|
||
"This server is not accepting new accounts. Ask the administrator to open registration.",
|
||
|
||
"nav.mail": "Mail",
|
||
"nav.back": "Back",
|
||
"nav.settings": "Settings",
|
||
"nav.compose": "Compose",
|
||
"nav.collapseSidebar": "Collapse sidebar",
|
||
"nav.expandSidebar": "Expand sidebar",
|
||
"nav.allAccounts": "All accounts",
|
||
"nav.inbox": "Inbox",
|
||
"nav.archive": "Archive",
|
||
"nav.drafts": "Drafts",
|
||
"nav.sent": "Sent",
|
||
"nav.spam": "Spam",
|
||
"nav.trash": "Trash",
|
||
"nav.search": "Search mail…",
|
||
"nav.searchInTrash": "Search in Trash",
|
||
"nav.searchInSpam": "Search in Spam",
|
||
"search.save": "Save this search",
|
||
"search.saved": "Saved searches",
|
||
"search.saveNamePrompt": "Name this saved search:",
|
||
"nav.storageQuota": "Storage used",
|
||
"nav.refresh": "Refresh all folders",
|
||
|
||
"mail.noConversations": "No conversations.",
|
||
"mail.selectConversation": "Select a conversation.",
|
||
"mail.loadingThread": "Loading thread…",
|
||
"mail.expandAll": "Expand all",
|
||
"mail.collapseAll": "Collapse all",
|
||
"mail.print": "Print",
|
||
"mail.previewPage": "Page {current} / {total}",
|
||
"mail.previewResetZoom": "Reset zoom",
|
||
"mail.previewPrev": "Previous",
|
||
"mail.previewNext": "Next",
|
||
"preview.pdfProtected": "This PDF is password-protected",
|
||
"preview.password": "Password",
|
||
"preview.pdfWrongPassword": "Incorrect password — try again",
|
||
"preview.unlock": "Unlock",
|
||
"preview.pdfError": "Couldn't open this PDF.",
|
||
"mail.orderOldest": "Oldest first",
|
||
"mail.orderNewest": "Newest first",
|
||
"filter.all": "All mail",
|
||
"filter.unread": "Unread",
|
||
"filter.pinned": "Pinned",
|
||
"filter.sortOldest": "Sort oldest first",
|
||
"filter.sortNewest": "Sort newest first",
|
||
"pager.prev": "Previous page",
|
||
"pager.next": "Next page",
|
||
"mail.reply": "Reply",
|
||
"mail.replyAll": "Reply all",
|
||
"mail.forward": "Forward",
|
||
"mail.archive": "Archive",
|
||
"mail.markRead": "Mark read",
|
||
"mail.markUnread": "Mark unread",
|
||
"mail.star": "Star",
|
||
"mail.unstar": "Unstar",
|
||
"mail.pin": "Pin",
|
||
"mail.unpin": "Unpin",
|
||
"mail.delete": "Delete",
|
||
"mail.restore": "Restore",
|
||
"mail.select": "Select conversation",
|
||
"mail.selectAll": "Select all",
|
||
"mail.conversationSelected": "1 conversation selected",
|
||
"mail.conversationsSelected": "{count} conversations selected",
|
||
"mail.alsoIn": "Also delivered to",
|
||
"mail.emptyTrash": "Empty trash",
|
||
"mail.emptySpam": "Empty spam",
|
||
"mail.more": "More",
|
||
"mail.markAllRead": "Mark all as read",
|
||
"mail.labels": "Labels",
|
||
"mail.noLabels": "No labels yet",
|
||
"mail.createLabel": "Create new…",
|
||
"mail.labelName": "Label name",
|
||
|
||
"panel.toggle": "Toggle side panel",
|
||
"panel.calendar": "Calendar",
|
||
"panel.people": "People",
|
||
"panel.attachments": "Attachments",
|
||
"panel.search": "Search",
|
||
"panel.newEvent": "New event",
|
||
"panel.miniCalendar": "Mini calendar",
|
||
"panel.week": "Week",
|
||
"panel.month": "Month",
|
||
"panel.view": "View",
|
||
"panel.day": "Day",
|
||
"panel.3days": "3 days",
|
||
"panel.agenda": "Agenda",
|
||
"panel.allCalendars": "All calendars",
|
||
"panel.searchEvents": "Search events",
|
||
"panel.today": "Today",
|
||
"panel.noEvents": "No events",
|
||
"panel.untitled": "(untitled)",
|
||
"panel.allDay": "All day",
|
||
"panel.openCalendar": "Open calendar in new tab",
|
||
"panel.inConversation": "In conversation",
|
||
"panel.allContacts": "All contacts",
|
||
"panel.recent": "Recent",
|
||
"panel.vips": "VIPs",
|
||
"panel.autosaved": "Autosaved",
|
||
"panel.senders": "Senders",
|
||
"panel.noPeople": "No people",
|
||
"panel.composeAll": "Compose to all",
|
||
"panel.inviteAll": "Invite all to new event",
|
||
"panel.call": "Call",
|
||
"panel.message": "Message",
|
||
"panel.compose": "Compose",
|
||
"panel.invite": "Invite",
|
||
"panel.contactDetails": "Contact details",
|
||
"panel.showAll": "Show all",
|
||
"panel.mailSection": "Mail",
|
||
"panel.noSubject": "(no subject)",
|
||
"panel.findAll": "Find all conversations with {name}",
|
||
"panel.eventsSection": "Events",
|
||
"panel.noMatches": "No matches found",
|
||
"panel.openContact": "Open contact in new tab",
|
||
"panel.openConversation": "Open a conversation to see its attachments.",
|
||
"panel.noAttachments": "No attachments",
|
||
"panel.download": "Download",
|
||
"mail.emptyConfirm": "Permanently delete everything in this folder? This can't be undone.",
|
||
"mail.loadFailed": "Couldn't load this message.",
|
||
"mail.imagesBlocked": "Images from this sender are blocked.",
|
||
"mail.loadImages": "Load images",
|
||
"mail.alwaysFromSender": "Always from this sender",
|
||
"mail.to": "to",
|
||
"mail.from": "From",
|
||
"mail.subjectLabel": "Subject",
|
||
"mail.dateLabel": "Date",
|
||
"mail.sizeLabel": "Size",
|
||
"mail.actions": "Actions",
|
||
"mail.forwardAsAttachment": "Forward as attachment",
|
||
"mail.showQuoted": "Show quoted text",
|
||
"mail.hideQuoted": "Hide quoted text",
|
||
"mail.markReadUnread": "Mark read / unread",
|
||
"mail.messageCount": "{count} messages",
|
||
"mail.downloadAll": "Download all {count} attachments",
|
||
"mail.downloadZip": "Download zip",
|
||
"mail.download": "Download",
|
||
|
||
"compose.newMessage": "New message",
|
||
"compose.to": "To",
|
||
"compose.cc": "Cc",
|
||
"compose.bcc": "Bcc",
|
||
"compose.subject": "Subject",
|
||
"compose.send": "Send",
|
||
"compose.sending": "Sending…",
|
||
"compose.discard": "Discard",
|
||
"compose.saveDraft": "Save draft",
|
||
"compose.closePrompt": "Save this message as a draft?",
|
||
"compose.sent": "Message sent.",
|
||
"compose.undoIn": "{count} seconds to",
|
||
"compose.undo": "Undo",
|
||
"compose.sendFailed": "Send failed.",
|
||
"compose.savingDraft": "Saving draft…",
|
||
"compose.draftSaved": "Draft saved",
|
||
"compose.noDrafts": "No drafts.",
|
||
"compose.otherClient": "other client",
|
||
"compose.noRecipient": "(no recipient)",
|
||
"compose.noSubject": "(no subject)",
|
||
"compose.from": "From",
|
||
"compose.attach": "Attach",
|
||
"compose.more": "More",
|
||
"compose.expand": "Expand",
|
||
"compose.collapse": "Collapse",
|
||
"compose.popOut": "Pop out",
|
||
"compose.replyLabel": "Reply",
|
||
"compose.addRecipient": "Add recipient…",
|
||
"compose.fmtBold": "Bold",
|
||
"compose.fmtItalic": "Italic",
|
||
"compose.fmtUnderline": "Underline",
|
||
"compose.fmtStrike": "Strikethrough",
|
||
"compose.fmtBulletList": "Bulleted list",
|
||
"compose.fmtNumberList": "Numbered list",
|
||
"compose.fmtQuote": "Quote",
|
||
"compose.fmtLink": "Insert link",
|
||
"compose.fmtAlignLeft": "Align left",
|
||
"compose.fmtAlignCenter": "Align center",
|
||
"compose.fmtAlignRight": "Align right",
|
||
"compose.fmtClear": "Clear formatting",
|
||
"compose.fmtColor": "Text color",
|
||
"compose.fmtHighlight": "Highlight color",
|
||
"compose.fmtImage": "Insert image",
|
||
"compose.insertSignature": "Insert signature",
|
||
"compose.linkPrompt": "Link URL:",
|
||
"compose.imageTooLarge": "Image is too large (max 5 MB).",
|
||
"compose.attachTooLarge": "File exceeds the 25 MB limit.",
|
||
"compose.attachments": "Attachments",
|
||
"compose.dropAttach": "Drop to attach",
|
||
"compose.dropBody": "Drop image to insert · other files attach",
|
||
|
||
"wizard.title": "Add mail account",
|
||
"wizard.step1": "Your email address",
|
||
"wizard.emailPlaceholder": "you@example.com",
|
||
"wizard.discover": "Continue",
|
||
"wizard.discovering": "Looking up settings…",
|
||
"wizard.foundVia": "Found via {source}",
|
||
"wizard.imapServer": "IMAP server",
|
||
"wizard.smtpServer": "SMTP server",
|
||
"wizard.host": "Host",
|
||
"wizard.port": "Port",
|
||
"wizard.security": "Security",
|
||
"wizard.accountPassword": "Account password",
|
||
"wizard.appPasswordHint": "For Gmail, Yahoo, iCloud, or Outlook use an app password.",
|
||
"wizard.help": "Help",
|
||
"wizard.appPasswordHelp.title": "Set up an app password",
|
||
"wizard.appPasswordHelp.intro":
|
||
"These providers need a one-time app password instead of your normal password:",
|
||
"wizard.appPasswordHelp.prefix": "Make sure to",
|
||
"wizard.appPasswordHelp.twoStep": "turn on 2-step verification",
|
||
"wizard.appPasswordHelp.middle": "if you haven't done it yet, and then",
|
||
"wizard.appPasswordHelp.generate": "generate the app password",
|
||
"wizard.test": "Test & continue",
|
||
"wizard.testing": "Testing connection…",
|
||
"wizard.testOk": "Connection works.",
|
||
"wizard.create": "Add account",
|
||
"wizard.creating": "Adding…",
|
||
"wizard.created": "Account added — syncing your mail.",
|
||
"wizard.startReading": "Start reading now",
|
||
"wizard.backToAccounts": "Back to accounts",
|
||
"wizard.manualConfig": "Enter settings manually",
|
||
"wizard.displayName": "Display name",
|
||
"wizard.syncWindow": "How much mail to sync",
|
||
"wizard.syncWindow.all": "All mail",
|
||
"wizard.syncWindow.all.hint": "Imports the last 30 days first, then the rest in the background.",
|
||
"wizard.syncWindow.3months": "Last 3 months only",
|
||
"wizard.syncWindow.3months.hint": "Older mail stays on the server until you download it.",
|
||
"wizard.syncWindow.new": "New mail only",
|
||
"wizard.syncWindow.new.hint":
|
||
"Nothing from before now — download older mail anytime from account settings.",
|
||
"wizard.syncSpam": "Sync spam?",
|
||
"wizard.syncSpam.hint": "Also import the Spam/Junk folder. Off by default.",
|
||
|
||
// Provider credential-helper panel (app passwords, SPEC §6.2.2).
|
||
"wizard.appPassword.title": "Create an app password",
|
||
"wizard.appPassword.intro":
|
||
"This provider needs a one-time app password instead of your normal password. Open the page below, generate one, and paste it here.",
|
||
"wizard.appPassword.open": "Open {provider} app passwords",
|
||
"wizard.appPassword.appNameHint": "Suggested name: {hint}",
|
||
"wizard.appPassword.pastePlaceholder": "Paste the app password",
|
||
"wizard.appPassword.verifying": "Verifying…",
|
||
"wizard.appPassword.connected": "Connected ✓",
|
||
"wizard.appPassword.docs": "Provider help",
|
||
"wizard.appPassword.useManual": "Enter server settings manually",
|
||
"wizard.appPassword.provider.gmail": "Google",
|
||
"wizard.appPassword.provider.yahoo": "Yahoo",
|
||
"wizard.appPassword.provider.icloud": "iCloud",
|
||
"wizard.appPassword.provider.outlook": "Microsoft",
|
||
// auth_failed recovery branch (the two real dead-ends).
|
||
"wizard.appPassword.failTitle": "That password didn't work",
|
||
"wizard.appPassword.failCauses":
|
||
"Common causes: 2-Step Verification isn't fully enabled yet; a brand-new account for which the provider withholds app passwords until it ages; or a work/school account where an admin disabled the feature.",
|
||
"wizard.appPassword.oauthInstead": "Sign in with Google instead",
|
||
// Gmail steps.
|
||
"wizard.help.gmail.step1": "Turn on 2-Step Verification for your Google account if you haven't.",
|
||
"wizard.help.gmail.step2": "Click the button to generate an app password.",
|
||
"wizard.help.gmail.step3": "On the App passwords page, name the password (e.g. \"ultimo.email\") and create it.",
|
||
"wizard.help.gmail.step4": "Copy the 16-character password and paste it below.",
|
||
// Outlook / Microsoft personal steps.
|
||
"wizard.help.outlook.step1": "Turn on two-step verification in your Microsoft account security settings.",
|
||
"wizard.help.outlook.step2": "Under Advanced security options, create a new app password.",
|
||
"wizard.help.outlook.step3": "Copy the generated password and paste it below.",
|
||
// Yahoo steps.
|
||
"wizard.help.yahoo.step1": "Open Account Security and turn on two-step verification.",
|
||
"wizard.help.yahoo.step2": "Choose \"Generate app password\" and name it.",
|
||
"wizard.help.yahoo.step3": "Copy the password and paste it below.",
|
||
// iCloud steps.
|
||
"wizard.help.icloud.step1": "Turn on two-factor authentication for your Apple Account.",
|
||
"wizard.help.icloud.step2": "Under Sign-In and Security, generate an app-specific password.",
|
||
"wizard.help.icloud.step3": "Copy the password and paste it below.",
|
||
|
||
"settings.title": "Settings",
|
||
"settings.profile": "Profile",
|
||
"settings.security": "Security",
|
||
"settings.accounts": "Accounts",
|
||
"settings.downloadAllMail": "Sync remaining mail",
|
||
"settings.syncedPartially": "Synced partially",
|
||
"backfill.importing": "Importing messages… {done} of {total}",
|
||
"backfill.preparing": "Preparing to import messages…",
|
||
"settings.appearance": "Appearance",
|
||
"settings.handle": "Handle",
|
||
"settings.recoveryEmail": "Recovery email",
|
||
"settings.twoFactor": "Two-factor authentication",
|
||
"settings.twoFactorOn": "2FA is enabled.",
|
||
"settings.twoFactorOff": "2FA is not enabled.",
|
||
"settings.enable2fa": "Enable 2FA",
|
||
"settings.disable2fa": "Disable 2FA",
|
||
"settings.disable2faPrompt": "Enter your password to turn off 2FA:",
|
||
"settings.disable": "Disable",
|
||
"settings.twoFactorDisabled": "2FA has been turned off.",
|
||
"settings.scanQr": "Scan this in your authenticator app, then enter a code:",
|
||
"settings.secret": "Secret",
|
||
"settings.confirm": "Confirm",
|
||
"settings.sessions": "Active sessions",
|
||
"settings.thisDevice": "this device",
|
||
"settings.revoke": "Revoke",
|
||
"settings.threadOrder": "Conversation order",
|
||
"settings.timezone": "Time zone",
|
||
"settings.timeFormat": "Time format",
|
||
"settings.timeFormat24": "24-hour (14:30)",
|
||
"settings.timeFormat12": "12-hour (2:30 PM)",
|
||
"settings.calendars": "Calendars",
|
||
"settings.myCalendars": "My calendars",
|
||
"settings.calendarOptions": "Calendar options",
|
||
"settings.createCalendar": "Create calendar",
|
||
"settings.editCalendar": "Edit calendar",
|
||
"settings.export": "Export",
|
||
"settings.calendarDisplay": "Calendar display",
|
||
"settings.default": "Default",
|
||
"settings.defaultCalendar": "Default calendar",
|
||
"settings.firstCalendar": "First calendar",
|
||
"settings.defaultRemindersTimed": "Default reminders for timed events",
|
||
"settings.defaultRemindersAllday": "Default reminders for all-day events",
|
||
"settings.addReminder": "Add reminder",
|
||
"settings.name": "Name",
|
||
"settings.onlyYou": "Only you can see this calendar.",
|
||
"settings.publish": "Publish",
|
||
"settings.publishHint": "Share this calendar (read-only) with anyone.",
|
||
"settings.fullEventDetails": "Full event details",
|
||
"settings.freeBusy": "Free/busy information",
|
||
"settings.addAccountHint": "Connect an external calendar account.",
|
||
"settings.subscriptions": "Subscriptions",
|
||
"settings.subscriptionsHint": "Add a read-only calendar from an iCal (.ics) URL.",
|
||
"settings.subscribe": "Subscribe",
|
||
"settings.subscribeUrl": "iCal (.ics) URL",
|
||
"settings.subscribed": "Subscribed",
|
||
"settings.comingSoon": "Coming soon",
|
||
"settings.subscribeError": "Couldn't subscribe to that URL.",
|
||
"settings.connectTitle": "Connect {provider}",
|
||
"settings.connect": "Connect",
|
||
"settings.connecting": "Connecting…",
|
||
"settings.connectError": "Couldn't connect. Check the details and try again.",
|
||
"settings.connectAuthFailed":
|
||
"Sign-in was rejected. If you have two-factor auth on, use an app password (not your normal password).",
|
||
"settings.connectPrivateHost":
|
||
"That server is on a private network, which isn't reachable for security reasons. Use a publicly-accessible HTTPS address.",
|
||
"settings.connectUnreachable":
|
||
"Couldn't reach that server. Check the URL is correct and uses https://.",
|
||
"settings.connectNoCalendars": "Connected, but no calendars were found on that account.",
|
||
"settings.connectNeedsUrl": "Enter the CalDAV server URL.",
|
||
"settings.davServerUrl": "CalDAV server URL",
|
||
"settings.appleId": "Apple ID (email)",
|
||
"settings.username": "Username",
|
||
"settings.appPassword": "App-specific password",
|
||
"settings.password": "Password",
|
||
"settings.icloudHint":
|
||
"Use an app-specific password from account.apple.com → Sign-In and Security.",
|
||
"settings.calendarCount": "{count} calendars",
|
||
"settings.removeSubscription": "Remove subscription",
|
||
"settings.removeSubscriptionConfirm": "Stop syncing “{name}” and remove its events?",
|
||
"settings.deleteCalendar": "Delete calendar",
|
||
"settings.thisCalendar": "this calendar",
|
||
"settings.deleteCalendarConfirm": "Delete “{name}” and all of its events? This can't be undone.",
|
||
"settings.showAlert": "Show an alert",
|
||
"settings.emailMe": "Email me",
|
||
"settings.invitations": "Invitations",
|
||
"settings.inviteWhen": "When I receive events by email",
|
||
"settings.inviteAddUpdate": "Add new events to my calendar and update events that have changed",
|
||
"settings.inviteUpdateOnly": "Only update events that I have already added to my calendar",
|
||
"settings.inviteNone": "Do not automatically update my calendar",
|
||
"settings.addNewFrom": "Add new events from",
|
||
"settings.myContacts": "My contacts",
|
||
"settings.anyone": "Anyone",
|
||
"settings.addToCalendar": "Add to calendar",
|
||
"settings.alsoFile": "Also mark the message as read and file it",
|
||
"settings.integrations": "Integrations",
|
||
|
||
"admin.title": "Webmail administration",
|
||
"admin.signInTitle": "Administrator sign-in",
|
||
"admin.signInHint": "Sign in with an administrator account to manage this server.",
|
||
"admin.signOut": "Sign out",
|
||
"admin.signedInAs": "Signed in as {handle}",
|
||
"admin.notAdminTitle": "Not an administrator",
|
||
"admin.notAdmin":
|
||
"{handle} is signed in, but does not have administrator rights on this server.",
|
||
"admin.registration": "New user registration",
|
||
"admin.registrationOn": "Open",
|
||
"admin.registrationOff": "Closed",
|
||
"admin.registrationHelp":
|
||
"While closed, the signup page is hidden and the server refuses new accounts.",
|
||
"admin.defaultQuota": "Default quota for new users",
|
||
"admin.quotaHelp":
|
||
"Applies to accounts created from now on. Existing mailboxes keep the quota they were given.",
|
||
"admin.save": "Save",
|
||
"admin.saving": "Saving…",
|
||
"admin.saved": "Saved",
|
||
"admin.quotaInvalid": "Enter a size greater than 0.",
|
||
"settings.jitsi": "Jitsi Meet",
|
||
"settings.jitsiHint":
|
||
"Server used to generate video-call links for calendar events. Leave empty to use the public https://meet.jit.si/ server.",
|
||
"settings.addAccount": "Add account",
|
||
"settings.syncState": "State: {state}",
|
||
"settings.confirmRemoveAccount": "Remove this account and all its mail?",
|
||
"settings.removingAccount": "Removing account…",
|
||
"settings.editAccount": "Edit account",
|
||
"settings.color": "Color",
|
||
"settings.serverSettings": "Change server settings / password",
|
||
"settings.serverSettingsHint": "Enter your mailbox password to apply server or password changes.",
|
||
"settings.signature": "Signature",
|
||
"settings.configureAccount": "Configure account",
|
||
"settings.editSignature": "Edit signature",
|
||
"settings.theme": "Theme",
|
||
"theme.light": "Light",
|
||
"theme.dark": "Dark",
|
||
"theme.system": "System",
|
||
"theme.toggle": "Toggle theme",
|
||
} as const;
|
||
|
||
export type MessageKey = keyof typeof en;
|
||
export type Messages = Record<MessageKey, string>;
|