add missing translation for export

This commit is contained in:
2026-05-12 19:26:18 +02:00
parent 56339222e7
commit 35d2d0a8d3
6 changed files with 74 additions and 10 deletions

View File

@@ -1402,8 +1402,10 @@
const exportProgressContainer = document.getElementById('export-progress-container'); const exportProgressContainer = document.getElementById('export-progress-container');
const exportProgressBar = document.getElementById('export-progress-bar'); const exportProgressBar = document.getElementById('export-progress-bar');
const exportStatusText = document.getElementById('export-status-text'); const exportStatusText = document.getElementById('export-status-text');
const exportStatusMsg = document.getElementById('export-status-msg');
const chkExportUploads = document.getElementById('export_uploads'); const chkExportUploads = document.getElementById('export_uploads');
const chkExportFavorites = document.getElementById('export_favorites'); const chkExportFavorites = document.getElementById('export_favorites');
const exportAnimatedDots = document.getElementById('export-animated-dots');
if (btnStartExport) { if (btnStartExport) {
btnStartExport.addEventListener('click', async () => { btnStartExport.addEventListener('click', async () => {
@@ -1411,14 +1413,14 @@
const exportFavorites = chkExportFavorites.checked; const exportFavorites = chkExportFavorites.checked;
if (!exportUploads && !exportFavorites) { if (!exportUploads && !exportFavorites) {
alert('Please select at least one option to export.'); alert(exportStatusText.dataset.selectOption || 'Please select at least one option to export.');
return; return;
} }
btnStartExport.disabled = true; btnStartExport.disabled = true;
exportProgressContainer.style.display = 'block'; exportProgressContainer.style.display = 'block';
exportProgressBar.style.width = '0%'; exportProgressBar.style.width = '0%';
exportStatusText.textContent = 'Fetching data list...'; exportStatusMsg.textContent = exportStatusText.dataset.fetching || 'Fetching data list...';
try { try {
const res = await fetch('/settings/export-data'); const res = await fetch('/settings/export-data');
@@ -1433,7 +1435,7 @@
} }
if (filesToDownload.length === 0) { if (filesToDownload.length === 0) {
alert('No data found to export.'); alert(exportStatusText.dataset.noData || 'No data found to export.');
btnStartExport.disabled = false; btnStartExport.disabled = false;
exportProgressContainer.style.display = 'none'; exportProgressContainer.style.display = 'none';
return; return;
@@ -1463,7 +1465,10 @@
completed++; completed++;
const percent = Math.round((completed / total) * 100); const percent = Math.round((completed / total) * 100);
exportProgressBar.style.width = percent + '%'; exportProgressBar.style.width = percent + '%';
exportStatusText.textContent = `Processing files: ${completed} / ${total}`; const msg = (exportStatusText.dataset.processing || 'Processing files: {completed} / {total}')
.replace('{completed}', completed)
.replace('{total}', total);
exportStatusMsg.textContent = msg;
return; return;
} }
@@ -1478,7 +1483,10 @@
completed++; completed++;
const percent = Math.round((completed / total) * 100); const percent = Math.round((completed / total) * 100);
exportProgressBar.style.width = percent + '%'; exportProgressBar.style.width = percent + '%';
exportStatusText.textContent = `Processing files: ${completed} / ${total}`; const msg = (exportStatusText.dataset.processing || 'Processing files: {completed} / {total}')
.replace('{completed}', completed)
.replace('{total}', total);
exportStatusMsg.textContent = msg;
} }
}; };
@@ -1489,7 +1497,8 @@
await Promise.all(batch.map(downloadFile)); await Promise.all(batch.map(downloadFile));
} }
exportStatusText.textContent = 'Generating ZIP file...'; exportStatusMsg.textContent = exportStatusText.dataset.generating || 'Generating ZIP file';
exportAnimatedDots.style.display = 'inline';
const content = await new Promise((resolve, reject) => { const content = await new Promise((resolve, reject) => {
const chunks = []; const chunks = [];
zip.generateInternalStream({ type: 'uint8array', compression: 'DEFLATE', compressionOptions: { level: 6 } }) zip.generateInternalStream({ type: 'uint8array', compression: 'DEFLATE', compressionOptions: { level: 6 } })
@@ -1504,6 +1513,7 @@
}) })
.resume(); .resume();
}); });
exportAnimatedDots.style.display = 'none';
const link = document.createElement('a'); const link = document.createElement('a');
link.href = URL.createObjectURL(content); link.href = URL.createObjectURL(content);
@@ -1512,13 +1522,13 @@
link.click(); link.click();
document.body.removeChild(link); document.body.removeChild(link);
exportStatusText.textContent = 'Export complete!'; exportStatusMsg.textContent = exportStatusText.dataset.complete || 'Export complete!';
btnStartExport.disabled = false; btnStartExport.disabled = false;
} catch (err) { } catch (err) {
console.error('Export failed:', err); console.error('Export failed:', err);
alert('Export failed. See console for details.'); alert(exportStatusText.dataset.failedAlert || 'Export failed. See console for details.');
btnStartExport.disabled = false; btnStartExport.disabled = false;
exportStatusText.textContent = 'Export failed.'; exportStatusMsg.textContent = exportStatusText.dataset.failed || 'Export failed.';
} }
}); });
} }

View File

@@ -213,6 +213,14 @@
"export_uploads": "Meine Uploads", "export_uploads": "Meine Uploads",
"export_favorites": "Meine Favoriten", "export_favorites": "Meine Favoriten",
"export_preparing": "Wird vorbereitet...", "export_preparing": "Wird vorbereitet...",
"export_fetching_data": "Datenliste wird abgerufen...",
"export_processing_files": "Dateien werden verarbeitet: {completed} / {total}",
"export_generating_zip": "ZIP-Datei wird generiert",
"export_complete": "Export abgeschlossen!",
"export_failed": "Export fehlgeschlagen.",
"export_select_option": "Bitte wähle mindestens eine Option zum Exportieren aus.",
"export_no_data": "Keine Daten zum Exportieren gefunden.",
"export_failed_alert": "Export fehlgeschlagen. Details findest du in der Konsole.",
"start_export": "Export generieren (ZIP)" "start_export": "Export generieren (ZIP)"
}, },
"filter": { "filter": {

View File

@@ -213,6 +213,14 @@
"export_uploads": "My Uploads", "export_uploads": "My Uploads",
"export_favorites": "My Favorites", "export_favorites": "My Favorites",
"export_preparing": "Preparing...", "export_preparing": "Preparing...",
"export_fetching_data": "Fetching data list...",
"export_processing_files": "Processing files: {completed} / {total}",
"export_generating_zip": "Generating ZIP file",
"export_complete": "Export complete!",
"export_failed": "Export failed.",
"export_select_option": "Please select at least one option to export.",
"export_no_data": "No data found to export.",
"export_failed_alert": "Export failed. See console for details.",
"start_export": "Generate Export (ZIP)" "start_export": "Generate Export (ZIP)"
}, },
"filter": { "filter": {

View File

@@ -213,6 +213,14 @@
"export_uploads": "Jouw uploads", "export_uploads": "Jouw uploads",
"export_favorites": "Jouw favorieten", "export_favorites": "Jouw favorieten",
"export_preparing": "Voorbereiden...", "export_preparing": "Voorbereiden...",
"export_fetching_data": "Gegevenslijst ophalen...",
"export_processing_files": "Bestanden verwerken: {completed} / {total}",
"export_generating_zip": "ZIP-bestand genereren",
"export_complete": "Export voltooid!",
"export_failed": "Export mislukt.",
"export_select_option": "Selecteer ten minste één optie om te exporteren.",
"export_no_data": "Geen gegevens gevonden om te exporteren.",
"export_failed_alert": "Export mislukt. Zie console voor details.",
"start_export": "Export genereren (ZIP)" "start_export": "Export genereren (ZIP)"
}, },
"filter": { "filter": {

View File

@@ -212,6 +212,14 @@
"export_uploads": "Meine Aufladungen", "export_uploads": "Meine Aufladungen",
"export_favorites": "Meine Favorisierungen", "export_favorites": "Meine Favorisierungen",
"export_preparing": "Vorbereitung wird getroffen...", "export_preparing": "Vorbereitung wird getroffen...",
"export_fetching_data": "Holt die ganze Liste...",
"export_processing_files": "Verpackt Dateien: {completed} / {total}",
"export_generating_zip": "Paket wird geschnürt...",
"export_complete": "Paket fertig!",
"export_failed": "Paket kaputt.",
"export_select_option": "Bitte wählen Sie etwas zum verpacken aus.",
"export_no_data": "Nix da zum verpacken.",
"export_failed_alert": "Auf dem Weg gestorben :(",
"start_export": "Paket schnüren" "start_export": "Paket schnüren"
}, },
"filter": { "filter": {

View File

@@ -278,7 +278,17 @@
<div class="progress-bar-wrapper" style="height: 20px; background: rgba(255,255,255,0.1); border-radius: 10px; overflow: hidden; margin-bottom: 5px;"> <div class="progress-bar-wrapper" style="height: 20px; background: rgba(255,255,255,0.1); border-radius: 10px; overflow: hidden; margin-bottom: 5px;">
<div id="export-progress-bar" style="height: 100%; width: 0%; background: var(--accent); transition: width 0.3s;"></div> <div id="export-progress-bar" style="height: 100%; width: 0%; background: var(--accent); transition: width 0.3s;"></div>
</div> </div>
<div id="export-status-text" style="font-size: 0.9em; color: var(--text-muted);">{{ t('settings.export_preparing') || 'Preparing...' }}</div> <div id="export-status-text"
style="font-size: 0.9em; color: var(--text-muted);"
data-fetching="{{ t('settings.export_fetching_data') }}"
data-processing="{{ t('settings.export_processing_files') }}"
data-generating="{{ t('settings.export_generating_zip') }}"
data-complete="{{ t('settings.export_complete') }}"
data-failed="{{ t('settings.export_failed') }}"
data-select-option="{{ t('settings.export_select_option') }}"
data-no-data="{{ t('settings.export_no_data') }}"
data-failed-alert="{{ t('settings.export_failed_alert') }}"
><span id="export-status-msg">{{ t('settings.export_preparing') || 'Preparing...' }}</span><span class="export-dots" id="export-animated-dots" style="display:none;"><span>.</span><span>.</span><span>.</span></span></div>
</div> </div>
<button type="button" id="btn-start-export" class="button button-primary"> <button type="button" id="btn-start-export" class="button button-primary">
@@ -387,6 +397,18 @@
</div> </div>
@endif @endif
<style>
@keyframes exportDotBounce {
0%, 80%, 100% { transform: translateY(0); opacity: 0.3; }
40% { transform: translateY(-5px); opacity: 1; }
}
.export-dots span {
display: inline-block;
animation: exportDotBounce 1.2s infinite ease-in-out;
}
.export-dots span:nth-child(2) { animation-delay: 0.2s; }
.export-dots span:nth-child(3) { animation-delay: 0.4s; }
</style>
<script src="/s/js/jszip.min.js"></script> <script src="/s/js/jszip.min.js"></script>
<script src="/s/js/settings.js?v=@mtime(/public/s/js/settings.js)"></script> <script src="/s/js/settings.js?v=@mtime(/public/s/js/settings.js)"></script>
</div> </div>