{ "app": { "title": "PicHost - Image Hosting", "description": "A lightweight self-hosted image hosting system", "tagline": "Personal lightweight image host" }, "common": { "loadingSession": "Verifying session…", "save": "Save", "cancel": "Cancel", "copy": "Copy", "delete": "Delete", "edit": "Edit", "search": "Search", "refresh": "Refresh", "back": "Back", "all": "All", "notConfigured": "(not configured)", "countImages": "{count} images", "itemsUnit": "items", "imagesUnit": "images", "more": "More" }, "nav": { "api": "API", "gallery": "Gallery", "stats": "Stats", "logs": "Activity log", "settings": "Settings", "storage": "Storage", "menu": "Menu", "language": "Language", "appearance": "Appearance", "account": "Account", "backToUpload": "Back to upload", "changePassword": "Change password", "systemSettings": "System settings", "logout": "Log out" }, "theme": { "switch": "Switch theme", "light": "Light", "dark": "Dark", "system": "System" }, "locale": { "switch": "Switch language", "zh-CN": "简体中文", "en": "English" }, "auth": { "username": "Username", "password": "Password", "confirmPassword": "Confirm password", "login": "Log in", "register": "Register", "adminSecret": "Admin secret", "adminSecretPlaceholder": "Enter ADMIN_SECRET", "legacyHint": "Legacy deployment: sign in with the secret to migrate to username/password", "noAccount": "No account?", "hasAccount": "Already have an account?", "backToLogin": "Back to login", "loginFooter": "Upload and management require sign-in", "loginSuccess": "Signed in", "loginFailedSecret": "Sign-in failed. Check your secret", "loginFailedCredentials": "Invalid username or password", "loginFailed": "Sign-in failed. Check username and password", "captchaHint": "Drag the slider to the slot", "captchaSuccess": "Verified", "verificationMisconfigured": "Human verification is not configured correctly. Contact an administrator.", "capInitialState": "Verify you are human", "capVerifying": "Verifying…", "capSolved": "Verified", "capError": "Verification failed", "registerFailed": "Registration failed. Check your input", "setupFailed": "Setup failed. Check your input", "migrateFailed": "Migration failed. Check your input", "passwordMismatch": "Passwords do not match", "showPassword": "Show password", "hidePassword": "Hide password", "registerSuccess": "Registered successfully", "errors": { "invalidUsername": "Username must be 3–32 letters, numbers, or underscores", "invalidPassword": "Password must be at least 8 characters" } }, "domainSeparationConfirm": { "title": "Save dual-domain settings?", "description": "After saving, only the site URL can serve the admin UI and API, and only the image URL can serve public image links. Access via IP, an unlisted Host, or a reverse proxy that does not forward Host correctly may lock you out of the admin UI.\n\nIf locked out, run docker exec pichost clear-domains (local dev: npm run clear-domains), or disable domain separation in Settings when you can access it again.\n\nSave anyway?", "confirm": "Save anyway" }, "setup": { "migrateTitle": "Migrate to username/password", "initTitle": "First run — create admin account", "usernamePlaceholder": "3–32 letters, numbers, or underscores", "passwordPlaceholder": "Set login password", "confirmPlaceholder": "Enter password again", "allowRegistration": "Allow user registration", "domainSeparation": "Separate admin and image domains", "domainSeparationHint": "Admin and API use the site URL; image links use a dedicated image URL", "domainSeparationProxyHint": "Point both domains to this host and reverse-proxy to port 6892 (Nginx, Caddy, NPM, etc.)", "domainSeparationProxyExample": "View example", "siteBaseUrl": "Site URL", "siteBaseUrlHint": "No trailing slash; admin UI and API upload endpoint", "siteBaseUrlPlaceholder": "https://admin.example.com", "imageBaseUrl": "Image URL", "imageBaseUrlHint": "No trailing slash; public image link prefix", "imageBaseUrlPlaceholder": "https://pic.example.com", "domainSeparationInvalid": "Enter valid site and image URLs with different hostnames", "migrateSubmit": "Complete migration", "initSubmit": "Create and continue", "migrateSuccess": "Migration complete", "initSuccess": "Setup complete", "restoreTitle": "Restore from backup", "restoreSubtitle": "Upload a .phost.tar.gz to restore the full site", "restoreHint": "Restore replaces all current data. Cloud storage secrets are not in the backup—re-enter them on the Storage page after sign-in.", "restoreUpload": "Choose backup file", "restoreSubmit": "Start restore", "restoreProgress": "Restoring… {progress}/{total}", "restoreSuccess": "Restore complete. Sign in with the admin account from the backup.", "restoreFailed": "Restore failed", "restoreSecretsHint": "Cloud storage secrets are not in the backup. Re-enter them on the Storage page after sign-in.", "modeInit": "Create admin", "modeRestore": "Restore backup" }, "register": { "title": "Register", "subtitle": "Create a PicHost user account" }, "password": { "title": "Change password", "subtitle": "Update your login password", "current": "Current password", "new": "New password", "confirmNew": "Confirm new password", "newPlaceholder": "Set new password", "changed": "Password updated", "tooShort": "New password must be at least 8 characters", "changeFailed": "Failed to change password", "strength": "Password strength", "weak": "Weak", "medium": "Medium", "strong": "Strong", "ruleMinLength": "At least {n} characters", "ruleMixedCase": "Upper and lower case letters", "ruleNumber": "Contains a number", "ruleSpecial": "Contains a special character" }, "upload": { "title": "Drop images here to upload", "hint": "Or click to select files, press {ctrl} + {v} to paste", "formats": "JPEG / PNG / WebP / GIF / SVG / ICO, max 10 MB each, up to 10 files per batch", "selectFiles": "Select images", "settings": "Upload settings", "progress": "Upload progress", "statusPending": "Pending", "statusUploading": "Uploading", "statusSuccess": "Done", "statusError": "Failed", "selectImages": "Select images to upload", "maxFiles": "Up to {n} images per upload", "uploadSuccess": "Uploaded {n} image(s)", "uploadPartialFail": "{n} image(s) failed to upload", "uploadFailed": "Upload failed", "loginRequired": "Please sign in first", "sessionTitle": "This session", "sessionEmpty": "No uploads in this session" }, "tags": { "column": "Tags", "uploadLabel": "Tags (optional)", "addTag": "Add tag", "searchOrCreate": "Search or create tag", "createNamed": "Create tag \"{name}\"", "created": "Created tag \"{name}\"", "createFailed": "Failed to create tag", "updateFailed": "Failed to update tags", "filterAll": "All tags", "filterSelected": "{n} selected", "filterTitle": "Filter by tag", "manage": "Manage", "manageTitle": "Manage tags", "manageImageTitle": "Manage tags", "manageSubtitle": "Centralized tag management — add, edit, delete, and merge", "newTag": "New tag", "addTag": "Add tag", "mergeTags": "Merge tags", "searchName": "Search tag name", "filterStatusAll": "All statuses", "filterStatusUsed": "In use", "filterStatusUnused": "Unused", "statTotal": "Total tags", "statUsed": "Tags in use", "statUnused": "Unused tags", "statNew7d": "New in 7 days", "colName": "Tag name", "colImageCount": "Images", "colLastUsed": "Last used", "colCreatedAt": "Created", "neverUsed": "Never used", "colActions": "Actions", "mergeIntoAction": "Merge into…", "mergeIntoTitle": "Merge into…", "mergeIntoSubtitle": "Merge tag \"{name}\" into another tag", "mergeIntoChoose": "Choose the target tag", "mergeIrreversibleTitle": "This cannot be undone", "mergeIrreversible": "Merged tags are permanently deleted and their images move to the kept tag. This action cannot be reversed.", "mergeConfirmKeep": "Keeping tag \"{name}\"", "mergeWillDelete": "These tags will be deleted: {names}", "totalCount": "{n} tags", "sortByCount": "By count", "sortByName": "By name", "search": "Search tags", "namePlaceholder": "Tag name", "customColor": "Custom color", "pickColor": "Pick a color", "preview": "Preview", "renamed": "Tag renamed", "renameFailed": "Rename failed", "colorFailed": "Failed to update color", "deleted": "Deleted tag \"{name}\"", "deleteFailed": "Failed to delete tag", "deleteConfirmTitle": "Delete tag", "deleteConfirmDesc": "Delete tag \"{name}\"? It will be removed from all images. This cannot be undone.", "mergeSelectAtLeast": "Select at least 2 tags", "mergeHint": "Select multiple tags to merge; images from other tags will move to the kept tag", "mergeSelected": "{n} tags selected", "mergeClear": "Clear selection", "mergeTitle": "Merge tags", "mergeSubtitle": "Combine multiple tags into one", "mergeNote": "Unselected tags will be deleted; their images move to the kept tag", "mergeChooseTarget": "Choose the tag to keep", "mergeAction": "Merge into…", "mergeRow": "Merge", "mergeConfirm": "Confirm merge", "merged": "Tags merged", "mergeFailed": "Merge failed", "untagged": "Untagged", "untaggedAction": "+ Untagged", "unlabeled": "Unlabeled", "selectedLabel": "Selected ({n})", "clearSelected": "Clear", "selectAll": "Select all", "deselectAll": "Deselect all", "existingLabel": "Existing tags ({n})", "commonTags": "Common tags", "recentTags": "Recently used", "moreTags": "{n} more tags", "classifyHint": "Tags are for organization only and do not affect storage paths", "saved": "Tags saved", "saveFailed": "Failed to save tags", "batchTagAll": "Batch tag", "batchAddTitle": "Add tags", "batchAddSubtitle": "{n} images selected", "modeOr": "Any", "modeAnd": "All", "batchTitle": "Batch tags", "batchSubtitle": "Update tags for {n} selected image(s)", "batchAdd": "Add tags", "batchRemove": "Remove tags", "batchSuccess": "Batch update complete", "batchFailed": "Batch update failed", "noMatch": "No matching tags", "emptyHint": "No tags yet — type a name to create one", "settingsLink": "Manage tags in the gallery (create, colors, merge, delete)", "openManage": "Open tag manager" }, "copy": { "url": "URL", "markdown": "Markdown", "html": "HTML", "bbcode": "BBCode", "copied": "Copied to clipboard", "copiedLabel": "Copied {label}", "copiedUrl": "URL copied", "copiedMarkdown": "Markdown copied", "copiedHtml": "HTML copied", "copiedBbcode": "BBCode copied", "copiedFormat": "Copied {format}", "failed": "Copy failed", "failedManual": "Copy failed — select the link manually", "curl": "cURL example copied" }, "preferences": { "title": "Upload preferences", "subtitle": "Browser-local and account settings for your uploads only", "back": "Back to upload", "processing": "Image processing", "clientCompress": "Client-side compression", "clientCompressHint": "Compress in the browser before upload. The server may still convert to WebP unless “Preserve originals” is enabled above.", "autoDeletePrefix": "Auto-delete after", "autoDeleteSuffix": "days", "autoDeleteHint": "Only affects images uploaded after enabling; existing images are kept", "webpQuality": "WebP quality", "webpQualityHint": "Quality for client-side WebP pre-compression; higher values mean better quality and larger files.", "current": "Current: {n}", "qualityHigh": "High quality", "qualityMedium": "Medium quality", "qualityLow": "Lossy", "convenience": "Convenience", "autoCopy": "Copy link after upload", "autoCopyHint": "Copy to clipboard in the selected format" }, "settings": { "title": "System settings", "pageTitle": "Settings & preferences", "pageSubtitle": "Manage system configuration and activity logs", "pageSubtitleBasic": "Configure basic options so PicHost works better for you.", "pageSubtitleDomains": "Configure site and image URLs and upload path rules", "pageSubtitleAccess": "Configure image access policies to prevent hotlink abuse", "pageSubtitleLogs": "View uploads, deletions, edits, and configuration changes", "searchPlaceholder": "Search settings…", "searchEmpty": "No matches", "restoreDefaults": "Restore defaults", "restoredDefaults": "Defaults restored", "refererProtection": "Hotlink protection", "defaultCopyFormatHint": "Link format copied automatically after upload", "systemVersionHint": "Currently running PicHost version", "badgeEnabled": "Enabled", "domainSeparationProxyTitle": "Both domains must resolve to this host", "domainSeparationProxyBody": "Point the site and image URLs to this host and reverse-proxy to port 6892 (Nginx, Caddy, NPM, etc.).", "siteBaseUrlRoleHint": "URL for the admin UI", "imageBaseUrlRoleHint": "URL for serving and displaying images", "imageDomainSection": "Image domain", "navBasic": "Basic", "navDomains": "Domains & paths", "navAccess": "Access control", "navTags": "Tags", "navPreferences": "Preferences", "navLogs": "Activity log", "pageSubtitleTags": "Create, rename, merge, or delete tags", "systemVersion": "Version", "checkUpdate": "Check for updates", "saveSettings": "Save settings", "subtitle": "Saved to database; environment variables take precedence", "featureToggles": "Feature toggles", "featureTogglesHint": "Control registration and system behavior", "pathAndLink": "Paths & links", "pathAndLinkHint": "Control image URL format and upload directory structure", "domainSeparationSection": "Domain separation", "allowRegistration": "Open registration", "allowRegistrationHint": "Allow new users to register (regular users see only their images)", "accessControl": "Access control", "refererHint": "Referer hotlink protection; comma-separated hostnames, empty = no restriction", "refererDomainsLabel": "Allowed domains", "refererTip": "Separate multiple domains with commas (,); wildcards are not supported", "refererExamplesTitle": "Example", "refererExamplesSample": "example.com, static.example.com", "refererScenarioTitle": "Common use case", "refererScenarioDesc": "Allow your main site and static site to embed images", "refererScenario1": "Personal blog embedding images", "refererScenario2": "Corporate site and static CDN", "refererScenario3": "Local development", "refererScenario4": "Leave empty for no restriction", "refererEnabled": "Enabled", "refererUnrestricted": "Unrestricted", "loginVerification": "Login verification", "loginVerificationHint": "Human verification for login and registration (choose one)", "loginVerificationSlider": "Local slider", "loginVerificationSliderHint": "Built-in slider puzzle; no third-party service", "loginVerificationTurnstile": "Cloudflare Turnstile", "loginVerificationTurnstileHint": "Create a widget in Cloudflare Dashboard, then enter Site Key and Secret Key", "loginVerificationCap": "Cap POW", "loginVerificationCapHint": "Self-hosted Cap Standalone; enter API Endpoint and Secret Key", "turnstileSiteKey": "Turnstile Site Key", "turnstileSiteKeyPlaceholder": "0x4AAAAAAA…", "turnstileSecretKey": "Turnstile Secret Key", "turnstileSecretKeyPlaceholder": "0x4AAAAAAA…", "capApiEndpoint": "Cap API Endpoint", "capApiEndpointPlaceholder": "https://cap.example.com/your-site-key/", "capSecretKey": "Cap Secret Key", "capSecretKeyPlaceholder": "Secret key from your Cap dashboard", "systemInfo": "System", "systemInfoHint": "Current version and updates", "uploadConvenience": "Upload convenience", "defaultCopyFormat": "Default copy format", "refererPlaceholder": "example.com, www.example.com", "domainSettings": "Domain settings", "domainSeparationActive": "Domain separation enabled: image host serves images only; site host serves admin and API", "siteBaseUrl": "Site URL", "siteBaseUrlHint": "No trailing slash; admin UI and API upload endpoint", "siteBaseUrlPlaceholder": "https://admin.example.com", "siteBaseUrlActive": "Active: {url}", "imageBaseUrl": "Image URL", "imageBaseUrlHint": "No trailing slash; public image link prefix", "imageBaseUrlSingleHint": "No trailing slash; leave empty to use the current request host; single-domain setups do not need a site URL", "imageBaseUrlPlaceholder": "https://pic.example.com", "imageBaseUrlActive": "Active: {url}", "runtimeDetected": "Detected current access: {url} (will not be saved automatically)", "fillDetectedOrigin": "Use detected URL", "hostRoleUnknown": "Current Host does not match configured domains; reverse-proxy bypass may be possible", "disableDomainSeparationTitle": "Disable domain separation", "disableDomainSeparationDesc": "This clears the site URL and keeps only the image URL. Continue?", "disableDomainSeparationConfirm": "Disable", "domainSeparationRequired": "Both site and image URLs are required when domain separation is enabled", "hideFolderInUrl": "Use short image links", "hideFolderInUrlHint": "When on, links are only domain + filename, e.g. img.example.com/abc.webp. When off, date or custom folders are kept, e.g. img.example.com/2026/08/abc.webp", "storageUseDatePath": "Group uploads by year/month", "storageUseDatePathHint": "When enabled, files are stored as images/2026/08/file.webp; when disabled, as images/file.webp. Applies only to new uploads after enabling", "badgeEnv": ".env", "badgeSaved": "Saved", "badgeDefault": "Default", "badgeUnset": "Not set", "badgeOptional": "Optional", "tokenEnv": "Environment", "tokenDb": "Generated in app", "tokenNone": "Not configured", "apiTokenLine": "Source: {source}", "viewReleases": "View releases", "updateAvailable": "Update available: {version}", "upToDate": "You are on the latest version", "checkUpdateFailed": "Failed to check for updates. Please try again later", "unsavedChanges": "Unsaved changes", "manageToken": "Manage token", "envOverride": "Overridden by environment variable; cannot edit in UI", "saved": "Settings saved", "saveFailed": "Failed to save settings", "loadFailed": "Failed to load settings", "uploadLimits": "Upload limits", "uploadLimitsHint": "Site-wide upload policy and your personal convenience options. Applies after save.", "imageProcessingHint": "Site-wide format conversion and personal compression/cleanup.", "serverPolicy": "Site-wide", "personalPreference": "Personal", "uploadRateGroup": "Upload rate limits", "minutesUnit": "min", "uploadMaxFileSize": "Max file size", "uploadMaxFileSizeHint": "Uploads larger than this are rejected (1–100 MB).", "allowedMimeTypes": "Allowed image formats", "allowedMimeTypesHint": "Keep at least one format enabled. The server validates file signatures, not just extensions.", "preserveOriginalUpload": "Preserve originals (disable WebP conversion)", "preserveOriginalUploadHint": "When enabled, JPEG/PNG/GIF uploads are stored as-is instead of converting to WebP.", "rateLimits": "Rate limits", "rateLimitsHint": "Protect against upload abuse and login brute force.", "loginRateLimitsHint": "Protect the login endpoint from brute-force attempts.", "uploadRateFootnote": "Returns 429 when exceeded within the window. Token uploads are counted separately.", "loginRateFootnote": "Returns 429 when exceeded within the window.", "uploadRateIpMax": "Upload limit (per IP)", "uploadRateTokenMax": "Upload limit (per token)", "uploadRateWindowMinutes": "Upload window (minutes)", "loginRateMax": "Login limit (per IP)", "loginRateWindowMinutes": "Login window (minutes)", "rateLimitsFootnote": "Exceeding the limit within the window returns HTTP 429. Token uploads are counted separately." }, "storage": { "title": "Storage", "subtitle": "New uploads go to the active backend; existing images keep their backend", "activeBackend": "Active backend", "backendLocal": "Local disk", "backendCloud": "Cloud storage", "backendS3": "Cloud storage", "switchHint": "Switching only affects new uploads", "provider": "Preset", "providerR2": "Cloudflare R2", "providerCos": "Tencent COS", "providerOss": "Alibaba OSS", "providerAws": "AWS S3", "providerCustom": "Custom", "providerTelegram": "Telegram channel", "backendTelegram": "Telegram", "telegramChatId": "Chat ID", "telegramChatIdPlaceholder": "-1001234567890", "telegramChatIdHint": "Channel or group ID; the bot must be an admin. Private channels work.", "telegramBotToken": "Bot Token", "telegramApiProxy": "API proxy (optional)", "telegramApiProxyPlaceholder": "http://127.0.0.1:7890", "telegramApiProxyHint": "HTTP/HTTPS proxy for PicHost → Telegram API; leave empty for direct access.", "telegramServingHint": "Image URLs are always served through PicHost, never redirected to Telegram.", "telegramQuotaHint": "Telegram practical limit is ~20MB per file and ~20 messages/min per channel.", "telegramSecretsRequired": "Bot Token and Chat ID are required", "endpoint": "Endpoint", "region": "Region", "bucket": "Bucket", "prefix": "Key prefix (optional)", "prefixPlaceholder": "e.g. pichost", "forcePathStyle": "Force path-style access", "accessKey": "Access Key", "secretKey": "Secret Key", "servingMode": "Serving mode", "servingProxy": "Proxy (same origin)", "servingPublic": "Public URL (302 to CDN)", "servingHint": "In public mode, configure referer protection on CDN/bucket", "publicUrl": "Public base URL", "publicUrlPlaceholder": "https://cdn.example.com", "testConnection": "Test connection", "testSuccess": "Connection successful", "testFailed": "Connection failed", "saved": "Storage settings saved", "saveFailed": "Failed to save storage settings", "loadFailed": "Failed to load storage settings", "envOverride": "Storage is overridden by environment variables", "pageTitle": "Storage management", "pageSubtitle": "Manage backends; new uploads go to the default backend", "addBackend": "Add storage", "editBackend": "Edit storage", "formCreateHint": "Configure cloud storage; set as default after saving to receive new uploads", "formEditHint": "Update connection settings; leave keys blank to keep existing secrets", "sectionBasic": "Basic", "sectionConnection": "Connection", "sectionCredentials": "Credentials", "sectionAccess": "Access", "sectionQuota": "Quota", "advancedOptions": "Advanced", "servingProxyShort": "Proxy", "servingPublicShort": "Public", "backendName": "Display name", "badgeDefault": "Default", "badgeDefaultStorage": "Default storage", "badgeDisabled": "Disabled", "badgeEnabled": "Enabled", "overviewTitle": "Storage overview", "overviewSubtitle": "Usage across all storage backends", "overviewTotal": "Total capacity", "overviewUsed": "Used", "overviewFree": "Free", "overviewUsageRate": "Overall usage", "overviewQuota": "Total quota", "overviewInstances": "Backends", "overviewActive": "Active", "capacityDistribution": "Distribution", "backendType": "Type", "storageId": "Storage ID", "storageType": "Storage type", "badgeLocal": "Local", "defaultStorageTip": "Default storage: new uploads are saved to “{name}”. Use “Set as default” on another backend to change this.", "supportedTitle": "Supported backends", "supportedSubtitle": "PicHost supports multiple storage backends for different scenarios", "supportedLocalDesc": "Ideal for small deployments and personal use", "supportedR2Desc": "Highly available, low-cost object storage", "supportedS3Title": "S3 compatible", "supportedS3Desc": "Storage services compatible with the Amazon S3 API", "supportedTelegramDesc": "Store images in a Telegram channel or group; good for light unlimited storage", "footerTip": "The default backend receives all new uploads", "statTotal": "Total", "statUsed": "Used", "statFree": "Free", "statFileCount": "Files", "statQuota": "Quota", "usageRate": "Usage", "indexImages": "PicHost images {count} · {size}", "setDefault": "Set as default", "actionSetDefault": "Default", "actionTest": "Test", "disable": "Disable", "enable": "Enable", "usageCount": "{count} images", "quotaTotal": "Plan size", "quotaPlaceholder": "e.g. 10", "quotaHint": "Enter your cloud plan size; used space is calculated from PicHost image index", "quotaRequired": "Enter a valid plan size", "notConfigured": "Not configured", "created": "Storage backend added", "deleted": "Storage backend deleted", "deleteFailed": "Delete failed", "deleteBlockedImages": "This backend still has images. Move or delete them before removing the backend.", "defaultUpdated": "Default backend updated", "deleteConfirmTitle": "Delete storage", "deleteConfirmBody": "Delete “{name}”? This cannot be undone.", "secretsRequired": "Access Key and Secret Key are required for new storage", "manageStorage": "Manage object storage", "manageStorageHint": "Configure R2 / S3 / COS backends and URL serving", "backup": { "sectionTitle": "Backup & migration", "sectionSubtitle": "Full-site backup, restore, and cross-backend image migration", "siteTitle": "Site backup & restore", "siteSubtitle": "For migration, disaster recovery, and full-site restore", "siteFooterHint": "Backups include the database and images, not plain-text secret_json.", "exportTitle": "Create site backup", "exportSubtitle": "Package the database and all images as .phost.tar.gz", "exportAction": "Start backup", "exportStarted": "Backup job started", "exportFailed": "Failed to start backup", "exportPathHint": "Exports are saved under data/backups/", "exportIncludesTitle": "Package includes", "exportIncludesDb": "Database snapshot (pichost.db)", "exportIncludesImages": "All image files ({count})", "exportExcludesSecrets": "Excludes plain-text secret.json for cloud storage", "exportConcurrencyHint": "Only one backup or migration job can run at a time", "estimateLoading": "Estimating size…", "estimateImageCountLabel": "Images", "estimatePackageSizeLabel": "Est. package", "estimateDatabaseSnapshotLabel": "Database snapshot", "estimateStoragePathLabel": "Save location", "estimateStoragePathValue": "data/backups/", "estimateImages": "{count} images · {size}", "estimateDatabase": "Database ~{size}", "estimateTotal": "Total ~{size}", "restoreTitle": "Restore from backup", "restoreSubtitle": "Upload or pick a .phost.tar.gz on the server, preview, then confirm", "restoreUpload": "Choose backup file", "restoreUploadLabel": "Upload from device", "restoreUploadHint": "Click to select a .phost.tar.gz backup", "restoreUploadAction": "Upload & restore", "restoreServerAction": "Server backup", "restoreServerPackages": "Server backups", "restoreServerSelectPlaceholder": "Select a backup", "restorePreview": "Preview", "restorePreviewConfirm": "Preview & confirm", "restoreConfirm": "Confirm restore", "restoreConfirmTitle": "Confirm site restore", "restoreConfirmSource": "Source: {name}", "restoreOverwriteWarning": "Overwrite mode replaces conflicting images and the database. Ensure you have a current backup.", "restoreSelectRequired": "Select or upload a backup file", "restoreStarted": "Restore job started", "restoreFailed": "Restore failed", "conflictMode": "Conflict policy", "conflictSkip": "Skip existing images", "conflictOverwrite": "Overwrite existing images and database", "syncTitle": "Cross-backend sync", "syncMigrateTitle": "Cross-backend migration", "syncMigrateSubtitle": "Migrate images between configured backends", "syncSubtitle": "Copy images between configured backends and update the index", "syncFrom": "Source backend", "syncTo": "Target backend", "syncPendingImages": "Images to migrate", "syncPendingSize": "Est. size", "syncIncludesTitle": "What sync does", "syncIncludesCopy": "Copy image files from source to target backend", "syncIncludesIndex": "Update storage_backend_id in the index", "syncIncludesConfig": "Site settings and other backends are unchanged", "syncDryRun": "Dry run only", "syncSetDefaultAfter": "Set target as default after migration", "syncStartMigrate": "Start migration", "syncPreviewOnly": "Preview", "syncFooterHint": "Only image files and index are migrated; site settings are unchanged.", "syncDeleteSource": "Delete source files after sync", "syncSetDefault": "Set target as default after sync", "syncPreview": "Preview & start", "syncConfirm": "Start sync", "syncConfirmTitle": "Confirm cross-backend sync", "syncDeleteWarning": "Source files will be deleted. This cannot be undone.", "syncSelectRequired": "Select source and target backends", "syncSameBackend": "Source and target must differ", "syncStarted": "Sync job started", "syncFailed": "Sync failed", "previewFailed": "Preview failed", "previewImages": "Images", "previewNew": "New images", "previewConflicts": "Conflicts", "previewCreated": "Backup created", "previewSize": "Data size", "jobsTitle": "Recent jobs", "jobsSubtitle": "Track backup, restore, and migration progress", "jobsEmpty": "No backup or migration jobs yet", "jobsEmptyHint": "Progress appears here after export, restore, or sync starts", "jobsUnit": "jobs", "colTask": "Task", "colType": "Type", "colStatus": "Status", "colProgress": "Progress", "colMessage": "Message", "colCreated": "Created", "colActions": "Actions", "jobTypeExport": "Site export", "jobTypeRestore": "Site restore", "jobTypeSync": "Cross-backend sync", "statusPending": "Pending", "statusRunning": "Running", "statusDone": "Done", "statusFailed": "Failed", "jobFailedUnknown": "Unknown error", "download": "Download", "jobView": "View", "retry": "Retry", "retryStarted": "Retry started", "retryFailed": "Retry failed", "jobRunning": "Another job is already running. Try again later.", "migrateIn": "Migrate in", "migrateOut": "Migrate out", "migrateInHint": "Copy images from the default backend to this one", "migrateOutHint": "Move images out of this backend", "syncDraftApplied": "Sync form prefilled — review and start when ready", "syncNeedTwoBackends": "At least two storage backends are required to sync", "selectBackend": "Select backend", "syncConfirmRoute": "{from} → {to}", "cancel": "Cancel", "cancelDone": "Job cancelled", "cancelFailed": "Failed to cancel job" } }, "stats": { "title": "Gallery", "subtitle": "Browse, search, and manage uploaded images", "uploadToday": "Uploaded today", "uploadMonth": "Uploaded this month", "uploadTotal": "Total uploads", "storedCount": "Stored now", "totalFiles": "Total files", "totalOccupied": "{size} used", "storageUsage": "Storage usage", "noQuota": "No quota configured", "vsYesterday": "vs yesterday", "vsLastMonth": "vs last month", "trendUp": "↑ {p}%", "trendDown": "↓ {p}%", "trendFlat": "flat", "deleteToday": "Deleted today", "deleteMonth": "Deleted this month", "deleteTotal": "Total deleted", "userCount": "Registered users", "uploadBytes": "Total upload size", "sourceDistribution": "Uploads by source", "sourceWeb": "Web", "sourceApi": "API", "tagWeb": "Web", "tagApi": "API", "noData": "No data", "gallery": "Gallery", "imagesSection": "All images", "filterStorageAll": "All storage", "storage": "Storage", "searchPlaceholder": "Search filename", "searchPlaceholderWide": "Search filename, tags, or links", "filterType": "Image type", "filterTypeAll": "All types", "filterSource": "Upload source", "filterSourceAll": "All sources", "sourceWeb": "Web upload", "sourceApi": "API upload", "resetFilters": "Reset", "batchActions": "Bulk actions", "selectedItems": "{n} selected", "colFilename": "Filename", "colPreview": "Preview", "colSize": "Size", "colType": "Type", "colSource": "Source", "colUploadedAt": "Uploaded", "colActions": "Actions", "previewBadge": "Image", "clear": "Clear", "selected": "{n} selected", "batchDelete": "Delete selected", "batchSelect": "Batch select", "viewMode": "View mode", "viewGrid": "Grid view", "viewList": "List view", "selectAll": "Select all", "invertSelection": "Invert", "clearSelection": "Clear selection", "scrollTop": "Back to top", "loadFailed": "Failed to load statistics", "selectFirst": "Select images first", "deleted": "Deleted {n} image(s)", "deletePartialFail": "{n} image(s) failed to delete", "deleteFailed": "Delete failed", "deletedSingle": "Deleted", "counting": "Counting…", "summarySearch": "Search “{q}” · {total} images", "summaryTotal": "{total} images", "summarySearchStorage": "{storage} · Search “{q}” · {total} images", "summaryTotalStorage": "{storage} · {total} images" }, "logs": { "pageTitle": "Activity log", "pageSubtitle": "Your activity history", "pageSubtitleAdmin": "Activity history for all users", "loadFailed": "Failed to load activity log", "empty": "No activity yet", "entriesUnit": "entries", "filterActionAll": "All actions", "filterSourceAll": "All sources", "filterUserAll": "All users", "searchPlaceholder": "Search filename, path, or IP", "dateFrom": "Start date", "dateTo": "End date", "dateRangeSeparator": "~", "summaryAll": "All · {total} entries, {upload} uploads, {delete} deletes", "actionUpload": "Upload", "actionDelete": "Delete", "actionLogin": "Login", "actionEdit": "Edit", "actionSettings": "Settings", "actionTags": "Tags", "sourceWeb": "Web", "sourceApi": "API", "sourceAdmin": "Admin", "colTime": "Time", "colUser": "User", "colStorage": "Storage", "colAction": "Action", "colSource": "Source", "colFile": "File", "colFolder": "Folder", "colSize": "Size", "colKey": "Path", "colIp": "IP address", "colResult": "Result", "resultSuccess": "Success", "resultFailure": "Failed" }, "image": { "empty": "No images", "previewFailed": "Preview failed", "openPreview": "View full image", "previewTitle": "Image details", "previewSubtitle": "View image info and links", "previewOriginalName": "Filename", "previewUploadedAt": "Uploaded", "previewSize": "Size", "previewSizeDetail": "{size} ({bytes} bytes)", "previewContentType": "File type", "previewOwner": "Uploader", "previewStorage": "Storage", "previewKey": "Image path", "previewExtension": "Extension", "previewDimensions": "Dimensions", "previewDimensionsUnknown": "Loading…", "previewUploadSource": "Upload source", "uploadSourceUnknown": "Unknown", "previewLinks": "Links & embed", "previewCopyLink": "Copy link", "previewDownload": "Download", "previewOpen": "Open in new tab", "previewClose": "Close", "uploader": "Uploader: {name}", "storageBackend": "Storage: {name}" }, "delete": { "confirmTitle": "Confirm delete", "confirmDesc": "Delete {count} selected image(s)? This cannot be undone.", "confirm": "Delete" }, "pagination": { "totalCount": "{total} {unit}", "pageStatus": "Page {page} / {totalPages}", "perPage": "{size} / page", "pageSize": "Page size", "pageNumber": "Page {page}", "pageOf": "Page {page} / {totalPages} · {total} {unit}", "totalOnly": "{total} {unit}", "first": "First page", "prev": "Previous page", "next": "Next page", "last": "Last page", "goTo": "Go", "goToPrefix": "Go to", "goToSuffix": "", "pagePlaceholder": "Page" }, "api": { "tokenTitle": "API token", "envOverrideTitle": "Token overridden by environment", "envOverrideDesc": "Restart after changing API_UPLOAD_TOKEN; cannot regenerate in UI.", "personalTitle": "Personal API token", "personalDesc": "For your scripts only; uploads belong to your account.", "notConfiguredTitle": "No token configured", "notConfiguredDesc": "A token is created automatically on first visit, or click Regenerate.", "regenerate": "Regenerate", "tokenSourceEnv": "Source: API_UPLOAD_TOKEN environment variable", "tokenSourceDb": "Source: generated in app (can regenerate)", "tokenSourceNone": "Source: not configured", "tokenHeader": "Header:", "tokenInvalidate": "Old token is invalidated immediately after regenerate", "docsTitle": "API reference", "curlExample": "cURL example", "loadFailed": "Failed to load API settings", "regenerateEnvBlocked": "Token is set via environment; cannot regenerate in UI", "regenerateFailed": "Failed to regenerate token", "confirmRegenerateTitle": "Regenerate token?", "confirmRegenerateDesc": "The old token stops working immediately. Update scripts and automation before continuing.", "confirmRegenerate": "Regenerate", "newTokenTitle": "New token generated", "newTokenDesc": "Copy and save it now. You can copy again from the field above after closing.", "copyToken": "Copy token", "saved": "Saved", "searchPlaceholder": "Search endpoints…", "showToken": "Show", "hideToken": "Hide", "helpText": "Need help? Read the full API docs", "helpTitle": "Need help?", "helpSubtitle": "Read the full API docs", "expand": "Expand", "collapse": "Collapse", "viewDocs": "View docs", "requestParams": "Request parameters", "paramName": "Name", "paramType": "Type", "paramLocation": "In", "paramRequired": "Required", "paramDescription": "Description", "required": "Yes", "optional": "No", "requestExample": "Request example", "responseExample": "Response example", "categories": { "image": "Images", "extension": "Plugins", "system": "System" }, "params": { "upload": { "image": "Primary upload field", "file": "Compatibility field, single file", "files": "Compatibility field, multiple files", "token": "Twikoo protocol form token", "tagNames": "Optional JSON array or comma-separated names; creates or reuses tags" }, "list": { "limit": "Page size, default 20, max 100", "page": "Page number, starts at 1" }, "search": { "q": "Search keyword, required" }, "delete": { "key": "Storage path, e.g. images/2026/08/xxx.webp" }, "batchDelete": { "keys": "Array of image keys to delete" }, "twikoo": { "image": "Image file", "token": "API token" }, "backendId": "Storage backend ID, optional" }, "debug": { "title": "Try it", "headers": "Headers", "query": "Query", "body": "Body", "send": "Send request", "response": "Response", "selectFile": "Select file", "noFileSelected": "No file selected", "tokenPlaceholder": "Enter Auth-Token", "invalidJson": "Invalid JSON", "sendFailed": "Request failed", "networkError": "Network error or unreachable", "notesTitle": "Notes", "noteSuccess": "200 means success with JSON body", "noteError": "4xx / 5xx means failure; check error field", "noteLimit": "Upload limit: up to 10 files, 10 MB each" }, "docs": { "upload": { "title": "Upload images", "desc": "Upload one or more images via image field. Also accepts file, files. Stored under images/." }, "list": { "title": "List images", "desc": "Paginated gallery. limit default 20, max 100." }, "search": { "title": "Search images", "desc": "Search by filename or path; q is required." }, "delete": { "title": "Delete image", "desc": "Delete by key (storage path, e.g. images/2026/08/xxx.webp)." }, "batchDelete": { "title": "Batch delete", "desc": "Delete multiple images; request body is a keys array." }, "twikoo": { "title": "Twikoo-compatible upload", "desc": "Twikoo / EasyImage 2.0 protocol; stored under images/. Fields: image + token." }, "config": { "title": "Get config", "desc": "Public system config; no authentication required." }, "count": { "title": "Image count", "desc": "Total images in your visible scope." } } }, "userSettings": { "loadFailed": "Failed to load settings", "saveFailed": "Failed to save settings" } }