1266 lines
57 KiB
JSON
1266 lines
57 KiB
JSON
{
|
||
"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",
|
||
"continue": "Continue",
|
||
"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",
|
||
"videoLibrary": "Video library",
|
||
"fileLibrary": "File library",
|
||
"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 separated-domain settings?",
|
||
"description": "After saving, the admin URL serves the admin UI and API, while the image, video and file URLs serve only their corresponding media 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, image, video and file domains",
|
||
"domainSeparationHint": "Allow admin, images, videos and files to each use a dedicated domain.",
|
||
"domainSeparationProxyHint": "Point the configured 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",
|
||
"videoBaseUrl": "Video URL",
|
||
"videoBaseUrlHint": "No trailing slash; falls back to the image URL when empty",
|
||
"videoBaseUrlPlaceholder": "https://video.example.com",
|
||
"fileBaseUrl": "File URL",
|
||
"fileBaseUrlHint": "No trailing slash; falls back to the image URL when empty",
|
||
"fileBaseUrlPlaceholder": "https://file.example.com",
|
||
"domainSeparationInvalid": "Enter valid admin, image, video and file URLs",
|
||
"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 {size} 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",
|
||
"videoProcessing": "Video processing",
|
||
"lowMemoryTranscodeTitle": "Low-memory server warning",
|
||
"lowMemoryTranscodeHint": "This machine has about {memory} GB of memory, below 2 GB. HLS transcoding is not recommended for now because it may exhaust memory or make the service unstable.",
|
||
"transcodeToHls": "Transcode to m3u8",
|
||
"transcodeToHlsHint": "Segment into HLS, uses extra CPU.",
|
||
"concurrentHint": "at a time",
|
||
"threadsHint": "per job",
|
||
"transcodeConcurrency": "Concurrent transcodes",
|
||
"transcodeThreads": "CPU threads",
|
||
"unitCount": "",
|
||
"transcodeQuality": "Quality",
|
||
"presetCopy": "Remux",
|
||
"presetSpeed": "Speed",
|
||
"presetBalanced": "Balanced",
|
||
"presetQuality": "Quality",
|
||
"presetCompress": "Compress",
|
||
"compressBitrate": "Target bitrate",
|
||
"transcodeLoadFailed": "Failed to load transcode settings",
|
||
"transcodeSaveFailed": "Failed to save transcode settings",
|
||
"autoCopy": "Copy link after upload",
|
||
"autoCopyHint": "Copy to clipboard in the selected format",
|
||
"uploadTags": "Upload tags",
|
||
"uploadTagsHint": "Press Enter, type a comma, or leave the field to add a tag. Leave empty to upload without tags.",
|
||
"uploadTagsPlaceholder": "Enter tag",
|
||
"uploadTagsPending": "Pending tags ({n})",
|
||
"uploadTagsRemove": "Remove tag {name}"
|
||
},
|
||
"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 admin, image, video and file domains plus 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": "Configured domains must resolve to this host",
|
||
"domainSeparationProxyBody": "Point the admin and configured image, video and file domains to this host and reverse-proxy to port 6892 (Nginx, Caddy, NPM, etc.).",
|
||
"siteBaseUrlRoleHint": "Admin and API use this domain; resources use it when their switches are off",
|
||
"imageBaseUrlRoleHint": "Use this domain for images when on; use the site domain when off",
|
||
"resourceDomainSection": "Resource domains",
|
||
"videoBaseUrl": "Video URL",
|
||
"videoBaseUrlRoleHint": "Use this domain for videos, HLS and thumbnails when on; use the site domain when off",
|
||
"videoBaseUrlPlaceholder": "https://video.example.com",
|
||
"videoBaseUrlActive": "Active: {url}",
|
||
"fileBaseUrl": "File URL",
|
||
"fileBaseUrlRoleHint": "Use this domain for file links and downloads when on; use the site domain when off",
|
||
"fileBaseUrlPlaceholder": "https://file.example.com",
|
||
"fileBaseUrlActive": "Active: {url}",
|
||
"fallbackImageDomain": "Uses image URL",
|
||
"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)",
|
||
"fileBed": "File bed",
|
||
"fileBedHint": "Access mode for file download links. Takes effect immediately.",
|
||
"fileBedPublic": "Public",
|
||
"fileBedPublicHint": "Anyone with the link can download. Best for sharing.",
|
||
"fileBedToken": "Token required",
|
||
"fileBedTokenHint": "Downloads must carry a token (append ?token= to the link). Best for private files.",
|
||
"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: admin, images, videos and files can use dedicated domains",
|
||
"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}",
|
||
"resourceBaseUrl": "Domain",
|
||
"resourceBaseUrlSingleHint": "No trailing slash; leave empty to use the current request host. When domain separation is off, this domain serves images, videos and files.",
|
||
"resourceBaseUrlPlaceholder": "https://cdn.example.com",
|
||
"resourceBaseUrlActive": "Current resource domain: {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 admin URL and keeps the image, video and file URLs. Continue?",
|
||
"disableDomainSeparationConfirm": "Disable",
|
||
"domainSeparationRequired": "Admin 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.",
|
||
"videoProcessingHint": "Site-wide transcode resources and personal video upload preferences, shared with the video upload page.",
|
||
"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).",
|
||
"uploadImageMaxFileSize": "Image size limit",
|
||
"uploadImageMaxFileSizeHint": "Images larger than this are rejected, up to 100 MB. 0 MB blocks uploads.",
|
||
"uploadVideoMaxFileSize": "Video size limit",
|
||
"uploadVideoMaxFileSizeHint": "Videos larger than this are rejected, up to 2048 MB. 0 MB blocks uploads.",
|
||
"uploadFileMaxFileSize": "File size limit",
|
||
"uploadFileMaxFileSizeHint": "Regular files larger than this are rejected, up to 1024 MB. 0 MB blocks uploads.",
|
||
"allowedMimeTypes": "Allowed image formats",
|
||
"allowedMimeTypesHint": "Keep at least one format enabled. The server validates file signatures, not just extensions.",
|
||
"allowedVideoExtensions": "Allowed video formats",
|
||
"allowedVideoExtensionsHint": "Keep at least one video container enabled. Both the upload page and server enforce this list.",
|
||
"forbiddenFileExtensions": "Forbidden file formats",
|
||
"forbiddenFileExtensionsHint": "These extensions are rejected by the file upload page and server. You can add custom extensions.",
|
||
"forbiddenFileExtensionsCustomPlaceholder": "Add extensions, e.g. exe, php",
|
||
"forbiddenFileExtensionsAdd": "Add",
|
||
"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": "All new images, videos, and files are saved to “{name}” by default. Use “Set as default” on another backend to change this.",
|
||
"clearStorage": "Clear storage",
|
||
"clearStorageTitle": "Clear my storage",
|
||
"clearStorageDescription": "Permanently delete every image, video, file, and cache uploaded by the current account without affecting other users.",
|
||
"clearStorageWarning": "High-risk operation: this will clear all files and caches in storage and cannot be undone!",
|
||
"clearStorageScope": "Only data and files owned by the current signed-in user are removed. Other users, account settings, storage configuration, and site backups are not affected.",
|
||
"clearStorageFinalTitle": "Final confirmation",
|
||
"clearStorageInstruction": "Type “I confirm” to continue. The operation cannot be cancelled or undone once started.",
|
||
"clearStoragePlaceholder": "I confirm",
|
||
"clearStoragePhrase": "I confirm",
|
||
"clearStorageConfirm": "Permanently clear",
|
||
"clearStorageSuccess": "Cleared {files} files and {cache} temporary caches; storage space has been released",
|
||
"clearStoragePartial": "{failed}/{total} files failed to clear; please retry",
|
||
"clearStorageFailed": "Failed to clear storage; please try again",
|
||
"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 images, videos, and files",
|
||
"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 file migration",
|
||
"siteTitle": "Site backup & restore",
|
||
"siteSubtitle": "For migration, disaster recovery, and full-site restore",
|
||
"siteFooterHint": "Backups include the database and all files, not plain-text secret_json.",
|
||
"exportTitle": "Create site backup",
|
||
"exportSubtitle": "Package the database and all files 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 images, videos, and 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": "Files",
|
||
"estimatePackageSizeLabel": "Est. package",
|
||
"estimateDatabaseSnapshotLabel": "Database snapshot",
|
||
"estimateStoragePathLabel": "Save location",
|
||
"estimateStoragePathValue": "data/backups/",
|
||
"estimateImages": "{count} files · {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 files 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 files",
|
||
"conflictOverwrite": "Overwrite existing files and database",
|
||
"syncTitle": "Cross-backend sync",
|
||
"siteSyncTitle": "Site-to-site sync",
|
||
"siteSyncSubtitle": "Sync media indexes, images, videos, files, thumbnails, HLS segments and tags to another PicHost. Matching usernames must already exist on the target.",
|
||
"siteSyncPushSubtitle": "Push media indexes, images, videos, files, thumbnails, HLS segments and tags to another PicHost. Matching usernames must already exist on the target.",
|
||
"siteSyncPullSubtitle": "Pull media indexes, images, videos, files, thumbnails, HLS segments and tags from another PicHost. Matching usernames must already exist on this site.",
|
||
"siteSyncTarget": "Target site URL",
|
||
"siteSyncSource": "Source site URL",
|
||
"siteSyncToken": "Target admin API token",
|
||
"siteSyncSourceToken": "Source admin API token",
|
||
"siteSyncTokenPlaceholder": "Enter target admin token",
|
||
"siteSyncSourceTokenPlaceholder": "Enter source admin token",
|
||
"siteSyncStart": "Start sync",
|
||
"siteSyncStartPush": "Start push",
|
||
"siteSyncStartPull": "Start pull",
|
||
"siteSyncDirection": "Sync direction:",
|
||
"siteSyncPush": "Push to target",
|
||
"siteSyncPull": "Pull from target",
|
||
"siteSyncConflict": "Conflict policy:",
|
||
"siteSyncSkip": "Skip existing",
|
||
"siteSyncOverwrite": "Overwrite existing",
|
||
"siteSyncResume": "Resume last sync",
|
||
"siteSyncAbandon": "Abandon and clean up",
|
||
"siteSyncAbandonConfirm": "Abandon this sync and delete partial objects created by it that are not yet referenced by a media record?",
|
||
"siteSyncAbandonWithoutTokenConfirm": "No target token is provided. Abandon the task now? Partial objects will be marked for later automatic cleanup on the target.",
|
||
"siteSyncAbandoned": "Sync abandoned and partial objects cleaned up",
|
||
"siteSyncAbandonedPendingCleanup": "Sync abandoned; partial objects still need cleanup",
|
||
"siteSyncScanProgress": "Media scan progress",
|
||
"siteSyncFileProgress": "Synced file count",
|
||
"siteSyncStarted": "Site-to-site sync started",
|
||
"siteSyncFailed": "Failed to start site-to-site sync",
|
||
"syncMigrateTitle": "Cross-backend migration",
|
||
"syncMigrateSubtitle": "Migrate files between configured backends",
|
||
"syncSubtitle": "Copy files between configured backends and update the index",
|
||
"syncFrom": "Source backend",
|
||
"syncTo": "Target backend",
|
||
"syncPendingImages": "Files to migrate",
|
||
"syncPendingSize": "Est. size",
|
||
"syncIncludesTitle": "What sync does",
|
||
"syncIncludesCopy": "Copy images, videos, and 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 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": "Files",
|
||
"previewNew": "New files",
|
||
"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",
|
||
"jobsHideAll": "Hide all",
|
||
"jobsRestoreAll": "Restore all",
|
||
"hiddenJobsShow": "Show hidden",
|
||
"hiddenJobsHide": "Show visible only",
|
||
"jobHide": "Hide from list (keeps the record)",
|
||
"jobUnhide": "Show again",
|
||
"jobHidden": "Job hidden; its record is still retained",
|
||
"jobUnhidden": "Job is visible again",
|
||
"jobsHiddenAll": "All finished jobs hidden; records are still retained",
|
||
"jobsUnhiddenAll": "All hidden jobs are visible again",
|
||
"hideFailed": "Failed to update job visibility",
|
||
"jobsUnit": "jobs",
|
||
"colTask": "Task",
|
||
"colType": "Type",
|
||
"colStatus": "Status",
|
||
"colProgress": "Progress",
|
||
"progressUnitMedia": "media records",
|
||
"progressUnitObjects": "storage objects",
|
||
"colMessage": "Message",
|
||
"colCreated": "Created",
|
||
"colUpdated": "Updated",
|
||
"colActions": "Actions",
|
||
"jobTypeExport": "Site export",
|
||
"jobTypeRestore": "Site restore",
|
||
"jobTypeSync": "Cross-backend sync",
|
||
"jobTypeSiteSync": "Site-to-site 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 files from the default backend to this one",
|
||
"migrateOutHint": "Move files 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": {
|
||
"confirmDescVideo": "Delete the selected {count} video(s)? This cannot be undone.",
|
||
"confirmDescFile": "Delete the selected {count} file(s)? This cannot be undone.",
|
||
"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; uploaded images, videos and files 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",
|
||
"video": "Videos",
|
||
"file": "Files",
|
||
"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"
|
||
},
|
||
"videoUpload": {
|
||
"video": "Primary video field; max 500 MB per file",
|
||
"file": "Compatibility field, can replace video",
|
||
"files": "Compatibility field for multiple videos",
|
||
"transcode": "Set to 1 to transcode to HLS asynchronously; otherwise keep the source and generate a thumbnail",
|
||
"transcodePreset": "Optional preset: copy, veryfast, medium, slow, or compress (target bitrate)",
|
||
"transcodeBitratePercent": "Used by compress only; target bitrate as 10–100% of the source. Uses the current server setting when omitted",
|
||
"token": "Optional; the API token can also be sent with the Auth-Token header"
|
||
},
|
||
"fileUpload": {
|
||
"file": "Primary file field; max 100 MB per file. HTML / HTM / SVG are blocked",
|
||
"files": "Compatibility field for multiple files",
|
||
"token": "Optional; the API token can also be sent with the Auth-Token header"
|
||
},
|
||
"mediaList": {
|
||
"kindVideo": "Set to video to list videos",
|
||
"kindFile": "Set to file to list files",
|
||
"page": "Page number, starts at 1",
|
||
"limit": "Page size, default 20, max 100",
|
||
"q": "Search by filename or path",
|
||
"processing": "Video only; set to 1 to return queued or running transcodes",
|
||
"uploadSource": "Upload source: web or api",
|
||
"tagIds": "Filter by comma-separated tag IDs",
|
||
"tagMode": "Use or or and for multiple tags; default is or",
|
||
"untagged": "Set to 1 to return only untagged items"
|
||
},
|
||
"mediaSearch": {
|
||
"q": "Search keyword matched against filename or storage path; required"
|
||
},
|
||
"videoDelete": {
|
||
"key": "Video storage path; also removes its thumbnail and HLS artifacts"
|
||
},
|
||
"videoBatchDelete": {
|
||
"keys": "Array of video keys; up to 100 per request. Thumbnails and HLS artifacts are also removed"
|
||
},
|
||
"fileDelete": {
|
||
"key": "File storage path, e.g. files/2026/10/xxx.pdf"
|
||
},
|
||
"fileBatchDelete": {
|
||
"keys": "Array of file keys; up to 100 per request"
|
||
},
|
||
"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 a JSON body",
|
||
"noteError": "4xx / 5xx means failure; check error field",
|
||
"noteLimit": "Upload limit: up to 10 files; videos up to 500 MB each, files up to 100 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."
|
||
},
|
||
"videoUpload": {
|
||
"title": "Upload videos",
|
||
"desc": "Upload MP4 / WebM / MOV / MKV and more, up to 10 files and 500 MB each. A thumbnail is generated independently; transcode=1 starts asynchronous HLS transcoding."
|
||
},
|
||
"videoList": {
|
||
"title": "List videos",
|
||
"desc": "Use kind=video to list videos, including untranscoded, completed and failed items. processing=1 returns only queued or running jobs."
|
||
},
|
||
"videoDelete": {
|
||
"title": "Delete video",
|
||
"desc": "Delete a video by key, including its thumbnail and generated HLS playlist and segments."
|
||
},
|
||
"videoSearch": {
|
||
"title": "Search videos",
|
||
"desc": "Search by filename or storage path with pagination, backend, upload source and tag filters; q is required."
|
||
},
|
||
"videoBatchDelete": {
|
||
"title": "Batch delete videos",
|
||
"desc": "Delete up to 100 videos at once, including each video's thumbnail, HLS playlist and segments."
|
||
},
|
||
"fileUpload": {
|
||
"title": "Upload files",
|
||
"desc": "Upload any file, up to 10 files and 100 MB each. HTML, HTM and SVG are blocked."
|
||
},
|
||
"fileList": {
|
||
"title": "List files",
|
||
"desc": "Use kind=file to paginate file-bed entries with search, storage, source and tag filters."
|
||
},
|
||
"fileDelete": {
|
||
"title": "Delete file",
|
||
"desc": "Delete one file by its storage key. This action cannot be undone."
|
||
},
|
||
"fileSearch": {
|
||
"title": "Search files",
|
||
"desc": "Search by filename or storage path with kind=file, pagination, backend, upload source and tag filters."
|
||
},
|
||
"fileBatchDelete": {
|
||
"title": "Batch delete files",
|
||
"desc": "Delete up to 100 files at once. The response reports deleted and failed keys separately."
|
||
},
|
||
"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."
|
||
}
|
||
}
|
||
},
|
||
"files": {
|
||
"maxFiles": "Up to {n} files per upload",
|
||
"uploadSuccess": "Uploaded {n} file(s)",
|
||
"uploadFailed": "Upload failed, please try again",
|
||
"fileTooLarge": "{name}: exceeds the {limit} MB per-file limit",
|
||
"loadFailed": "Failed to load files",
|
||
"copyLink": "Copy link",
|
||
"download": "Download",
|
||
"deleted": "Deleted",
|
||
"deleteFailed": "Delete failed",
|
||
"videoFormatBlocked": "{format} videos are not allowed",
|
||
"fileFormatBlocked": "{format} files are not allowed"
|
||
},
|
||
"host": {
|
||
"video": "Video",
|
||
"file": "File",
|
||
"imageFull": "Personal lightweight image host",
|
||
"videoFull": "Personal lightweight video host",
|
||
"fileFull": "Personal lightweight file host"
|
||
},
|
||
"library": {
|
||
"play": "Play",
|
||
"copyVideoLink": "Copy video link",
|
||
"copyThumbLink": "Copy thumbnail link",
|
||
"selectedCount": "{n} selected",
|
||
"selectFirst": "Select videos first",
|
||
"clearSelection": "Clear",
|
||
"reset": "Reset",
|
||
"batchDelete": "Delete",
|
||
"deleted": "Deleted {n} video(s)",
|
||
"fileDeleted": "Deleted {n} file(s)",
|
||
"deletePartialFail": "{n} video(s) failed to delete",
|
||
"statsToday": "Uploaded today",
|
||
"statsMonth": "This month",
|
||
"statsTotal": "Videos",
|
||
"statsBytes": "Total size",
|
||
"statsUsage": "Storage usage",
|
||
"statsSource": "Upload source",
|
||
"statsTotalHintVideo": "Total videos",
|
||
"statsTotalHintFile": "Total files",
|
||
"statsTotalHintImage": "Total images",
|
||
"statsVsYesterday": "vs yesterday {value}",
|
||
"statsVsLastMonth": "vs last month {value}",
|
||
"transcodePending": "Queued",
|
||
"transcoding": "Transcoding",
|
||
"transcodeFailed": "Transcode failed",
|
||
"searchPlaceholder": "Search file name",
|
||
"searchEmpty": "Nothing matched",
|
||
"clearSearch": "Clear search",
|
||
"file": {
|
||
"title": "File bed",
|
||
"subtitle": "Manage uploaded files, copy links or download",
|
||
"uploadTitle": "Drop files here to upload",
|
||
"uploadHint": "or click to choose files, up to 10 at a time",
|
||
"uploadFormats": "Any type allowed (HTML / HTM / SVG blocked), up to {size} MB per file",
|
||
"uploadFormatsBlocked": "{formats} blocked; other file types allowed, up to {size} MB per file",
|
||
"uploadFormatsUnrestricted": "Any file type allowed, up to {size} MB per file",
|
||
"empty": "No files yet — upload one to get started"
|
||
},
|
||
"video": {
|
||
"title": "Videos",
|
||
"subtitle": "Manage uploaded videos, copy links or download",
|
||
"previewTitle": "Video details",
|
||
"previewSubtitle": "View video info and links",
|
||
"previewTranscode": "Transcode",
|
||
"previewThumbLink": "Thumbnail link",
|
||
"previewKey": "Video path",
|
||
"transcodeNone": "Not transcoded",
|
||
"transcodeDone": "Done (m3u8)",
|
||
"transcodeErrorFfmpegMissing": "No FFmpeg",
|
||
"transcodeErrorPermissionDenied": "File permission denied",
|
||
"transcodeErrorUnknown": "Unknown reason",
|
||
"downloadMp4": "Download MP4",
|
||
"downloadMp4Title": "Download MP4 video",
|
||
"downloadMp4Confirm": "The video segments will be merged into an MP4 file. Continue?",
|
||
"downloadMp4Working": "Merging video segments, please wait…",
|
||
"downloadMp4Failed": "Video merge failed. Please try again later.",
|
||
"uploadTitle": "Drop videos here to upload",
|
||
"uploadHint": "or click to choose video files, up to 10 at a time",
|
||
"uploadFormats": "MP4 / WebM / MOV / MKV and more, up to {size} MB per file",
|
||
"uploadFormatsAllowed": "{formats} supported, up to {size} MB per file",
|
||
"empty": "No videos yet — upload one to get started"
|
||
}
|
||
},
|
||
"userSettings": {
|
||
"loadFailed": "Failed to load settings",
|
||
"saveFailed": "Failed to save settings"
|
||
}
|
||
}
|