From 4cd9ad00d2797e63c072cf6d3475938c02b20736 Mon Sep 17 00:00:00 2001 From: shuaiplus <2327005759@qq.com> Date: Sat, 27 Jun 2026 12:38:41 +0800 Subject: [PATCH] Add backup-related error messages and improve UI styles - Updated English, Spanish, Russian, Simplified Chinese, and Traditional Chinese locale files to include new error messages related to backup and restore processes. - Added prefix and suffix strings for the "cached empty" message to enhance clarity in user prompts. - Enhanced the management CSS with new styles for the backup browser refresh prompt to improve layout and user experience. --- webapp/src/components/BackupCenterPage.tsx | 3 +- .../backup-center/RemoteBackupBrowser.tsx | 16 +++- webapp/src/lib/i18n.ts | 88 +++++++++++++++++++ webapp/src/lib/i18n/locales/en.ts | 75 ++++++++++++++++ webapp/src/lib/i18n/locales/es.ts | 75 ++++++++++++++++ webapp/src/lib/i18n/locales/ru.ts | 75 ++++++++++++++++ webapp/src/lib/i18n/locales/zh-CN.ts | 75 ++++++++++++++++ webapp/src/lib/i18n/locales/zh-TW.ts | 75 ++++++++++++++++ webapp/src/styles/management.css | 4 + 9 files changed, 483 insertions(+), 3 deletions(-) diff --git a/webapp/src/components/BackupCenterPage.tsx b/webapp/src/components/BackupCenterPage.tsx index 2537db1..de38543 100644 --- a/webapp/src/components/BackupCenterPage.tsx +++ b/webapp/src/components/BackupCenterPage.tsx @@ -193,7 +193,7 @@ export default function BackupCenterPage(props: BackupCenterPageProps) { const [downloadingRemotePercent, setDownloadingRemotePercent] = useState(null); const [restoringRemotePath, setRestoringRemotePath] = useState(''); const [deletingRemotePath, setDeletingRemotePath] = useState(''); - const [localError, setLocalError] = useState(''); + const [, setLocalError] = useState(''); const [restoreProgress, setRestoreProgress] = useState(null); const [restoreElapsedSeconds, setRestoreElapsedSeconds] = useState(0); const [confirmLocalRestoreOpen, setConfirmLocalRestoreOpen] = useState(false); @@ -974,7 +974,6 @@ export default function BackupCenterPage(props: BackupCenterPageProps) { }} /> - {localError ?
{localError}
: null} {restoreProgress && typeof document !== 'undefined' ? createPortal((
diff --git a/webapp/src/components/backup-center/RemoteBackupBrowser.tsx b/webapp/src/components/backup-center/RemoteBackupBrowser.tsx index a07fdd1..0faa00c 100644 --- a/webapp/src/components/backup-center/RemoteBackupBrowser.tsx +++ b/webapp/src/components/backup-center/RemoteBackupBrowser.tsx @@ -32,6 +32,18 @@ export function RemoteBackupBrowser(props: RemoteBackupBrowserProps) { : t('txt_downloading_percent', { percent: props.downloadingRemotePercent }); }; + const renderRefreshPrompt = () => ( +
+ + {t('txt_backup_remote_cached_empty_prefix')} + + {t('txt_backup_remote_cached_empty_suffix')} + +
+ ); + return ( <>
@@ -42,8 +54,10 @@ export function RemoteBackupBrowser(props: RemoteBackupBrowserProps) { {!props.destinationIsSaved ? (
{t('txt_backup_remote_save_first')}
+ ) : props.loadingRemoteBrowser && !props.remoteBrowser ? ( +
{t('txt_backup_remote_loading')}
) : !props.remoteBrowser ? ( -
{t('txt_backup_remote_cached_empty')}
+ renderRefreshPrompt() ) : ( <>
diff --git a/webapp/src/lib/i18n.ts b/webapp/src/lib/i18n.ts index 93a3ced..f6ea5b0 100644 --- a/webapp/src/lib/i18n.ts +++ b/webapp/src/lib/i18n.ts @@ -113,27 +113,115 @@ export function translateServerError(message: string | null | undefined, fallbac return t('txt_rate_limit_try_again_seconds', { seconds: rateLimitMatch[1] }); } + const backupDestinationLimitMatch = normalized.match(/^You can save up to (\d+) backup destinations$/i); + if (backupDestinationLimitMatch) { + return t('txt_backup_error_destination_limit', { count: backupDestinationLimitMatch[1] }); + } + + const backupArchiveVerificationMatch = normalized.match(/^Backup archive upload verification failed after (\d+) attempts: (.+)$/i); + if (backupArchiveVerificationMatch) { + return t('txt_backup_error_archive_upload_verification_failed_attempts', { + count: backupArchiveVerificationMatch[1], + reason: translateServerError(backupArchiveVerificationMatch[2], backupArchiveVerificationMatch[2]), + }); + } + + const remoteAttachmentStatusMatch = normalized.match(/^Remote attachment (download|batch download) failed: (\d+)$/i); + if (remoteAttachmentStatusMatch) { + return t( + remoteAttachmentStatusMatch[1].toLowerCase() === 'batch download' + ? 'txt_backup_error_remote_attachment_batch_download_failed_status' + : 'txt_backup_error_remote_attachment_download_failed_status', + { status: remoteAttachmentStatusMatch[2] } + ); + } + + const providerStatusMatch = normalized.match(/^(WebDAV|S3) (directory creation|upload|listing|download|delete|existence check) failed: (\d+)$/i); + if (providerStatusMatch) { + const provider = providerStatusMatch[1].toLowerCase() === 'webdav' ? 'webdav' : 's3'; + const actionKey = providerStatusMatch[2].toLowerCase().replace(/\s+/g, '_'); + return t(`txt_backup_error_${provider}_${actionKey}_failed_status`, { status: providerStatusMatch[3] }); + } + const key = { 'Account is disabled': 'txt_server_error_account_disabled', + 'Another backup or restore run is already in progress': 'txt_backup_error_another_backup_or_restore_running', + 'Another backup run is already in progress': 'txt_backup_error_another_backup_running', + 'Backup archive upload failed': 'txt_backup_error_archive_upload_failed', + 'Backup attachment blob is invalid': 'txt_backup_error_attachment_blob_invalid', + 'Backup attachment blob is required': 'txt_backup_error_attachment_blob_required', + 'Backup attachment blob not found': 'txt_backup_error_attachment_blob_not_found', + 'Backup attachment download failed': 'txt_backup_error_attachment_download_failed', + 'Backup destination is invalid': 'txt_backup_error_destination_invalid', + 'Backup destination not found': 'txt_backup_error_destination_not_found', + 'Backup destination ids must be unique': 'txt_backup_error_destination_ids_unique', + 'Backup destination type is invalid': 'txt_backup_error_destination_type_invalid', + 'Backup destinations are invalid': 'txt_backup_error_destinations_invalid', + 'Backup export payload is invalid': 'txt_backup_error_export_payload_invalid', + 'Backup file checksum does not match its filename': 'txt_backup_error_file_checksum_mismatch', + 'Backup file is required': 'txt_backup_error_file_required', + 'Backup interval hours must be between 1 and 99': 'txt_backup_error_interval_hours_range', + 'Backup retention count must be between 1 and 1000': 'txt_backup_error_retention_count_range', + 'Backup run failed': 'txt_backup_error_run_failed', + 'Backup run payload is invalid': 'txt_backup_error_run_payload_invalid', + 'Backup run response is invalid': 'txt_backup_error_run_response_invalid', + 'Backup settings are invalid': 'txt_backup_error_settings_invalid', + 'Backup settings could not be loaded': 'txt_backup_error_settings_load_failed', + 'Backup settings envelope is invalid': 'txt_backup_error_settings_envelope_invalid', + 'Backup settings need administrator reactivation after restore': 'txt_backup_error_settings_need_reactivation', + 'Backup settings payload is invalid': 'txt_backup_error_settings_payload_invalid', + 'Backup settings repair payload is invalid': 'txt_backup_error_settings_repair_payload_invalid', + 'Backup settings repair state could not be loaded': 'txt_backup_error_settings_repair_state_load_failed', + 'Backup start time must be in HH:mm format': 'txt_backup_error_start_time_format', 'Client IP is required': 'txt_server_error_client_ip_required', 'ClientId or clientSecret is incorrect. Try again': 'txt_server_error_client_credentials_incorrect', + 'Content-Type must be multipart/form-data': 'txt_backup_error_multipart_required', 'Email already registered': 'txt_server_error_email_already_registered', 'Email and password are required': 'txt_server_error_email_password_required', 'Email is required': 'txt_server_error_email_required', + 'Forbidden': 'txt_server_error_forbidden', 'Invite code is invalid or expired': 'txt_server_error_invite_invalid_or_expired', 'Invite code is required': 'txt_server_error_invite_required', + 'Invalid backup timezone': 'txt_backup_error_timezone_invalid', + 'Invalid password': 'txt_server_error_invalid_password', 'Invalid refresh token': 'txt_server_error_invalid_refresh_token', + 'Invalid remote backup path': 'txt_backup_error_remote_path_invalid', 'Invalid request payload': 'txt_server_error_invalid_request_payload', + 'Invalid user verification token': 'txt_server_error_invalid_user_verification_token', 'JWT_SECRET is not set': 'txt_server_error_jwt_secret_missing', 'JWT_SECRET is using the default/sample value. Please change it.': 'txt_server_error_jwt_secret_default', 'JWT_SECRET must be at least 32 characters': 'txt_server_error_jwt_secret_too_short', 'Parameter error': 'txt_server_error_parameter_error', + 'Please select a backup file': 'txt_backup_error_select_backup_file', + 'Please select a backup ZIP file': 'txt_backup_error_select_backup_zip_file', 'Refresh token is required': 'txt_server_error_refresh_token_required', + 'Remote backup ZIP checksum verification failed': 'txt_backup_error_remote_zip_checksum_failed', + 'Remote backup ZIP size verification failed': 'txt_backup_error_remote_zip_size_failed', + 'Remote backup delete failed': 'txt_backup_error_remote_delete_failed', + 'Remote backup download failed': 'txt_backup_error_remote_download_failed', + 'Remote backup download payload is invalid': 'txt_backup_error_remote_download_payload_invalid', + 'Remote backup integrity inspection failed': 'txt_backup_error_remote_integrity_failed', + 'Remote backup listing failed': 'txt_backup_error_remote_listing_failed', + 'Remote restore payload is invalid': 'txt_backup_error_remote_restore_payload_invalid', 'Registration is temporarily unavailable, retry once': 'txt_server_error_registration_retry', + 'S3 access key is required': 'txt_backup_error_s3_access_key_required', + 'S3 bucket is required': 'txt_backup_error_s3_bucket_required', + 'S3 endpoint is required': 'txt_backup_error_s3_endpoint_required', + 'S3 endpoint must start with http:// or https://': 'txt_backup_error_s3_endpoint_protocol', + 'S3 secret key is required': 'txt_backup_error_s3_secret_key_required', 'TOTP token is required': 'txt_server_error_totp_token_required', 'Two factor required.': 'txt_server_error_two_factor_required', 'Two-step token is invalid. Try again.': 'txt_server_error_two_factor_invalid', + 'Unable to read backup file': 'txt_backup_error_read_backup_file_failed', + 'Unsupported backup destination type': 'txt_backup_error_destination_type_unsupported', 'Username or password is incorrect. Try again': 'txt_server_error_username_password_incorrect', + 'WebDAV password is required': 'txt_backup_error_webdav_password_required', + 'WebDAV remote backup path is too deep for safe attachment batching': 'txt_backup_error_webdav_path_too_deep', + 'WebDAV server URL is required': 'txt_backup_error_webdav_url_required', + 'WebDAV server URL must start with http:// or https://': 'txt_backup_error_webdav_url_protocol', + 'WebDAV username is required': 'txt_backup_error_webdav_username_required', + 'masterPasswordHash is required': 'txt_server_error_master_password_hash_required', + 'masterPasswordHash or userVerificationToken is required': 'txt_server_error_master_password_or_verification_required', }[normalized]; return key ? t(key) : normalized; diff --git a/webapp/src/lib/i18n/locales/en.ts b/webapp/src/lib/i18n/locales/en.ts index 172fc1c..a3c1cc3 100644 --- a/webapp/src/lib/i18n/locales/en.ts +++ b/webapp/src/lib/i18n/locales/en.ts @@ -224,6 +224,8 @@ const en: Record = { "txt_backup_restore_progress_remote_finalize_detail": "The server is performing final validation and then switching the verified restore data into the live tables.", "txt_backup_remote_loading": "Loading remote backups...", "txt_backup_remote_cached_empty": "Click Refresh to load this destination.", + "txt_backup_remote_cached_empty_prefix": "Click", + "txt_backup_remote_cached_empty_suffix": "to load this destination.", "txt_backup_remote_empty": "No backup files found in this folder.", "txt_backup_remote_folder": "Folder", "txt_backup_remote_unknown_time": "Unknown time", @@ -247,6 +249,74 @@ const en: Record = { "txt_backup_remote_run_invalid_response": "Invalid remote backup run response", "txt_backup_settings_invalid_response": "Invalid backup settings response", "txt_backup_import_invalid_response": "Invalid backup import response", + "txt_backup_error_another_backup_or_restore_running": "Another backup or restore task is already running.", + "txt_backup_error_another_backup_running": "Another backup task is already running.", + "txt_backup_error_archive_upload_failed": "Backup archive upload failed.", + "txt_backup_error_archive_upload_verification_failed_attempts": "Backup upload verification failed after {count} attempt(s): {reason}", + "txt_backup_error_attachment_blob_invalid": "Backup attachment blob is invalid.", + "txt_backup_error_attachment_blob_required": "Backup attachment blob is required.", + "txt_backup_error_attachment_blob_not_found": "Backup attachment blob not found.", + "txt_backup_error_attachment_download_failed": "Backup attachment download failed.", + "txt_backup_error_destination_invalid": "Backup destination is invalid.", + "txt_backup_error_destination_limit": "You can save up to {count} backup destinations.", + "txt_backup_error_destination_not_found": "Backup destination not found.", + "txt_backup_error_destination_ids_unique": "Backup destination IDs must be unique.", + "txt_backup_error_destination_type_invalid": "Backup destination type is invalid.", + "txt_backup_error_destination_type_unsupported": "Unsupported backup destination type.", + "txt_backup_error_destinations_invalid": "Backup destinations are invalid.", + "txt_backup_error_export_payload_invalid": "Backup export payload is invalid.", + "txt_backup_error_file_checksum_mismatch": "Backup file checksum does not match its filename.", + "txt_backup_error_file_required": "Backup file is required.", + "txt_backup_error_interval_hours_range": "Backup interval must be between 1 and 99 hours.", + "txt_backup_error_multipart_required": "The upload request must use multipart/form-data.", + "txt_backup_error_read_backup_file_failed": "Unable to read backup file.", + "txt_backup_error_remote_attachment_batch_download_failed_status": "Remote attachment batch download failed: HTTP {status}.", + "txt_backup_error_remote_attachment_download_failed_status": "Remote attachment download failed: HTTP {status}.", + "txt_backup_error_remote_delete_failed": "Remote backup delete failed.", + "txt_backup_error_remote_download_failed": "Remote backup download failed.", + "txt_backup_error_remote_download_payload_invalid": "Remote backup download request is invalid.", + "txt_backup_error_remote_integrity_failed": "Remote backup integrity inspection failed.", + "txt_backup_error_remote_listing_failed": "Remote backup listing failed.", + "txt_backup_error_remote_path_invalid": "Remote backup path is invalid.", + "txt_backup_error_remote_restore_payload_invalid": "Remote restore request is invalid.", + "txt_backup_error_remote_zip_checksum_failed": "Remote backup ZIP checksum verification failed.", + "txt_backup_error_remote_zip_size_failed": "Remote backup ZIP size verification failed.", + "txt_backup_error_retention_count_range": "Backup retention count must be between 1 and 1000.", + "txt_backup_error_run_failed": "Backup run failed.", + "txt_backup_error_run_payload_invalid": "Backup run request is invalid.", + "txt_backup_error_run_response_invalid": "Backup run response is invalid.", + "txt_backup_error_s3_access_key_required": "S3 access key is required.", + "txt_backup_error_s3_bucket_required": "S3 bucket is required.", + "txt_backup_error_s3_delete_failed_status": "S3 delete failed: HTTP {status}.", + "txt_backup_error_s3_download_failed_status": "S3 download failed: HTTP {status}.", + "txt_backup_error_s3_endpoint_required": "S3 endpoint is required.", + "txt_backup_error_s3_endpoint_protocol": "S3 endpoint must start with http:// or https://.", + "txt_backup_error_s3_existence_check_failed_status": "S3 existence check failed: HTTP {status}.", + "txt_backup_error_s3_listing_failed_status": "S3 listing failed: HTTP {status}.", + "txt_backup_error_s3_secret_key_required": "S3 secret key is required.", + "txt_backup_error_s3_upload_failed_status": "S3 upload failed: HTTP {status}.", + "txt_backup_error_select_backup_file": "Please select a backup file.", + "txt_backup_error_select_backup_zip_file": "Please select a backup ZIP file.", + "txt_backup_error_settings_envelope_invalid": "Backup settings envelope is invalid.", + "txt_backup_error_settings_invalid": "Backup settings are invalid.", + "txt_backup_error_settings_load_failed": "Backup settings could not be loaded.", + "txt_backup_error_settings_need_reactivation": "Backup settings need administrator reactivation after restore.", + "txt_backup_error_settings_payload_invalid": "Backup settings request is invalid.", + "txt_backup_error_settings_repair_payload_invalid": "Backup settings repair request is invalid.", + "txt_backup_error_settings_repair_state_load_failed": "Backup settings repair state could not be loaded.", + "txt_backup_error_start_time_format": "Backup start time must be in HH:mm format.", + "txt_backup_error_timezone_invalid": "Backup timezone is invalid.", + "txt_backup_error_webdav_delete_failed_status": "WebDAV delete failed: HTTP {status}.", + "txt_backup_error_webdav_directory_creation_failed_status": "WebDAV directory creation failed: HTTP {status}.", + "txt_backup_error_webdav_download_failed_status": "WebDAV download failed: HTTP {status}.", + "txt_backup_error_webdav_existence_check_failed_status": "WebDAV existence check failed: HTTP {status}.", + "txt_backup_error_webdav_listing_failed_status": "WebDAV listing failed: HTTP {status}.", + "txt_backup_error_webdav_password_required": "WebDAV password is required.", + "txt_backup_error_webdav_path_too_deep": "WebDAV remote backup path is too deep for safe attachment batching.", + "txt_backup_error_webdav_upload_failed_status": "WebDAV upload failed: HTTP {status}.", + "txt_backup_error_webdav_url_required": "WebDAV server URL is required.", + "txt_backup_error_webdav_url_protocol": "WebDAV server URL must start with http:// or https://.", + "txt_backup_error_webdav_username_required": "WebDAV username is required.", "txt_backup_destination": "Backup Destination", "txt_backup_protocol_webdav": "WebDAV", "txt_backup_protocol_s3": "S3", @@ -522,16 +592,21 @@ const en: Record = { "txt_server_error_account_disabled": "Account is disabled", "txt_server_error_client_credentials_incorrect": "Client ID or client secret is incorrect. Try again.", "txt_server_error_client_ip_required": "Client IP is required", + "txt_server_error_forbidden": "You do not have permission to perform this action.", "txt_server_error_email_already_registered": "Email already registered", "txt_server_error_email_password_required": "Email and password are required", "txt_server_error_email_required": "Email is required", + "txt_server_error_invalid_password": "Invalid password.", "txt_server_error_invalid_refresh_token": "Session expired. Please sign in again.", + "txt_server_error_invalid_user_verification_token": "Invalid user verification token.", "txt_server_error_invalid_request_payload": "Invalid request payload", "txt_server_error_invite_invalid_or_expired": "Invite code is invalid or expired", "txt_server_error_invite_required": "Invite code is required", "txt_server_error_jwt_secret_default": "JWT_SECRET is using the default/sample value. Please change it.", "txt_server_error_jwt_secret_missing": "JWT_SECRET is not set", "txt_server_error_jwt_secret_too_short": "JWT_SECRET must be at least 32 characters", + "txt_server_error_master_password_hash_required": "Master password verification is required.", + "txt_server_error_master_password_or_verification_required": "Master password or user verification token is required.", "txt_server_error_parameter_error": "Parameter error", "txt_server_error_refresh_token_required": "Session is missing. Please sign in again.", "txt_server_error_registration_retry": "Registration is temporarily unavailable. Please retry once.", diff --git a/webapp/src/lib/i18n/locales/es.ts b/webapp/src/lib/i18n/locales/es.ts index e32b9fd..7675d6f 100644 --- a/webapp/src/lib/i18n/locales/es.ts +++ b/webapp/src/lib/i18n/locales/es.ts @@ -224,6 +224,8 @@ const es: Record = { "txt_backup_restore_progress_remote_finalize_detail": "El servidor está realizando la validación final y luego cambiando los datos de restauración verificados a las tablas activas.", "txt_backup_remote_loading": "Cargando copias remotas...", "txt_backup_remote_cached_empty": "Haga clic en Actualizar para cargar este destino.", + "txt_backup_remote_cached_empty_prefix": "Haga clic en", + "txt_backup_remote_cached_empty_suffix": "para cargar este destino.", "txt_backup_remote_empty": "No se encontraron archivos de copia de seguridad en esta carpeta.", "txt_backup_remote_folder": "Carpeta", "txt_backup_remote_unknown_time": "Hora desconocida", @@ -247,6 +249,74 @@ const es: Record = { "txt_backup_remote_run_invalid_response": "Respuesta de ejecución de copia de seguridad remota no válida", "txt_backup_settings_invalid_response": "Respuesta de configuración de copia de seguridad no válida", "txt_backup_import_invalid_response": "Respuesta de importación de copia de seguridad no válida", + "txt_backup_error_another_backup_or_restore_running": "Ya hay una tarea de copia o restauración en curso.", + "txt_backup_error_another_backup_running": "Ya hay una tarea de copia en curso.", + "txt_backup_error_archive_upload_failed": "No se pudo subir el archivo de copia.", + "txt_backup_error_archive_upload_verification_failed_attempts": "La verificación de subida falló tras {count} intento(s): {reason}", + "txt_backup_error_attachment_blob_invalid": "El objeto de adjunto de copia no es válido.", + "txt_backup_error_attachment_blob_required": "Falta el objeto de adjunto de copia.", + "txt_backup_error_attachment_blob_not_found": "No se encontró el objeto de adjunto de copia.", + "txt_backup_error_attachment_download_failed": "No se pudo descargar el adjunto de copia.", + "txt_backup_error_destination_invalid": "El destino de copia no es válido.", + "txt_backup_error_destination_limit": "Puede guardar hasta {count} destinos de copia.", + "txt_backup_error_destination_not_found": "No se encontró el destino de copia.", + "txt_backup_error_destination_ids_unique": "Los ID de destino de copia no pueden repetirse.", + "txt_backup_error_destination_type_invalid": "El tipo de destino de copia no es válido.", + "txt_backup_error_destination_type_unsupported": "Tipo de destino de copia no compatible.", + "txt_backup_error_destinations_invalid": "La lista de destinos de copia no es válida.", + "txt_backup_error_export_payload_invalid": "La solicitud de exportación de copia no es válida.", + "txt_backup_error_file_checksum_mismatch": "La suma de verificación de la copia no coincide con el nombre del archivo.", + "txt_backup_error_file_required": "Seleccione un archivo de copia.", + "txt_backup_error_interval_hours_range": "El intervalo de copia debe estar entre 1 y 99 horas.", + "txt_backup_error_multipart_required": "La solicitud de subida debe usar multipart/form-data.", + "txt_backup_error_read_backup_file_failed": "No se pudo leer el archivo de copia.", + "txt_backup_error_remote_attachment_batch_download_failed_status": "Error al descargar adjuntos remotos por lotes: HTTP {status}.", + "txt_backup_error_remote_attachment_download_failed_status": "Error al descargar adjunto remoto: HTTP {status}.", + "txt_backup_error_remote_delete_failed": "No se pudo eliminar la copia remota.", + "txt_backup_error_remote_download_failed": "No se pudo descargar la copia remota.", + "txt_backup_error_remote_download_payload_invalid": "La solicitud de descarga remota no es válida.", + "txt_backup_error_remote_integrity_failed": "No se pudo inspeccionar la integridad de la copia remota.", + "txt_backup_error_remote_listing_failed": "No se pudo leer la lista de copias remotas.", + "txt_backup_error_remote_path_invalid": "La ruta de copia remota no es válida.", + "txt_backup_error_remote_restore_payload_invalid": "La solicitud de restauración remota no es válida.", + "txt_backup_error_remote_zip_checksum_failed": "Falló la verificación de suma del ZIP remoto.", + "txt_backup_error_remote_zip_size_failed": "Falló la verificación de tamaño del ZIP remoto.", + "txt_backup_error_retention_count_range": "La retención debe estar entre 1 y 1000.", + "txt_backup_error_run_failed": "La ejecución de copia falló.", + "txt_backup_error_run_payload_invalid": "La solicitud de ejecución de copia no es válida.", + "txt_backup_error_run_response_invalid": "La respuesta de ejecución de copia no es válida.", + "txt_backup_error_s3_access_key_required": "La clave de acceso S3 es obligatoria.", + "txt_backup_error_s3_bucket_required": "El bucket S3 es obligatorio.", + "txt_backup_error_s3_delete_failed_status": "Eliminación S3 fallida: HTTP {status}.", + "txt_backup_error_s3_download_failed_status": "Descarga S3 fallida: HTTP {status}.", + "txt_backup_error_s3_endpoint_required": "El endpoint S3 es obligatorio.", + "txt_backup_error_s3_endpoint_protocol": "El endpoint S3 debe empezar por http:// o https://.", + "txt_backup_error_s3_existence_check_failed_status": "Comprobación de existencia S3 fallida: HTTP {status}.", + "txt_backup_error_s3_listing_failed_status": "Listado S3 fallido: HTTP {status}.", + "txt_backup_error_s3_secret_key_required": "La clave secreta S3 es obligatoria.", + "txt_backup_error_s3_upload_failed_status": "Subida S3 fallida: HTTP {status}.", + "txt_backup_error_select_backup_file": "Seleccione un archivo de copia.", + "txt_backup_error_select_backup_zip_file": "Seleccione un archivo ZIP de copia.", + "txt_backup_error_settings_envelope_invalid": "El contenedor cifrado de configuración de copia no es válido.", + "txt_backup_error_settings_invalid": "La configuración de copia no es válida.", + "txt_backup_error_settings_load_failed": "No se pudo cargar la configuración de copia.", + "txt_backup_error_settings_need_reactivation": "La configuración de copia requiere reactivación de administrador tras la restauración.", + "txt_backup_error_settings_payload_invalid": "La solicitud de configuración de copia no es válida.", + "txt_backup_error_settings_repair_payload_invalid": "La solicitud de reparación de configuración no es válida.", + "txt_backup_error_settings_repair_state_load_failed": "No se pudo cargar el estado de reparación de configuración.", + "txt_backup_error_start_time_format": "La hora de inicio debe tener formato HH:mm.", + "txt_backup_error_timezone_invalid": "La zona horaria de copia no es válida.", + "txt_backup_error_webdav_delete_failed_status": "Eliminación WebDAV fallida: HTTP {status}.", + "txt_backup_error_webdav_directory_creation_failed_status": "Creación de directorio WebDAV fallida: HTTP {status}.", + "txt_backup_error_webdav_download_failed_status": "Descarga WebDAV fallida: HTTP {status}.", + "txt_backup_error_webdav_existence_check_failed_status": "Comprobación de existencia WebDAV fallida: HTTP {status}.", + "txt_backup_error_webdav_listing_failed_status": "Listado WebDAV fallido: HTTP {status}.", + "txt_backup_error_webdav_password_required": "La contraseña WebDAV es obligatoria.", + "txt_backup_error_webdav_path_too_deep": "La ruta remota WebDAV es demasiado profunda para procesar adjuntos por lotes de forma segura.", + "txt_backup_error_webdav_upload_failed_status": "Subida WebDAV fallida: HTTP {status}.", + "txt_backup_error_webdav_url_required": "La URL del servidor WebDAV es obligatoria.", + "txt_backup_error_webdav_url_protocol": "La URL WebDAV debe empezar por http:// o https://.", + "txt_backup_error_webdav_username_required": "El usuario WebDAV es obligatorio.", "txt_backup_destination": "Destino de copia", "txt_backup_protocol_webdav": "WebDAV", "txt_backup_protocol_s3": "S3", @@ -522,16 +592,21 @@ const es: Record = { "txt_server_error_account_disabled": "La cuenta está deshabilitada", "txt_server_error_client_credentials_incorrect": "El ID de cliente o el secreto de cliente no son correctos. Inténtalo de nuevo.", "txt_server_error_client_ip_required": "Se requiere la IP del cliente", + "txt_server_error_forbidden": "No tiene permiso para realizar esta acción.", "txt_server_error_email_already_registered": "Este correo ya está registrado", "txt_server_error_email_password_required": "Correo y contraseña son obligatorios", "txt_server_error_email_required": "El correo es obligatorio", + "txt_server_error_invalid_password": "Contraseña no válida.", "txt_server_error_invalid_refresh_token": "La sesión caducó. Inicia sesión de nuevo.", + "txt_server_error_invalid_user_verification_token": "Token de verificación de usuario no válido.", "txt_server_error_invalid_request_payload": "Solicitud no válida", "txt_server_error_invite_invalid_or_expired": "El código de invitación no es válido o ha caducado", "txt_server_error_invite_required": "El código de invitación es obligatorio", "txt_server_error_jwt_secret_default": "JWT_SECRET usa el valor predeterminado/de ejemplo. Cámbialo.", "txt_server_error_jwt_secret_missing": "JWT_SECRET no está configurado", "txt_server_error_jwt_secret_too_short": "JWT_SECRET debe tener al menos 32 caracteres", + "txt_server_error_master_password_hash_required": "Se requiere verificación de la contraseña maestra.", + "txt_server_error_master_password_or_verification_required": "Se requiere contraseña maestra o token de verificación de usuario.", "txt_server_error_parameter_error": "Error de parámetros", "txt_server_error_refresh_token_required": "Falta la sesión. Inicia sesión de nuevo.", "txt_server_error_registration_retry": "El registro no está disponible temporalmente. Inténtalo una vez más.", diff --git a/webapp/src/lib/i18n/locales/ru.ts b/webapp/src/lib/i18n/locales/ru.ts index dc0f4c2..fd4507c 100644 --- a/webapp/src/lib/i18n/locales/ru.ts +++ b/webapp/src/lib/i18n/locales/ru.ts @@ -224,6 +224,8 @@ const ru: Record = { "txt_backup_restore_progress_remote_finalize_detail": "Сервер выполняет окончательную проверку, а затем переключает проверенные данные восстановления в живые таблицы.", "txt_backup_remote_loading": "Загрузка удаленных резервных копий...", "txt_backup_remote_cached_empty": "Нажмите «Обновить», чтобы загрузить это место назначения.", + "txt_backup_remote_cached_empty_prefix": "Нажмите", + "txt_backup_remote_cached_empty_suffix": "чтобы загрузить это место назначения.", "txt_backup_remote_empty": "В этой папке не найдено файлов резервных копий.", "txt_backup_remote_folder": "Папка", "txt_backup_remote_unknown_time": "Неизвестное время", @@ -247,6 +249,74 @@ const ru: Record = { "txt_backup_remote_run_invalid_response": "Неверный ответ на удаленное резервное копирование.", "txt_backup_settings_invalid_response": "Неверный ответ на настройки резервного копирования", "txt_backup_import_invalid_response": "Неверный ответ на импорт резервной копии", + "txt_backup_error_another_backup_or_restore_running": "Уже выполняется задача резервного копирования или восстановления.", + "txt_backup_error_another_backup_running": "Уже выполняется задача резервного копирования.", + "txt_backup_error_archive_upload_failed": "Не удалось загрузить архив резервной копии.", + "txt_backup_error_archive_upload_verification_failed_attempts": "Проверка загрузки не прошла после {count} попыток: {reason}", + "txt_backup_error_attachment_blob_invalid": "Объект вложения резервной копии недействителен.", + "txt_backup_error_attachment_blob_required": "Требуется объект вложения резервной копии.", + "txt_backup_error_attachment_blob_not_found": "Объект вложения резервной копии не найден.", + "txt_backup_error_attachment_download_failed": "Не удалось скачать вложение резервной копии.", + "txt_backup_error_destination_invalid": "Место назначения резервной копии недействительно.", + "txt_backup_error_destination_limit": "Можно сохранить не более {count} мест назначения резервной копии.", + "txt_backup_error_destination_not_found": "Место назначения резервной копии не найдено.", + "txt_backup_error_destination_ids_unique": "ID мест назначения резервной копии должны быть уникальными.", + "txt_backup_error_destination_type_invalid": "Тип места назначения резервной копии недействителен.", + "txt_backup_error_destination_type_unsupported": "Неподдерживаемый тип места назначения резервной копии.", + "txt_backup_error_destinations_invalid": "Список мест назначения резервной копии недействителен.", + "txt_backup_error_export_payload_invalid": "Запрос экспорта резервной копии недействителен.", + "txt_backup_error_file_checksum_mismatch": "Контрольная сумма файла резервной копии не совпадает с именем файла.", + "txt_backup_error_file_required": "Выберите файл резервной копии.", + "txt_backup_error_interval_hours_range": "Интервал резервного копирования должен быть от 1 до 99 часов.", + "txt_backup_error_multipart_required": "Запрос загрузки должен использовать multipart/form-data.", + "txt_backup_error_read_backup_file_failed": "Не удалось прочитать файл резервной копии.", + "txt_backup_error_remote_attachment_batch_download_failed_status": "Пакетное скачивание удаленных вложений не удалось: HTTP {status}.", + "txt_backup_error_remote_attachment_download_failed_status": "Скачивание удаленного вложения не удалось: HTTP {status}.", + "txt_backup_error_remote_delete_failed": "Не удалось удалить удаленную резервную копию.", + "txt_backup_error_remote_download_failed": "Не удалось скачать удаленную резервную копию.", + "txt_backup_error_remote_download_payload_invalid": "Запрос скачивания удаленной резервной копии недействителен.", + "txt_backup_error_remote_integrity_failed": "Не удалось проверить целостность удаленной резервной копии.", + "txt_backup_error_remote_listing_failed": "Не удалось получить список удаленных резервных копий.", + "txt_backup_error_remote_path_invalid": "Путь удаленной резервной копии недействителен.", + "txt_backup_error_remote_restore_payload_invalid": "Запрос удаленного восстановления недействителен.", + "txt_backup_error_remote_zip_checksum_failed": "Проверка контрольной суммы удаленного ZIP не прошла.", + "txt_backup_error_remote_zip_size_failed": "Проверка размера удаленного ZIP не прошла.", + "txt_backup_error_retention_count_range": "Количество сохраняемых копий должно быть от 1 до 1000.", + "txt_backup_error_run_failed": "Запуск резервного копирования не удался.", + "txt_backup_error_run_payload_invalid": "Запрос запуска резервного копирования недействителен.", + "txt_backup_error_run_response_invalid": "Ответ запуска резервного копирования недействителен.", + "txt_backup_error_s3_access_key_required": "Требуется ключ доступа S3.", + "txt_backup_error_s3_bucket_required": "Требуется bucket S3.", + "txt_backup_error_s3_delete_failed_status": "Удаление S3 не удалось: HTTP {status}.", + "txt_backup_error_s3_download_failed_status": "Скачивание S3 не удалось: HTTP {status}.", + "txt_backup_error_s3_endpoint_required": "Требуется endpoint S3.", + "txt_backup_error_s3_endpoint_protocol": "Endpoint S3 должен начинаться с http:// или https://.", + "txt_backup_error_s3_existence_check_failed_status": "Проверка существования S3 не удалась: HTTP {status}.", + "txt_backup_error_s3_listing_failed_status": "Получение списка S3 не удалось: HTTP {status}.", + "txt_backup_error_s3_secret_key_required": "Требуется секретный ключ S3.", + "txt_backup_error_s3_upload_failed_status": "Загрузка S3 не удалась: HTTP {status}.", + "txt_backup_error_select_backup_file": "Выберите файл резервной копии.", + "txt_backup_error_select_backup_zip_file": "Выберите ZIP-файл резервной копии.", + "txt_backup_error_settings_envelope_invalid": "Зашифрованный контейнер настроек резервного копирования недействителен.", + "txt_backup_error_settings_invalid": "Настройки резервного копирования недействительны.", + "txt_backup_error_settings_load_failed": "Не удалось загрузить настройки резервного копирования.", + "txt_backup_error_settings_need_reactivation": "После восстановления настройки резервного копирования нужно повторно активировать администратором.", + "txt_backup_error_settings_payload_invalid": "Запрос настроек резервного копирования недействителен.", + "txt_backup_error_settings_repair_payload_invalid": "Запрос восстановления настроек резервного копирования недействителен.", + "txt_backup_error_settings_repair_state_load_failed": "Не удалось загрузить состояние восстановления настроек резервного копирования.", + "txt_backup_error_start_time_format": "Время начала резервного копирования должно быть в формате HH:mm.", + "txt_backup_error_timezone_invalid": "Часовой пояс резервного копирования недействителен.", + "txt_backup_error_webdav_delete_failed_status": "Удаление WebDAV не удалось: HTTP {status}.", + "txt_backup_error_webdav_directory_creation_failed_status": "Создание каталога WebDAV не удалось: HTTP {status}.", + "txt_backup_error_webdav_download_failed_status": "Скачивание WebDAV не удалось: HTTP {status}.", + "txt_backup_error_webdav_existence_check_failed_status": "Проверка существования WebDAV не удалась: HTTP {status}.", + "txt_backup_error_webdav_listing_failed_status": "Получение списка WebDAV не удалось: HTTP {status}.", + "txt_backup_error_webdav_password_required": "Требуется пароль WebDAV.", + "txt_backup_error_webdav_path_too_deep": "Удаленный путь WebDAV слишком глубокий для безопасной пакетной обработки вложений.", + "txt_backup_error_webdav_upload_failed_status": "Загрузка WebDAV не удалась: HTTP {status}.", + "txt_backup_error_webdav_url_required": "Требуется URL сервера WebDAV.", + "txt_backup_error_webdav_url_protocol": "URL WebDAV должен начинаться с http:// или https://.", + "txt_backup_error_webdav_username_required": "Требуется имя пользователя WebDAV.", "txt_backup_destination": "Место назначения резервного копирования", "txt_backup_protocol_webdav": "WebDAV", "txt_backup_protocol_s3": "S3", @@ -522,16 +592,21 @@ const ru: Record = { "txt_server_error_account_disabled": "Учетная запись отключена", "txt_server_error_client_credentials_incorrect": "ID клиента или секрет клиента неверны. Повторите попытку.", "txt_server_error_client_ip_required": "Требуется IP клиента", + "txt_server_error_forbidden": "У вас нет прав для выполнения этого действия.", "txt_server_error_email_already_registered": "Этот адрес электронной почты уже зарегистрирован", "txt_server_error_email_password_required": "Требуются адрес электронной почты и пароль", "txt_server_error_email_required": "Требуется адрес электронной почты", + "txt_server_error_invalid_password": "Неверный пароль.", "txt_server_error_invalid_refresh_token": "Сеанс истек. Войдите снова.", + "txt_server_error_invalid_user_verification_token": "Недействительный токен проверки пользователя.", "txt_server_error_invalid_request_payload": "Недопустимый запрос", "txt_server_error_invite_invalid_or_expired": "Код приглашения недействителен или истек", "txt_server_error_invite_required": "Требуется код приглашения", "txt_server_error_jwt_secret_default": "JWT_SECRET использует значение по умолчанию/пример. Измените его.", "txt_server_error_jwt_secret_missing": "JWT_SECRET не настроен", "txt_server_error_jwt_secret_too_short": "JWT_SECRET должен содержать не менее 32 символов", + "txt_server_error_master_password_hash_required": "Требуется проверка мастер-пароля.", + "txt_server_error_master_password_or_verification_required": "Требуется мастер-пароль или токен проверки пользователя.", "txt_server_error_parameter_error": "Ошибка параметров", "txt_server_error_refresh_token_required": "Сеанс отсутствует. Войдите снова.", "txt_server_error_registration_retry": "Регистрация временно недоступна. Повторите попытку один раз.", diff --git a/webapp/src/lib/i18n/locales/zh-CN.ts b/webapp/src/lib/i18n/locales/zh-CN.ts index 05c23b3..4d4b7ec 100644 --- a/webapp/src/lib/i18n/locales/zh-CN.ts +++ b/webapp/src/lib/i18n/locales/zh-CN.ts @@ -224,6 +224,8 @@ const zhCN: Record = { "txt_backup_restore_progress_remote_finalize_detail": "服务器正在执行最终校验,校验通过后会把已验证的数据切换为正式数据。", "txt_backup_remote_loading": "正在读取远端备份...", "txt_backup_remote_cached_empty": "点击“刷新”后读取", + "txt_backup_remote_cached_empty_prefix": "点击", + "txt_backup_remote_cached_empty_suffix": "后读取", "txt_backup_remote_empty": "这个目录下还没有备份文件", "txt_backup_remote_folder": "文件夹", "txt_backup_remote_unknown_time": "未知时间", @@ -247,6 +249,74 @@ const zhCN: Record = { "txt_backup_remote_run_invalid_response": "远端备份执行响应无效", "txt_backup_settings_invalid_response": "备份设置响应无效", "txt_backup_import_invalid_response": "备份还原响应无效", + "txt_backup_error_another_backup_or_restore_running": "已有备份或还原任务正在执行。", + "txt_backup_error_another_backup_running": "已有备份任务正在执行。", + "txt_backup_error_archive_upload_failed": "备份压缩包上传失败。", + "txt_backup_error_archive_upload_verification_failed_attempts": "备份上传校验在 {count} 次尝试后仍失败:{reason}", + "txt_backup_error_attachment_blob_invalid": "备份附件对象无效。", + "txt_backup_error_attachment_blob_required": "缺少备份附件对象。", + "txt_backup_error_attachment_blob_not_found": "未找到备份附件对象。", + "txt_backup_error_attachment_download_failed": "备份附件下载失败。", + "txt_backup_error_destination_invalid": "备份地点无效。", + "txt_backup_error_destination_limit": "最多只能保存 {count} 个备份地点。", + "txt_backup_error_destination_not_found": "未找到备份地点。", + "txt_backup_error_destination_ids_unique": "备份地点 ID 不能重复。", + "txt_backup_error_destination_type_invalid": "备份地点类型无效。", + "txt_backup_error_destination_type_unsupported": "不支持的备份地点类型。", + "txt_backup_error_destinations_invalid": "备份地点列表无效。", + "txt_backup_error_export_payload_invalid": "备份导出请求无效。", + "txt_backup_error_file_checksum_mismatch": "备份文件校验值与文件名不一致。", + "txt_backup_error_file_required": "请选择备份文件。", + "txt_backup_error_interval_hours_range": "备份间隔必须在 1 到 99 小时之间。", + "txt_backup_error_multipart_required": "上传请求必须使用 multipart/form-data。", + "txt_backup_error_read_backup_file_failed": "无法读取备份文件。", + "txt_backup_error_remote_attachment_batch_download_failed_status": "远端附件批量下载失败:HTTP {status}。", + "txt_backup_error_remote_attachment_download_failed_status": "远端附件下载失败:HTTP {status}。", + "txt_backup_error_remote_delete_failed": "远端备份删除失败。", + "txt_backup_error_remote_download_failed": "远端备份下载失败。", + "txt_backup_error_remote_download_payload_invalid": "远端备份下载请求无效。", + "txt_backup_error_remote_integrity_failed": "远端备份完整性检查失败。", + "txt_backup_error_remote_listing_failed": "远端备份列表读取失败。", + "txt_backup_error_remote_path_invalid": "远端备份路径无效。", + "txt_backup_error_remote_restore_payload_invalid": "远端还原请求无效。", + "txt_backup_error_remote_zip_checksum_failed": "远端备份 ZIP 校验失败。", + "txt_backup_error_remote_zip_size_failed": "远端备份 ZIP 大小校验失败。", + "txt_backup_error_retention_count_range": "备份保留数量必须在 1 到 1000 之间。", + "txt_backup_error_run_failed": "备份执行失败。", + "txt_backup_error_run_payload_invalid": "备份执行请求无效。", + "txt_backup_error_run_response_invalid": "备份执行响应无效。", + "txt_backup_error_s3_access_key_required": "请填写 S3 访问 ID。", + "txt_backup_error_s3_bucket_required": "请填写 S3 存储桶名称。", + "txt_backup_error_s3_delete_failed_status": "S3 删除失败:HTTP {status}。", + "txt_backup_error_s3_download_failed_status": "S3 下载失败:HTTP {status}。", + "txt_backup_error_s3_endpoint_required": "请填写 S3 端点 URL。", + "txt_backup_error_s3_endpoint_protocol": "S3 端点 URL 必须以 http:// 或 https:// 开头。", + "txt_backup_error_s3_existence_check_failed_status": "S3 文件存在性检查失败:HTTP {status}。", + "txt_backup_error_s3_listing_failed_status": "S3 列表读取失败:HTTP {status}。", + "txt_backup_error_s3_secret_key_required": "请填写 S3 访问密码。", + "txt_backup_error_s3_upload_failed_status": "S3 上传失败:HTTP {status}。", + "txt_backup_error_select_backup_file": "请选择备份文件。", + "txt_backup_error_select_backup_zip_file": "请选择备份 ZIP 文件。", + "txt_backup_error_settings_envelope_invalid": "备份设置加密封装无效。", + "txt_backup_error_settings_invalid": "备份设置无效。", + "txt_backup_error_settings_load_failed": "无法加载备份设置。", + "txt_backup_error_settings_need_reactivation": "还原后需要管理员重新激活备份设置。", + "txt_backup_error_settings_payload_invalid": "备份设置请求无效。", + "txt_backup_error_settings_repair_payload_invalid": "备份设置修复请求无效。", + "txt_backup_error_settings_repair_state_load_failed": "无法加载备份设置修复状态。", + "txt_backup_error_start_time_format": "备份开始时间必须是 HH:mm 格式。", + "txt_backup_error_timezone_invalid": "备份时区无效。", + "txt_backup_error_webdav_delete_failed_status": "WebDAV 删除失败:HTTP {status}。", + "txt_backup_error_webdav_directory_creation_failed_status": "WebDAV 目录创建失败:HTTP {status}。", + "txt_backup_error_webdav_download_failed_status": "WebDAV 下载失败:HTTP {status}。", + "txt_backup_error_webdav_existence_check_failed_status": "WebDAV 文件存在性检查失败:HTTP {status}。", + "txt_backup_error_webdav_listing_failed_status": "WebDAV 列表读取失败:HTTP {status}。", + "txt_backup_error_webdav_password_required": "请填写 WebDAV 密码。", + "txt_backup_error_webdav_path_too_deep": "WebDAV 远端备份路径过深,无法安全分批处理附件。", + "txt_backup_error_webdav_upload_failed_status": "WebDAV 上传失败:HTTP {status}。", + "txt_backup_error_webdav_url_required": "请填写 WebDAV 服务地址。", + "txt_backup_error_webdav_url_protocol": "WebDAV 服务地址必须以 http:// 或 https:// 开头。", + "txt_backup_error_webdav_username_required": "请填写 WebDAV 用户名。", "txt_backup_destination": "备份地点", "txt_backup_protocol_webdav": "WebDAV", "txt_backup_protocol_s3": "S3", @@ -522,16 +592,21 @@ const zhCN: Record = { "txt_server_error_account_disabled": "账号已被禁用", "txt_server_error_client_credentials_incorrect": "客户端 ID 或客户端密钥不正确,请重试", "txt_server_error_client_ip_required": "无法获取客户端 IP", + "txt_server_error_forbidden": "你没有权限执行此操作。", "txt_server_error_email_already_registered": "该邮箱已注册", "txt_server_error_email_password_required": "邮箱和密码不能为空", "txt_server_error_email_required": "邮箱不能为空", + "txt_server_error_invalid_password": "密码无效。", "txt_server_error_invalid_refresh_token": "登录状态已失效,请重新登录", + "txt_server_error_invalid_user_verification_token": "用户验证令牌无效。", "txt_server_error_invalid_request_payload": "请求内容无效", "txt_server_error_invite_invalid_or_expired": "邀请码无效或已过期", "txt_server_error_invite_required": "邀请码不能为空", "txt_server_error_jwt_secret_default": "JWT_SECRET 正在使用默认示例值,请修改后再继续", "txt_server_error_jwt_secret_missing": "JWT_SECRET 未设置", "txt_server_error_jwt_secret_too_short": "JWT_SECRET 至少需要 32 个字符", + "txt_server_error_master_password_hash_required": "需要验证主密码。", + "txt_server_error_master_password_or_verification_required": "需要主密码或用户验证令牌。", "txt_server_error_parameter_error": "请求参数错误", "txt_server_error_refresh_token_required": "登录状态缺失,请重新登录", "txt_server_error_registration_retry": "注册暂时不可用,请重试一次", diff --git a/webapp/src/lib/i18n/locales/zh-TW.ts b/webapp/src/lib/i18n/locales/zh-TW.ts index c561a2b..63ba0fd 100644 --- a/webapp/src/lib/i18n/locales/zh-TW.ts +++ b/webapp/src/lib/i18n/locales/zh-TW.ts @@ -224,6 +224,8 @@ const zhTW: Record = { "txt_backup_restore_progress_remote_finalize_detail": "服務器正在執行最終校驗,校驗通過後會把已驗證的數據切換為正式數據。", "txt_backup_remote_loading": "正在讀取遠端備份...", "txt_backup_remote_cached_empty": "點擊“刷新”後讀取", + "txt_backup_remote_cached_empty_prefix": "點擊", + "txt_backup_remote_cached_empty_suffix": "後讀取", "txt_backup_remote_empty": "這個目錄下還沒有備份文件", "txt_backup_remote_folder": "文件夾", "txt_backup_remote_unknown_time": "未知時間", @@ -247,6 +249,74 @@ const zhTW: Record = { "txt_backup_remote_run_invalid_response": "遠端備份執行響應無效", "txt_backup_settings_invalid_response": "備份設置響應無效", "txt_backup_import_invalid_response": "備份還原響應無效", + "txt_backup_error_another_backup_or_restore_running": "已有備份或還原任務正在執行。", + "txt_backup_error_another_backup_running": "已有備份任務正在執行。", + "txt_backup_error_archive_upload_failed": "備份壓縮包上傳失敗。", + "txt_backup_error_archive_upload_verification_failed_attempts": "備份上傳校驗在 {count} 次嘗試後仍失敗:{reason}", + "txt_backup_error_attachment_blob_invalid": "備份附件對象無效。", + "txt_backup_error_attachment_blob_required": "缺少備份附件對象。", + "txt_backup_error_attachment_blob_not_found": "未找到備份附件對象。", + "txt_backup_error_attachment_download_failed": "備份附件下載失敗。", + "txt_backup_error_destination_invalid": "備份地點無效。", + "txt_backup_error_destination_limit": "最多只能保存 {count} 個備份地點。", + "txt_backup_error_destination_not_found": "未找到備份地點。", + "txt_backup_error_destination_ids_unique": "備份地點 ID 不能重複。", + "txt_backup_error_destination_type_invalid": "備份地點類型無效。", + "txt_backup_error_destination_type_unsupported": "不支持的備份地點類型。", + "txt_backup_error_destinations_invalid": "備份地點列表無效。", + "txt_backup_error_export_payload_invalid": "備份導出請求無效。", + "txt_backup_error_file_checksum_mismatch": "備份文件校驗值與文件名不一致。", + "txt_backup_error_file_required": "請選擇備份文件。", + "txt_backup_error_interval_hours_range": "備份間隔必須在 1 到 99 小時之間。", + "txt_backup_error_multipart_required": "上傳請求必須使用 multipart/form-data。", + "txt_backup_error_read_backup_file_failed": "無法讀取備份文件。", + "txt_backup_error_remote_attachment_batch_download_failed_status": "遠端附件批量下載失敗:HTTP {status}。", + "txt_backup_error_remote_attachment_download_failed_status": "遠端附件下載失敗:HTTP {status}。", + "txt_backup_error_remote_delete_failed": "遠端備份刪除失敗。", + "txt_backup_error_remote_download_failed": "遠端備份下載失敗。", + "txt_backup_error_remote_download_payload_invalid": "遠端備份下載請求無效。", + "txt_backup_error_remote_integrity_failed": "遠端備份完整性檢查失敗。", + "txt_backup_error_remote_listing_failed": "遠端備份列表讀取失敗。", + "txt_backup_error_remote_path_invalid": "遠端備份路徑無效。", + "txt_backup_error_remote_restore_payload_invalid": "遠端還原請求無效。", + "txt_backup_error_remote_zip_checksum_failed": "遠端備份 ZIP 校驗失敗。", + "txt_backup_error_remote_zip_size_failed": "遠端備份 ZIP 大小校驗失敗。", + "txt_backup_error_retention_count_range": "備份保留數量必須在 1 到 1000 之間。", + "txt_backup_error_run_failed": "備份執行失敗。", + "txt_backup_error_run_payload_invalid": "備份執行請求無效。", + "txt_backup_error_run_response_invalid": "備份執行響應無效。", + "txt_backup_error_s3_access_key_required": "請填寫 S3 存取 ID。", + "txt_backup_error_s3_bucket_required": "請填寫 S3 儲存桶名稱。", + "txt_backup_error_s3_delete_failed_status": "S3 刪除失敗:HTTP {status}。", + "txt_backup_error_s3_download_failed_status": "S3 下載失敗:HTTP {status}。", + "txt_backup_error_s3_endpoint_required": "請填寫 S3 端點 URL。", + "txt_backup_error_s3_endpoint_protocol": "S3 端點 URL 必須以 http:// 或 https:// 開頭。", + "txt_backup_error_s3_existence_check_failed_status": "S3 文件存在性檢查失敗:HTTP {status}。", + "txt_backup_error_s3_listing_failed_status": "S3 列表讀取失敗:HTTP {status}。", + "txt_backup_error_s3_secret_key_required": "請填寫 S3 存取密碼。", + "txt_backup_error_s3_upload_failed_status": "S3 上傳失敗:HTTP {status}。", + "txt_backup_error_select_backup_file": "請選擇備份文件。", + "txt_backup_error_select_backup_zip_file": "請選擇備份 ZIP 文件。", + "txt_backup_error_settings_envelope_invalid": "備份設置加密封裝無效。", + "txt_backup_error_settings_invalid": "備份設置無效。", + "txt_backup_error_settings_load_failed": "無法加載備份設置。", + "txt_backup_error_settings_need_reactivation": "還原後需要管理員重新激活備份設置。", + "txt_backup_error_settings_payload_invalid": "備份設置請求無效。", + "txt_backup_error_settings_repair_payload_invalid": "備份設置修復請求無效。", + "txt_backup_error_settings_repair_state_load_failed": "無法加載備份設置修復狀態。", + "txt_backup_error_start_time_format": "備份開始時間必須是 HH:mm 格式。", + "txt_backup_error_timezone_invalid": "備份時區無效。", + "txt_backup_error_webdav_delete_failed_status": "WebDAV 刪除失敗:HTTP {status}。", + "txt_backup_error_webdav_directory_creation_failed_status": "WebDAV 目錄創建失敗:HTTP {status}。", + "txt_backup_error_webdav_download_failed_status": "WebDAV 下載失敗:HTTP {status}。", + "txt_backup_error_webdav_existence_check_failed_status": "WebDAV 文件存在性檢查失敗:HTTP {status}。", + "txt_backup_error_webdav_listing_failed_status": "WebDAV 列表讀取失敗:HTTP {status}。", + "txt_backup_error_webdav_password_required": "請填寫 WebDAV 密碼。", + "txt_backup_error_webdav_path_too_deep": "WebDAV 遠端備份路徑過深,無法安全分批處理附件。", + "txt_backup_error_webdav_upload_failed_status": "WebDAV 上傳失敗:HTTP {status}。", + "txt_backup_error_webdav_url_required": "請填寫 WebDAV 服務地址。", + "txt_backup_error_webdav_url_protocol": "WebDAV 服務地址必須以 http:// 或 https:// 開頭。", + "txt_backup_error_webdav_username_required": "請填寫 WebDAV 用戶名。", "txt_backup_destination": "備份地點", "txt_backup_protocol_webdav": "WebDAV", "txt_backup_protocol_s3": "S3", @@ -522,16 +592,21 @@ const zhTW: Record = { "txt_server_error_account_disabled": "帳號已被禁用", "txt_server_error_client_credentials_incorrect": "客戶端 ID 或客戶端密鑰不正確,請重試", "txt_server_error_client_ip_required": "無法獲取客戶端 IP", + "txt_server_error_forbidden": "你沒有權限執行此操作。", "txt_server_error_email_already_registered": "該郵箱已註冊", "txt_server_error_email_password_required": "郵箱和密碼不能為空", "txt_server_error_email_required": "郵箱不能為空", + "txt_server_error_invalid_password": "密碼無效。", "txt_server_error_invalid_refresh_token": "登入狀態已失效,請重新登入", + "txt_server_error_invalid_user_verification_token": "用戶驗證令牌無效。", "txt_server_error_invalid_request_payload": "請求內容無效", "txt_server_error_invite_invalid_or_expired": "邀請碼無效或已過期", "txt_server_error_invite_required": "邀請碼不能為空", "txt_server_error_jwt_secret_default": "JWT_SECRET 正在使用默認示例值,請修改後再繼續", "txt_server_error_jwt_secret_missing": "JWT_SECRET 未設置", "txt_server_error_jwt_secret_too_short": "JWT_SECRET 至少需要 32 個字符", + "txt_server_error_master_password_hash_required": "需要驗證主密碼。", + "txt_server_error_master_password_or_verification_required": "需要主密碼或用戶驗證令牌。", "txt_server_error_parameter_error": "請求參數錯誤", "txt_server_error_refresh_token_required": "登入狀態缺失,請重新登入", "txt_server_error_registration_retry": "註冊暫時不可用,請重試一次", diff --git a/webapp/src/styles/management.css b/webapp/src/styles/management.css index db175e2..1c6cbac 100644 --- a/webapp/src/styles/management.css +++ b/webapp/src/styles/management.css @@ -443,6 +443,10 @@ color: #64748b; } +.backup-browser-refresh-prompt { + @apply inline-flex flex-wrap items-center justify-center gap-2; +} + .backup-inline-note { @apply m-0 mb-3 leading-[1.5]; color: #64748b;