Compare commits

...

9 Commits

Author SHA1 Message Date
Gitea Actions Bot 8b0c1655a1 chore: bump frontend version to 1.0.88
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing
2025-07-23 10:10:42 +00:00
paul ff950244d5 fix: complete restore page translations and fix structure
Mirror to GitHub / mirror (push) Successful in 39s
Test and Lint / backend-test (push) Successful in 1m23s
Test and Lint / frontend-test (push) Successful in 2m0s
Version and Release / version-bump (push) Successful in 45s
Version and Release / trigger-drone (push) Successful in 3s
continuous-integration/drone/push Build is passing
- Fix restoreTypes translation structure (was under options.types)
- Add missing restore.messages.restoreStarted translation
- Ensure all restore wizard strings use translations
- Add corresponding German translations for restore section
- Fix translation key structure to match component expectations

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-23 12:05:48 +02:00
Gitea Actions Bot cd3d6fc704 chore: bump frontend version to 1.0.87
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
2025-07-23 10:03:33 +00:00
paul c536fe45ff fix: complete backup page translations and improve UI
Mirror to GitHub / mirror (push) Successful in 36s
Test and Lint / backend-test (push) Successful in 1m32s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 1m56s
Version and Release / version-bump (push) Successful in 40s
Version and Release / trigger-drone (push) Successful in 3s
- Fix '0 files' hardcoded string to use translation
- Fix 'local' destination type to show translated name
- Add missing field placeholders for rsync and S3 configurations
- Add missing backup.history.columns.* translations
- Add missing backup.history.filter.* translations
- Add missing backup.history.details.* translations
- Fix backup destination display to use proper translation key
- Replace TestTube icon with Wifi icon for connection testing
- Add all corresponding German translations
- Ensure Backup Health and Coverage titles use translations

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-23 11:58:31 +02:00
paul 42c8ef1c0e docs: add minimum system requirements section to README
Mirror to GitHub / mirror (push) Successful in 47s
Test and Lint / backend-test (push) Successful in 1m35s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 1m58s
- Add CPU, RAM, and storage requirements
- Include OS and software dependencies
- Add Docker requirements for containerized deployment
- Keep it concise and focused on minimum requirements only

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-23 11:18:27 +02:00
paul d07d742528 fix: use plugins/github-release for Drone CI/CD
Mirror to GitHub / mirror (push) Successful in 50s
Test and Lint / backend-test (push) Successful in 1m46s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m12s
- Replace manual curl approach with plugins/github-release
- Fixes shell parsing issues with multiline strings
- Properly passes GITHUB_TOKEN via api_key setting
- Uses YAML multiline string (|) for release notes
- Cleaner and more reliable approach

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-23 10:56:46 +02:00
Gitea Actions Bot dbc9f0a605 chore: bump frontend version to 1.0.86
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-07-23 08:44:17 +00:00
paul 3eb8550cbf fix: add missing translations and fix BackupHistory useTranslation error
Mirror to GitHub / mirror (push) Successful in 43s
Test and Lint / backend-test (push) Successful in 1m40s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 1m59s
Version and Release / version-bump (push) Successful in 1m31s
Version and Release / trigger-drone (push) Successful in 3s
- Add missing useTranslation hook in BackupHistory.jsx
- Add missing translation keys:
  - backup.dashboard.health.title
  - backup.dashboard.coverage.title
  - backup.dashboard.stats.noBackupsYet
  - backup.configuration.enableBackupHelp
  - backup.configuration.schedule.options.*
  - backup.configuration.messages.*
  - backup.dashboard.noDestinationSet
  - Fix health message keys to match component usage
- Update German translations with same missing keys
- Fix runtime error preventing access to backup history page

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-23 10:37:39 +02:00
paul bebc045029 fix: simplify Drone github-release step to avoid shell parsing issues
Mirror to GitHub / mirror (push) Successful in 47s
Test and Lint / backend-test (push) Successful in 2m27s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m20s
- Use echo with single JSON string instead of heredoc
- Use > for folded scalar to avoid newline issues
- Properly escape quotes in JSON body
- Ensure GITHUB_TOKEN is properly passed

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-23 10:31:45 +02:00
10 changed files with 206 additions and 63 deletions
+40 -27
View File
@@ -110,36 +110,49 @@ steps:
# -------- NEW: Create GitHub Release -------- # -------- NEW: Create GitHub Release --------
- name: github-release - name: github-release
image: curlimages/curl:latest image: plugins/github-release
when: when:
event: tag event: tag
environment: settings:
GITHUB_TOKEN: api_key:
from_secret: GITHUB_TOKEN from_secret: GITHUB_TOKEN
commands: files: []
- | title: PicPeak ${DRONE_TAG}
# Create release payload in /tmp to avoid permission issues note: |
cat > /tmp/release.json <<'RELEASE_EOF' # PicPeak ${DRONE_TAG}
{
"tag_name": "DRONE_TAG_PLACEHOLDER", ## 🐳 Docker Images
"target_commitish": "main",
"name": "PicPeak DRONE_TAG_PLACEHOLDER", This release includes Docker images published to GitHub Container Registry:
"body": "# PicPeak DRONE_TAG_PLACEHOLDER\n\n## 🐳 Docker Images\n\nThis release includes Docker images published to GitHub Container Registry:\n\n```bash\n# Backend\ndocker pull ghcr.io/the-luap/picpeak-backend:DRONE_TAG_PLACEHOLDER\ndocker pull ghcr.io/the-luap/picpeak-backend:latest\n\n# Frontend\ndocker pull ghcr.io/the-luap/picpeak-frontend:DRONE_TAG_PLACEHOLDER\ndocker pull ghcr.io/the-luap/picpeak-frontend:latest\n```\n\n## 📦 What's New\n\nSee the [README](https://github.com/the-luap/picpeak#readme) for features and documentation.\n\n## 🚀 Quick Start\n\n```bash\n# Clone and deploy\ngit clone https://github.com/the-luap/picpeak.git\ncd picpeak\n\n# Use the tagged version\ndocker-compose -f docker-compose.prod.yml up -d\n```\n\n---\n\nFor detailed deployment instructions, see the [Deployment Guide](https://github.com/the-luap/picpeak/blob/main/DEPLOYMENT.md).",
"draft": false, ```bash
"prerelease": false # Backend
} docker pull ghcr.io/the-luap/picpeak-backend:${DRONE_TAG}
RELEASE_EOF docker pull ghcr.io/the-luap/picpeak-backend:latest
# Replace placeholders with actual tag # Frontend
sed -i "s/DRONE_TAG_PLACEHOLDER/${DRONE_TAG}/g" /tmp/release.json docker pull ghcr.io/the-luap/picpeak-frontend:${DRONE_TAG}
docker pull ghcr.io/the-luap/picpeak-frontend:latest
# Create the release on GitHub ```
curl -X POST \
-H "Accept: application/vnd.github+json" \ ## 📦 What's New
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "X-GitHub-Api-Version: 2022-11-28" \ See the [README](https://github.com/the-luap/picpeak#readme) for features and documentation.
https://api.github.com/repos/the-luap/picpeak/releases \
-d @/tmp/release.json ## 🚀 Quick Start
```bash
# Clone and deploy
git clone https://github.com/the-luap/picpeak.git
cd picpeak
# Use the tagged version
docker-compose -f docker-compose.prod.yml up -d
```
---
For detailed deployment instructions, see the [Deployment Guide](https://github.com/the-luap/picpeak/blob/main/DEPLOYMENT.md).
trigger: trigger:
event: event:
+14
View File
@@ -94,6 +94,20 @@ Perfect for:
- **Email**: SMTP with customizable templates - **Email**: SMTP with customizable templates
- **Analytics**: Privacy-focused with Umami integration - **Analytics**: Privacy-focused with Umami integration
## 💻 System Requirements
### Minimum Requirements
- **CPU**: 2 CPU cores
- **RAM**: 2GB minimum
- **Storage**: 20GB minimum (plus photo storage needs)
- **OS**: Linux (Ubuntu 20.04+), macOS, or Windows with WSL2
- **Node.js**: v18.0.0 or higher
- **Database**: SQLite (included) or PostgreSQL 12+
### Docker Requirements (Recommended)
- **Docker**: v20.10.0+
- **Docker Compose**: v2.0.0+
## 🤝 Contributing ## 🤝 Contributing
We love contributions! PicPeak is built by photographers, for photographers. Whether you're fixing bugs, adding features, or improving documentation, your help is welcome. We love contributions! PicPeak is built by photographers, for photographers. Whether you're fixing bugs, adding features, or improving documentation, your help is welcome.
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "picpeak-frontend", "name": "picpeak-frontend",
"version": "1.0.85", "version": "1.0.88",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "picpeak-frontend", "name": "picpeak-frontend",
"version": "1.0.85", "version": "1.0.88",
"dependencies": { "dependencies": {
"@tanstack/react-query": "^5.0.0", "@tanstack/react-query": "^5.0.0",
"@tiptap/extension-character-count": "^2.26.1", "@tiptap/extension-character-count": "^2.26.1",
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "picpeak-frontend", "name": "picpeak-frontend",
"private": true, "private": true,
"version": "1.0.85", "version": "1.0.88",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -12,7 +12,7 @@ import {
Info, Info,
Eye, Eye,
EyeOff, EyeOff,
TestTube, Wifi,
CheckCircle, CheckCircle,
XCircle, XCircle,
Loader2, Loader2,
@@ -386,7 +386,7 @@ export const BackupConfiguration = ({ config, onSave, isSaving }) => {
</> </>
) : ( ) : (
<> <>
<TestTube className="mr-2 h-4 w-4" /> <Wifi className="mr-2 h-4 w-4" />
{t('backup.actions.testConnection')} {t('backup.actions.testConnection')}
</> </>
)} )}
@@ -183,7 +183,7 @@ export const BackupDashboard = ({ status, config, onRunBackup, isBackupRunning }
label={t('backup.dashboard.stats.backupSize')} label={t('backup.dashboard.stats.backupSize')}
value={formatBytes(statistics.total_size || 0)} value={formatBytes(statistics.total_size || 0)}
color="green" color="green"
subtext={`${statistics.files_processed || 0} files`} subtext={`${statistics.files_processed || 0} ${t('backup.dashboard.stats.files')}`}
/> />
<StatCard <StatCard
@@ -294,7 +294,7 @@ export const BackupDashboard = ({ status, config, onRunBackup, isBackupRunning }
<div> <div>
<p className="font-medium text-gray-900"> <p className="font-medium text-gray-900">
{config?.backup_destination_type {config?.backup_destination_type
? config.backup_destination_type.toUpperCase() ? t(`backup.configuration.destinationTypes.${config.backup_destination_type}.name`)
: t('backup.dashboard.notConfigured.title')} : t('backup.dashboard.notConfigured.title')}
</p> </p>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
@@ -1,4 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { import {
Download, Download,
Eye, Eye,
@@ -41,6 +42,7 @@ const formatBytes = (bytes) => {
}; };
export const BackupHistory = () => { export const BackupHistory = () => {
const { t } = useTranslation();
const [expandedRows, setExpandedRows] = useState(new Set()); const [expandedRows, setExpandedRows] = useState(new Set());
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const [filterStatus, setFilterStatus] = useState('all'); const [filterStatus, setFilterStatus] = useState('all');
@@ -187,8 +187,8 @@ export const RestoreWizard = () => {
const renderSourceSelection = () => ( const renderSourceSelection = () => (
<div className="space-y-6"> <div className="space-y-6">
<div> <div>
<h3 className="text-lg font-semibold text-gray-900 mb-2">Select Backup Source</h3> <h3 className="text-lg font-semibold text-gray-900 mb-2">{t('backup.restore.source.title')}</h3>
<p className="text-sm text-gray-600">Choose where to restore the backup from</p> <p className="text-sm text-gray-600">{t('backup.restore.source.subtitle')}</p>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
@@ -203,8 +203,8 @@ export const RestoreWizard = () => {
<HardDrive className={`h-12 w-12 mb-3 mx-auto ${ <HardDrive className={`h-12 w-12 mb-3 mx-auto ${
restoreData.source === 'local' ? 'text-primary' : 'text-gray-400' restoreData.source === 'local' ? 'text-primary' : 'text-gray-400'
}`} /> }`} />
<h4 className="font-medium text-gray-900">Local Backup</h4> <h4 className="font-medium text-gray-900">{t('backup.restore.source.local.name')}</h4>
<p className="text-xs text-gray-500 mt-1">Restore from local filesystem</p> <p className="text-xs text-gray-500 mt-1">{t('backup.restore.source.local.description')}</p>
</button> </button>
<button <button
@@ -218,8 +218,8 @@ export const RestoreWizard = () => {
<Cloud className={`h-12 w-12 mb-3 mx-auto ${ <Cloud className={`h-12 w-12 mb-3 mx-auto ${
restoreData.source === 's3' ? 'text-primary' : 'text-gray-400' restoreData.source === 's3' ? 'text-primary' : 'text-gray-400'
}`} /> }`} />
<h4 className="font-medium text-gray-900">S3 Storage</h4> <h4 className="font-medium text-gray-900">{t('backup.restore.source.s3.name')}</h4>
<p className="text-xs text-gray-500 mt-1">Restore from S3 bucket</p> <p className="text-xs text-gray-500 mt-1">{t('backup.restore.source.s3.description')}</p>
</button> </button>
<button <button
@@ -233,8 +233,8 @@ export const RestoreWizard = () => {
<Upload className={`h-12 w-12 mb-3 mx-auto ${ <Upload className={`h-12 w-12 mb-3 mx-auto ${
restoreData.source === 'upload' ? 'text-primary' : 'text-gray-400' restoreData.source === 'upload' ? 'text-primary' : 'text-gray-400'
}`} /> }`} />
<h4 className="font-medium text-gray-900">Upload Backup</h4> <h4 className="font-medium text-gray-900">{t('backup.restore.source.upload.name')}</h4>
<p className="text-xs text-gray-500 mt-1">Upload a backup file</p> <p className="text-xs text-gray-500 mt-1">{t('backup.restore.source.upload.description')}</p>
</button> </button>
</div> </div>
+63 -9
View File
@@ -959,8 +959,9 @@
"active": "Aktiv", "active": "Aktiv",
"inactive": "Inaktiv" "inactive": "Inaktiv"
}, },
"recentActivity": "Letzte Backup-Aktivitäten", "recentActivity": {
"backupCoverage": "Backup-Abdeckung", "title": "Letzte Backup-Aktivitäten"
},
"notConfigured": { "notConfigured": {
"title": "Backup nicht konfiguriert", "title": "Backup nicht konfiguriert",
"message": "Bitte konfigurieren Sie die Backup-Einstellungen im Konfiguration-Tab, bevor Sie Backups ausführen." "message": "Bitte konfigurieren Sie die Backup-Einstellungen im Konfiguration-Tab, bevor Sie Backups ausführen."
@@ -977,7 +978,7 @@
"storageDestination": "Speicherziel", "storageDestination": "Speicherziel",
"nextScheduledBackup": "Nächstes geplantes Backup", "nextScheduledBackup": "Nächstes geplantes Backup",
"backupType": "{{type}} Backup", "backupType": "{{type}} Backup",
"noBackupsYet": "Noch keine Backups" "noDestinationSet": "Kein Ziel festgelegt"
}, },
"configuration": { "configuration": {
"enableBackup": "Automatisierte Backups aktivieren", "enableBackup": "Automatisierte Backups aktivieren",
@@ -999,24 +1000,34 @@
"fields": { "fields": {
"destinationPath": "Zielpfad", "destinationPath": "Zielpfad",
"destinationPathHelp": "Lokaler Verzeichnispfad für Backup-Speicherung", "destinationPathHelp": "Lokaler Verzeichnispfad für Backup-Speicherung",
"destinationPathPlaceholder": "/pfad/zum/backup/verzeichnis",
"rsyncHost": "Remote-Host", "rsyncHost": "Remote-Host",
"rsyncHostHelp": "SSH-Hostname oder IP-Adresse", "rsyncHostHelp": "SSH-Hostname oder IP-Adresse",
"rsyncHostPlaceholder": "backup.beispiel.de",
"rsyncUser": "SSH-Benutzer", "rsyncUser": "SSH-Benutzer",
"rsyncUserHelp": "Benutzername für SSH-Verbindung", "rsyncUserHelp": "Benutzername für SSH-Verbindung",
"rsyncUserPlaceholder": "backup-benutzer",
"rsyncPath": "Remote-Pfad", "rsyncPath": "Remote-Pfad",
"rsyncPathHelp": "Verzeichnispfad auf Remote-Server", "rsyncPathHelp": "Verzeichnispfad auf Remote-Server",
"rsyncPathPlaceholder": "/home/backup/foto-sharing",
"rsyncSshKey": "SSH Private Key", "rsyncSshKey": "SSH Private Key",
"rsyncSshKeyHelp": "SSH Private Key für Authentifizierung (optional)", "rsyncSshKeyHelp": "SSH Private Key für Authentifizierung (optional)",
"rsyncSshKeyPlaceholder": "-----BEGIN RSA PRIVATE KEY-----",
"s3Endpoint": "S3-Endpunkt", "s3Endpoint": "S3-Endpunkt",
"s3EndpointHelp": "S3 API-Endpunkt (z.B. s3.amazonaws.com)", "s3EndpointHelp": "S3 API-Endpunkt (z.B. s3.amazonaws.com)",
"s3EndpointPlaceholder": "https://s3.amazonaws.com",
"s3Bucket": "Bucket-Name", "s3Bucket": "Bucket-Name",
"s3BucketHelp": "S3-Bucket für Backup-Speicherung", "s3BucketHelp": "S3-Bucket für Backup-Speicherung",
"s3BucketPlaceholder": "mein-backup-bucket",
"s3AccessKey": "Zugriffsschlüssel-ID", "s3AccessKey": "Zugriffsschlüssel-ID",
"s3AccessKeyHelp": "AWS/S3 Zugriffsschlüssel-ID", "s3AccessKeyHelp": "AWS/S3 Zugriffsschlüssel-ID",
"s3AccessKeyPlaceholder": "AKIAIOSFODNN7EXAMPLE",
"s3SecretKey": "Geheimer Zugriffsschlüssel", "s3SecretKey": "Geheimer Zugriffsschlüssel",
"s3SecretKeyHelp": "AWS/S3 geheimer Zugriffsschlüssel", "s3SecretKeyHelp": "AWS/S3 geheimer Zugriffsschlüssel",
"s3SecretKeyPlaceholder": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"s3Region": "Region", "s3Region": "Region",
"s3RegionHelp": "S3-Region (z.B. eu-central-1)" "s3RegionHelp": "S3-Region (z.B. eu-central-1)",
"s3RegionPlaceholder": "eu-central-1"
}, },
"schedule": { "schedule": {
"title": "Backup-Zeitplan", "title": "Backup-Zeitplan",
@@ -1027,6 +1038,12 @@
"weekly": "Wöchentlich", "weekly": "Wöchentlich",
"custom": "Benutzerdefinierter Cron-Ausdruck" "custom": "Benutzerdefinierter Cron-Ausdruck"
}, },
"options": {
"hourly": "Jede Stunde",
"daily": "Täglich",
"weekly": "Wöchentlich",
"custom": "Benutzerdefinierter Cron-Ausdruck"
},
"customCron": "Cron-Ausdruck", "customCron": "Cron-Ausdruck",
"customCronHelp": "Geben Sie einen gültigen Cron-Ausdruck ein (z.B. 0 3 * * *)", "customCronHelp": "Geben Sie einen gültigen Cron-Ausdruck ein (z.B. 0 3 * * *)",
"retention": "Aufbewahrungszeitraum", "retention": "Aufbewahrungszeitraum",
@@ -1063,6 +1080,11 @@
"connectionTestFailed": "Verbindungstest fehlgeschlagen", "connectionTestFailed": "Verbindungstest fehlgeschlagen",
"connectionTestSuccess": "Verbindungstest erfolgreich!" "connectionTestSuccess": "Verbindungstest erfolgreich!"
}, },
"messages": {
"requiredFields": "Bitte füllen Sie alle erforderlichen Felder aus",
"connectionSuccess": "Verbindungstest erfolgreich!",
"connectionFailed": "Verbindungstest fehlgeschlagen"
},
"testingConnection": "Teste Verbindung...", "testingConnection": "Teste Verbindung...",
"saveSettings": "Konfiguration speichern", "saveSettings": "Konfiguration speichern",
"savingSettings": "Speichern..." "savingSettings": "Speichern..."
@@ -1086,6 +1108,14 @@
"duration": "Dauer", "duration": "Dauer",
"actions": "Aktionen" "actions": "Aktionen"
}, },
"columns": {
"status": "Status",
"dateTime": "Datum & Zeit",
"type": "Typ",
"size": "Größe",
"duration": "Dauer",
"actions": "Aktionen"
},
"details": "Details", "details": "Details",
"statistics": "Statistiken", "statistics": "Statistiken",
"errors": "Fehler", "errors": "Fehler",
@@ -1104,6 +1134,27 @@
"showing": "Zeige {{from}}-{{to}} von {{total}} Backups", "showing": "Zeige {{from}}-{{to}} von {{total}} Backups",
"previous": "Zurück", "previous": "Zurück",
"next": "Weiter" "next": "Weiter"
},
"filter": {
"allStatus": "Alle Status",
"completed": "Abgeschlossen",
"failed": "Fehlgeschlagen",
"running": "Läuft",
"partial": "Teilweise"
},
"noBackupsFound": "Keine Backups gefunden",
"backupsWillAppear": "Backups werden hier angezeigt, sobald sie erstellt wurden",
"messages": {
"deleteSuccess": "Backup erfolgreich gelöscht"
},
"details": {
"backupDetails": "Backup-Details",
"destination": "Ziel",
"started": "Gestartet",
"completed": "Abgeschlossen",
"contentBackedUp": "Gesicherter Inhalt",
"errorDetails": "Fehlerdetails",
"manifest": "Manifest"
} }
}, },
"restore": { "restore": {
@@ -1147,10 +1198,7 @@
"enterPassphrase": "Verschlüsselungs-Passphrase eingeben", "enterPassphrase": "Verschlüsselungs-Passphrase eingeben",
"at": "um" "at": "um"
}, },
"options": { "restoreTypes": {
"title": "Wiederherstellungsoptionen",
"subtitle": "Wählen Sie, was wiederhergestellt werden soll",
"types": {
"full": { "full": {
"name": "Vollständige Wiederherstellung", "name": "Vollständige Wiederherstellung",
"description": "Alles wiederherstellen, einschließlich Datenbank, Fotos und Archive", "description": "Alles wiederherstellen, einschließlich Datenbank, Fotos und Archive",
@@ -1171,7 +1219,10 @@
"description": "Bestimmte Elemente zur Wiederherstellung auswählen", "description": "Bestimmte Elemente zur Wiederherstellung auswählen",
"warning": "Nur ausgewählte Elemente werden wiederhergestellt" "warning": "Nur ausgewählte Elemente werden wiederhergestellt"
} }
}, },
"options": {
"title": "Wiederherstellungsoptionen",
"subtitle": "Wählen Sie, was wiederhergestellt werden soll",
"additionalOptions": { "additionalOptions": {
"title": "Zusätzliche Optionen", "title": "Zusätzliche Optionen",
"skipPreBackup": "Vor-Wiederherstellungs-Backup überspringen", "skipPreBackup": "Vor-Wiederherstellungs-Backup überspringen",
@@ -1234,6 +1285,9 @@
"starting": "Starte...", "starting": "Starte...",
"validating": "Validiere...", "validating": "Validiere...",
"startNewRestore": "Neue Wiederherstellung starten" "startNewRestore": "Neue Wiederherstellung starten"
},
"messages": {
"restoreStarted": "Wiederherstellung erfolgreich gestartet"
} }
}, },
"messages": { "messages": {
+72 -12
View File
@@ -990,12 +990,15 @@
"warning": "Warning", "warning": "Warning",
"critical": "Critical" "critical": "Critical"
}, },
"health": {
"title": "Backup Health"
},
"healthMessages": { "healthMessages": {
"noBackups": "No backups found", "noBackups": "No backups found",
"failed": "Last backup failed", "lastBackupFailed": "Last backup failed",
"upToDate": "Backup is up to date", "upToDate": "Backup is up to date",
"recent": "Backup is recent", "recent": "Backup is recent",
"old": "Backup is getting old", "gettingOld": "Backup is getting old",
"outdated": "Backup is outdated" "outdated": "Backup is outdated"
}, },
"stats": { "stats": {
@@ -1007,15 +1010,18 @@
"files": "files", "files": "files",
"minutes": "{{count}}m", "minutes": "{{count}}m",
"active": "Active", "active": "Active",
"inactive": "Inactive" "inactive": "Inactive",
"noBackupsYet": "No backups yet"
},
"recentActivity": {
"title": "Recent Backup Activity"
}, },
"recentActivity": "Recent Backup Activity",
"backupCoverage": "Backup Coverage",
"notConfigured": { "notConfigured": {
"title": "Backup Not Configured", "title": "Backup Not Configured",
"message": "Please configure backup settings in the Configuration tab before running backups." "message": "Please configure backup settings in the Configuration tab before running backups."
}, },
"coverage": { "coverage": {
"title": "Backup Coverage",
"database": "Database", "database": "Database",
"photos": "Photos", "photos": "Photos",
"archives": "Archives", "archives": "Archives",
@@ -1027,10 +1033,11 @@
"storageDestination": "Storage Destination", "storageDestination": "Storage Destination",
"nextScheduledBackup": "Next Scheduled Backup", "nextScheduledBackup": "Next Scheduled Backup",
"backupType": "{{type}} backup", "backupType": "{{type}} backup",
"noBackupsYet": "No backups yet" "noDestinationSet": "No destination set"
}, },
"configuration": { "configuration": {
"enableBackup": "Enable Automated Backups", "enableBackup": "Enable Automated Backups",
"enableBackupHelp": "Automatically create backups according to the configured schedule",
"destinationType": "Backup Destination", "destinationType": "Backup Destination",
"destinationTypes": { "destinationTypes": {
"local": { "local": {
@@ -1049,24 +1056,34 @@
"fields": { "fields": {
"destinationPath": "Destination Path", "destinationPath": "Destination Path",
"destinationPathHelp": "Local directory path for storing backups", "destinationPathHelp": "Local directory path for storing backups",
"destinationPathPlaceholder": "/path/to/backup/directory",
"rsyncHost": "Remote Host", "rsyncHost": "Remote Host",
"rsyncHostHelp": "SSH hostname or IP address", "rsyncHostHelp": "SSH hostname or IP address",
"rsyncHostPlaceholder": "backup.example.com",
"rsyncUser": "SSH User", "rsyncUser": "SSH User",
"rsyncUserHelp": "Username for SSH connection", "rsyncUserHelp": "Username for SSH connection",
"rsyncUserPlaceholder": "backup-user",
"rsyncPath": "Remote Path", "rsyncPath": "Remote Path",
"rsyncPathHelp": "Directory path on remote server", "rsyncPathHelp": "Directory path on remote server",
"rsyncPathPlaceholder": "/home/backup/photo-sharing",
"rsyncSshKey": "SSH Private Key", "rsyncSshKey": "SSH Private Key",
"rsyncSshKeyHelp": "SSH private key for authentication (optional)", "rsyncSshKeyHelp": "SSH private key for authentication (optional)",
"rsyncSshKeyPlaceholder": "-----BEGIN RSA PRIVATE KEY-----",
"s3Endpoint": "S3 Endpoint", "s3Endpoint": "S3 Endpoint",
"s3EndpointHelp": "S3 API endpoint (e.g., s3.amazonaws.com)", "s3EndpointHelp": "S3 API endpoint (e.g., s3.amazonaws.com)",
"s3EndpointPlaceholder": "https://s3.amazonaws.com",
"s3Bucket": "Bucket Name", "s3Bucket": "Bucket Name",
"s3BucketHelp": "S3 bucket for storing backups", "s3BucketHelp": "S3 bucket for storing backups",
"s3BucketPlaceholder": "my-backup-bucket",
"s3AccessKey": "Access Key ID", "s3AccessKey": "Access Key ID",
"s3AccessKeyHelp": "AWS/S3 access key ID", "s3AccessKeyHelp": "AWS/S3 access key ID",
"s3AccessKeyPlaceholder": "AKIAIOSFODNN7EXAMPLE",
"s3SecretKey": "Secret Access Key", "s3SecretKey": "Secret Access Key",
"s3SecretKeyHelp": "AWS/S3 secret access key", "s3SecretKeyHelp": "AWS/S3 secret access key",
"s3SecretKeyPlaceholder": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"s3Region": "Region", "s3Region": "Region",
"s3RegionHelp": "S3 region (e.g., us-east-1)" "s3RegionHelp": "S3 region (e.g., us-east-1)",
"s3RegionPlaceholder": "us-east-1"
}, },
"schedule": { "schedule": {
"title": "Backup Schedule", "title": "Backup Schedule",
@@ -1077,6 +1094,12 @@
"weekly": "Weekly", "weekly": "Weekly",
"custom": "Custom cron expression" "custom": "Custom cron expression"
}, },
"options": {
"hourly": "Every hour",
"daily": "Daily",
"weekly": "Weekly",
"custom": "Custom cron expression"
},
"customCron": "Cron Expression", "customCron": "Cron Expression",
"customCronHelp": "Enter a valid cron expression (e.g., 0 3 * * *)", "customCronHelp": "Enter a valid cron expression (e.g., 0 3 * * *)",
"retention": "Retention Period", "retention": "Retention Period",
@@ -1113,6 +1136,11 @@
"connectionTestFailed": "Connection test failed", "connectionTestFailed": "Connection test failed",
"connectionTestSuccess": "Connection test successful!" "connectionTestSuccess": "Connection test successful!"
}, },
"messages": {
"requiredFields": "Please fill in all required fields",
"connectionSuccess": "Connection test successful!",
"connectionFailed": "Connection test failed"
},
"testingConnection": "Testing connection...", "testingConnection": "Testing connection...",
"saveSettings": "Save Configuration", "saveSettings": "Save Configuration",
"savingSettings": "Saving..." "savingSettings": "Saving..."
@@ -1136,6 +1164,14 @@
"duration": "Duration", "duration": "Duration",
"actions": "Actions" "actions": "Actions"
}, },
"columns": {
"status": "Status",
"dateTime": "Date & Time",
"type": "Type",
"size": "Size",
"duration": "Duration",
"actions": "Actions"
},
"details": "Details", "details": "Details",
"statistics": "Statistics", "statistics": "Statistics",
"errors": "Errors", "errors": "Errors",
@@ -1154,6 +1190,27 @@
"showing": "Showing {{from}}-{{to}} of {{total}} backups", "showing": "Showing {{from}}-{{to}} of {{total}} backups",
"previous": "Previous", "previous": "Previous",
"next": "Next" "next": "Next"
},
"filter": {
"allStatus": "All Status",
"completed": "Completed",
"failed": "Failed",
"running": "Running",
"partial": "Partial"
},
"noBackupsFound": "No backups found",
"backupsWillAppear": "Backups will appear here once created",
"messages": {
"deleteSuccess": "Backup deleted successfully"
},
"details": {
"backupDetails": "Backup Details",
"destination": "Destination",
"started": "Started",
"completed": "Completed",
"contentBackedUp": "Content Backed Up",
"errorDetails": "Error Details",
"manifest": "Manifest"
} }
}, },
"restore": { "restore": {
@@ -1197,10 +1254,7 @@
"enterPassphrase": "Enter encryption passphrase", "enterPassphrase": "Enter encryption passphrase",
"at": "at" "at": "at"
}, },
"options": { "restoreTypes": {
"title": "Restore Options",
"subtitle": "Choose what to restore",
"types": {
"full": { "full": {
"name": "Full Restore", "name": "Full Restore",
"description": "Restore everything including database, photos, and archives", "description": "Restore everything including database, photos, and archives",
@@ -1221,7 +1275,10 @@
"description": "Choose specific items to restore", "description": "Choose specific items to restore",
"warning": "Only selected items will be restored" "warning": "Only selected items will be restored"
} }
}, },
"options": {
"title": "Restore Options",
"subtitle": "Choose what to restore",
"additionalOptions": { "additionalOptions": {
"title": "Additional Options", "title": "Additional Options",
"skipPreBackup": "Skip Pre-Restore Backup", "skipPreBackup": "Skip Pre-Restore Backup",
@@ -1284,6 +1341,9 @@
"starting": "Starting...", "starting": "Starting...",
"validating": "Validating...", "validating": "Validating...",
"startNewRestore": "Start New Restore" "startNewRestore": "Start New Restore"
},
"messages": {
"restoreStarted": "Restore started successfully"
} }
}, },
"messages": { "messages": {