(function (root, factory) { const api = factory(); if (typeof module === 'object' && module.exports) module.exports = api; if (root) root.I18n = api; })(typeof window !== 'undefined' ? window : globalThis, function () { const pairs = [ ['Arbeitsbereich', 'Workspace'], ['Accounts verwalten', 'Manage accounts'], ['Archiv', 'Archive'], ['(aktivieren zum Erzeugen)', '(enable to generate)'], ['-Tab direkt beim jeweiligen Hoster.', ' tab for the relevant host.'], ['127.0.0.1 oder Tunnel-/Tailscale-Adresse', '127.0.0.1 or tunnel/Tailscale address'], ['API-Token', 'API token'], ['Account-Status', 'Account status'], ['Allowlist (IP/CIDR, eine pro Zeile)', 'Allowlist (one IP/CIDR per line)'], ['Aufbewahrung', 'Retention'], ['Ausgabe-Format der kopierten Links', 'Output format for copied links'], ['Auto-Check vor Upload', 'Auto-check before upload'], ['Automatischer Check vor dem Upload', 'Automatic check before upload'], ['Bildschirm und Eingabesteuerung bleiben gesperrt.', 'Screen and input control remain locked.'], ['Bindet nur an', 'Binds only to'], ['Bindet an', 'Binds to'], ['. Nur IPs/CIDRs aus der Allowlist dürfen verbinden (Loopback immer) — zusätzlich zum Token. Über Tailscale: trage deinen Tailnet-Bereich ein (z.B.', '. Only IPs/CIDRs from the allowlist may connect (loopback is always allowed), in addition to the token. For Tailscale, enter your tailnet range, e.g.'], [') und die Tailscale-IP/MagicDNS oben als Code-Adresse. Transport ist plaintext über den Tunnel — Tailscale/WireGuard verschlüsselt.', ') and enter the Tailscale IP or MagicDNS name above as the code address. Transport is plaintext through the tunnel; Tailscale/WireGuard provides encryption.'], ['Datum', 'Date'], ['Einstellungskategorien', 'Settings categories'], ['Erlaubt', 'Allowed'], ['Erneut versuchen', 'Retry'], ['Exportieren', 'Export'], ['Fehlgeschlagene erneut', 'Retry failed'], ['Fensterverhalten, Drop-Target und Programmupdates.', 'Window behavior, drop target, and application updates.'], ['Gesamt:', 'Total:'], ['Globales Speed-Limit', 'Global speed limit'], ['Hauptbereiche', 'Main sections'], ['Hinweis', 'Notice'], ['Hoster-Limits automatisch hochskalieren', 'Automatically scale host limits'], ['Hoster', 'Host'], ['Importieren', 'Import'], ['In Zwischenablage', 'To clipboard'], ['In diesem Lauf hochgeladen:', 'Uploaded during this run:'], ['Input erlauben', 'Allow input'], ['Installierte Version', 'Installed version'], ['Laufzeit:', 'Runtime:'], ['Letzte 100 Uploads', 'Last 100 uploads'], ['Letzte 1000 Uploads', 'Last 1,000 uploads'], ['Letzte 7 Tage', 'Last 7 days'], ['Letzte 30 Tage', 'Last 30 days'], ['Letzte 90 Tage', 'Last 90 days'], ['Max. parallele Uploads', 'Max. parallel uploads'], ['Maximale parallele Uploads', 'Maximum parallel uploads'], ['Neustart', 'Restart'], ['Noch keine Accounts', 'No accounts yet'], ['Nur lokal (127.0.0.1) — Tunnel/VPN', 'Local only (127.0.0.1) — tunnel/VPN'], ['Parallele Uploads verringern', 'Decrease parallel uploads'], ['Restzeit:', 'Time remaining:'], ['Rest', 'Remaining'], ['Schnell finden', 'Quick find'], ['Schnelleinstellungen', 'Quick settings'], ['Sicherung', 'Backup'], ['Sichtbarkeit', 'Visibility'], ['Sitzung', 'Session'], ['Speicherstatus', 'Save status'], ['Statistik', 'Statistics'], ['Suche Aktualisierungen', 'Checking for updates'], ['Verbleibend:', 'Remaining:'], ['Zuletzt erzeugte Upload-Links', 'Recently generated upload links'], ['User-ID, role:ROLLEN-ID, @here oder @everyone', 'User ID, role:ROLE-ID, @here, or @everyone'], ['https://discord.com/api/webhooks/… oder eigene URL', 'https://discord.com/api/webhooks/… or custom URL'], ['nur lesenden', 'read-only'], ['z. B. Hauptaccount, Premium, Kunde XY', 'e.g. primary account, premium, customer XY'], ['Datei', 'File'], ['Dateien', 'Files'], ['Dateien hinzufügen', 'Add files'], ['Ordner hinzufügen', 'Add folder'], ['Online-Schlüssel erstellen', 'Create online key'], ['Online-Schlüssel importieren', 'Import online key'], ['Einstellungen öffnen', 'Open settings'], ['Geschwindigkeitslimit', 'Speed limit'], ['Hilfe', 'Help'], ['Log-Ordner öffnen', 'Open log folder'], ['Diagnose-Paket exportieren', 'Export diagnostics package'], ['Eine neue Version ist verfügbar', 'A new version is available'], ['Bereit zum Download', 'Ready to download'], ['Abbrechen', 'Cancel'], ['Jetzt installieren', 'Install now'], ['Jetzt updaten', 'Install now'], ['Alle Dateien', 'All files'], ['Aktiv', 'Active'], ['Warteschlange', 'Queue'], ['Fertig', 'Completed'], ['Fehler', 'Failed'], ['Verfügbarkeit', 'Availability'], ['Bereite Accounts', 'Ready accounts'], ['Primär', 'Primary'], ['Nicht geprüft', 'Not checked'], ['Nicht aktiv', 'Inactive'], ['Prüfen', 'Check'], ['Bearbeiten', 'Edit'], ['Keine Upload-Ziele ausgewählt', 'No upload destinations selected'], ['Dateien ablegen, Ziele wählen und Uploads zentral steuern.', 'Drop files, choose destinations, and manage uploads in one place.'], ['Upload-Aufträge', 'Upload jobs'], ['Dateien hinzufügen, Ziele auswählen und Fortschritt verfolgen', 'Add files, choose destinations, and track progress'], ['+ Dateien', '+ Files'], ['+ Ordner', '+ Folder'], ['Dateien hierher ziehen oder klicken', 'Drop files here or click to browse'], ['Dateien und Ordner werden vor dem Upload geprüft.', 'Files and folders are checked before upload.'], ['Dateiname', 'File name'], ['Hoster / Account', 'Host / Account'], ['Hochgeladen / Größe', 'Uploaded / Size'], ['Geschwindigkeit', 'Speed'], ['Fortschritt', 'Progress'], ['Status', 'Status'], ['Aktionen', 'Actions'], ['Alle Links kopieren', 'Copy all links'], ['Alle entfernen', 'Remove all'], ['Entfernen', 'Remove'], ['Dateien in der Warteschlange', 'Files in queue'], ['Läuft:', 'Running:'], ['Fehler:', 'Failed:'], ['Dateigröße in der Warteschlange', 'Queued file size'], ['Upload-Geschwindigkeit:', 'Upload speed:'], ['Zugänge', 'Accounts'], ['Alle Accounts', 'All accounts'], ['Bereit', 'Ready'], ['Aktion nötig', 'Action required'], ['Zugänge prüfen, priorisieren und für Uploads bereitstellen.', 'Check, prioritize, and prepare accounts for uploads.'], ['Hoster-Zugangsdaten verwalten und prüfen', 'Manage and verify host account credentials'], ['Accounts prüfen', 'Check accounts'], ['Account hinzufügen', 'Add account'], ['Füge deinen ersten Hoster-Account hinzu. Die Zugangsdaten werden vor dem Speichern geprüft.', 'Add your first host account. Credentials are verified before saving.'], ['Alle ausklappen', 'Expand all'], ['Alle einklappen', 'Collapse all'], ['Wähle einen Hoster und gib deine Zugangsdaten ein.', 'Choose a host and enter your credentials.'], ['Wähle einen Hoster und gib deine Zugangsdaten ein. Der Account wird vor dem Anlegen geprüft.', 'Choose a host and enter your credentials. The account is checked before it is added.'], ['Prüfen und anlegen', 'Verify and add'], ['Prüfen und speichern', 'Verify and save'], ['Keine Einträge.', 'No entries.'], ['Schließen', 'Close'], ['Account löschen?', 'Delete account?'], ['Account wirklich löschen?', 'Are you sure you want to delete this account?'], ['Löschen', 'Delete'], ['Alle Optionen nach Aufgaben sortiert. Änderungen werden mit dem Speichern-Button übernommen.', 'All options are grouped by task. Changes are applied with the Save button.'], ['Speichern', 'Save'], ['Einstellungen', 'Settings'], ['Allgemein', 'General'], ['Uploads', 'Uploads'], ['Automatik', 'Automation'], ['Benachrichtigungen', 'Notifications'], ['Logs & Support', 'Logs & Support'], ['Fernsteuerung', 'Remote control'], ['Diagnose-Zugriff', 'Diagnostics access'], ['Backup & Übertragen', 'Backup & Transfer'], ['Keine passende Einstellung gefunden.', 'No matching setting found.'], ['Keine ungespeicherten Änderungen', 'No unsaved changes'], ['Oberfläche', 'Interface'], ['Sprache', 'Language'], ['Englisch', 'English'], ['Deutsch', 'German'], ['Immer im Vordergrund', 'Always on top'], ['Drop-Target anzeigen', 'Show drop target'], ['Programmupdate', 'Application update'], ['Nach neuer Version suchen', 'Check for a newer version'], ['Verfügbare Updates werden zusammen mit dem Changelog angezeigt.', 'Available updates are shown together with the changelog.'], ['Neue Version suchen', 'Check for a new version'], ['Nach Updates suchen', 'Check for updates'], ['Upload-Verhalten', 'Upload behavior'], ['Globale Leistung, Warteschlange und Verhalten nach einem erfolgreichen Upload.', 'Global performance, queue, and behavior after a successful upload.'], ['Leistung', 'Performance'], ['Globale parallele Uploads', 'Global parallel uploads'], ['0 = nur die Einstellung des jeweiligen Hosters verwenden', '0 = use the setting of each host'], ['Verteilt die globale Parallelität auf vorhandene Accounts eines Hosters.', 'Distributes global parallelism across the available accounts of a host.'], ['Nach Abschluss', 'After completion'], ['Nach Abschluss aus der Liste entfernen', 'Remove from the list after completion'], ['Erfolgreich hochgeladene Dateien verschwinden automatisch aus der Upload-Liste.', 'Successfully uploaded files are automatically removed from the upload list.'], ['Warteschlange beim Start wiederherstellen', 'Restore queue on startup'], ['Noch nicht abgeschlossene Uploads werden beim nächsten Programmstart erneut angezeigt.', 'Incomplete uploads are shown again the next time the application starts.'], ['Hoster-Einstellungen', 'Host settings'], ['Upload-Einstellungen', 'Upload settings'], ['Erfolgreiche Links in fileuploader.log.', 'Successful links in fileuploader.log.'], ['Verteilt die Dateien reihum auf alle aktiven Accounts dieses Hosters (Datei 1 → Account 1, Datei 2 → Account 2 …). Hält z. B. byse-Accounts aktiv. Nur ein Account = kein Effekt.', 'Distributes files across all active accounts for this host in round-robin order (file 1 → account 1, file 2 → account 2, and so on). Keeps accounts such as byse active. Has no effect with only one account.'], ['Größen-Limit merken', 'Remember size limit'], ['Überspringt nach zwei verdächtigen Ablehnungen auf einem Account größere Dateien dort vorab ("Bekanntes Größen-Limit"). Abschalten = jede Datei wird immer wirklich versucht.', 'After two suspicious rejections on an account, larger files are skipped there in advance ("Known size limit"). When disabled, every file is always attempted.'], ['Einstellungen einzelner Hoster', 'Settings for individual hosts'], ['wie Wiederholungen, Geschwindigkeit, Parallelität, Dateigröße und Logging findest du im', 'such as retries, speed, parallelism, file size, and logging are available in'], ['Accounts-Tab.', 'the Accounts tab.'], ['Wiederholungen und überwachte Ordner für unbeaufsichtigte Uploads.', 'Retries and watched folders for unattended uploads.'], ['Unbeaufsichtigter Betrieb', 'Unattended operation'], ['Automatische Wiederholungsrunden', 'Automatic retry rounds'], ['0 = aus. Nach Batch-Ende werden transiente Fehler (Netzwerk, Hoster-Flake) automatisch bis zu N Runden neu versucht.', '0 = off. After a batch ends, transient errors (network or host issues) are retried automatically for up to N rounds.'], ['Wartezeit zwischen Runden', 'Delay between rounds'], ['Minuten · jede weitere Runde wartet entsprechend länger', 'Minutes · each additional round waits proportionally longer'], ['Ordnerüberwachung', 'Folder monitoring'], ['Inaktiv', 'Inactive'], ['Ordnerpfad', 'Folder path'], ['Wählen', 'Choose'], ['Dateierweiterungen', 'File extensions'], ['Nur diese', 'Only these'], ['Alle außer', 'All except'], ['Verzögerung (Sekunden)', 'Delay (seconds)'], ['Warten bis Datei fertig geschrieben', 'Wait until the file has finished writing'], ['Verhalten', 'Behavior'], ['Aktiviert', 'Enabled'], ['Unterordner einbeziehen', 'Include subfolders'], ['Duplikate überspringen', 'Skip duplicates'], ['Auto-Upload starten', 'Start uploads automatically'], ['Hoster-Vorauswahl', 'Host preselection'], ['Erst Accounts anlegen, dann hier auswählen.', 'Add accounts first, then select them here.'], ['Keine Auswahl = Hoster-Modal bei jeder Datei.', 'No selection = show the host dialog for every file.'], ['Meldungen nach einem abgeschlossenen Upload-Batch versenden.', 'Send notifications after a completed upload batch.'], ['Webhook-Adresse', 'Webhook URL'], ['Test senden', 'Send test'], ['Nach Batch-Ende wird eine Zusammenfassung versendet. Discord wird automatisch erkannt, andere Ziele erhalten JSON.', 'A summary is sent after the batch ends. Discord is detected automatically; other destinations receive JSON.'], ['Discord-Erwähnung', 'Discord mention'], ['Optional · leer lassen, wenn die Nachricht ohne Ping gesendet werden soll', 'Optional · leave blank to send the message without a ping'], ['Protokollierung verwalten, Log-Dateien öffnen und ein bereinigtes Support-Paket erstellen.', 'Manage logging, open log files, and create a sanitized support package.'], ['Ordner wählen', 'Choose folder'], ['Öffnen', 'Open'], ['Log-Datei-Modus', 'Log file mode'], ['Eine Datei', 'Single file'], ['Pro Tag', 'Per day'], ['Pro Session', 'Per session'], ['Pro Session = neue Datei bei jedem App-Start; nach komplettem Schließen + erneutem Öffnen beginnt eine neue Session.', 'Per session = a new file on every application start; a new session begins after fully closing and reopening the application.'], ['DEBUG-Einträge in debug.log schreiben (Performance ↓, Diagnostik ↑)', 'Write DEBUG entries to debug.log (performance ↓, diagnostics ↑)'], ['Diagnose', 'Diagnostics'], ['Log-Dateien', 'Log files'], ['Wird geladen…', 'Loading…'], ['Zeigen', 'Show'], ['Im Explorer zeigen', 'Show in File Explorer'], ['Support-Paket', 'Support package'], ['Eine .txt mit Logs + sanitierter Config; Passwörter/API-Keys werden vor dem Speichern maskiert.', 'A .txt containing logs and sanitized configuration; passwords and API keys are masked before saving.'], ['Upload-Funktionen über einen verbundenen Client steuern.', 'Control upload features through a connected client.'], ['Server', 'Server'], ['Eingaben erlauben', 'Allow input'], ['Kopieren', 'Copy'], ['Neu', 'New'], ['Prüfe...', 'Checking...'], ['Prüfe…', 'Checking…'], ['Zeitlich kontrollierter Lesezugriff für Fehleranalyse und Support.', 'Time-limited read access for troubleshooting and support.'], ['Diagnose-Zugriff (nur lesen)', 'Diagnostics access (read-only)'], ['Zugriff auf Logs, Queue-Status und bereinigte Einstellungen. Passwörter, API-Keys und Tokens werden maskiert.', 'Access to logs, queue status, and sanitized settings. Passwords, API keys, and tokens are masked.'], ['Der Verbindungs-Code ist ein Zugangsschlüssel — nur mit vertrauenswürdigen Stellen teilen; bei Verdacht „Neu" klicken. Standard-Bindung ist', 'The connection code is an access key. Share it only with trusted parties and click “New” if you suspect misuse. The default binding is'], ['und damit nur über einen SSH- oder VPN-Tunnel erreichbar.', 'and is therefore reachable only through an SSH or VPN tunnel.'], ['Im Netzwerk (0.0.0.0) — Allowlist nötig', 'On the network (0.0.0.0) — allowlist required'], ['Adresse für den Code', 'Address for the code'], ['Verbindungs-Code', 'Connection code'], ['. Fernzugriff nur über einen Tunnel (z.B. Tailscale/SSH) — die sicherste Variante.', '. Remote access is available only through a tunnel such as Tailscale or SSH, which is the safest option.'], ['Accounts und Einstellungen sichern oder auf ein anderes Gerät übernehmen.', 'Back up accounts and settings or transfer them to another device.'], ['Der Upload-Verlauf wird nicht übertragen und bleibt auf diesem Gerät.', 'Upload history is not transferred and remains on this device.'], ['Verschlüsseltes Online-Backup', 'Encrypted online backup'], ['Die Verschlüsselung findet ausschließlich auf diesem Gerät statt. Der Server speichert nur verschlüsselte Daten.', 'Encryption takes place only on this device. The server stores encrypted data only.'], ['Neuen Schlüssel erzeugen', 'Generate new key'], ['Jeder Export erzeugt einen neuen Schlüssel. Ältere Schlüssel bleiben gültig.', 'Each export creates a new key. Older keys remain valid.'], ['Dein neuer Schlüssel', 'Your new key'], ['Vorhandenen Schlüssel importieren', 'Import existing key'], ['Online importieren', 'Import online'], ['Behandle den Schlüssel wie ein Passwort. Wer ihn besitzt, kann die verschlüsselten Einstellungen entschlüsseln.', 'Treat the key like a password. Anyone who has it can decrypt the encrypted settings.'], ['Lokales Datei-Backup', 'Local file backup'], ['Datei exportieren', 'Export file'], ['Datei importieren', 'Import file'], ['Alle Uploads', 'All uploads'], ['Erfolgreich', 'Successful'], ['Aktive Regel', 'Active rule'], ['Alles behalten', 'Keep everything'], ['Links wiederfinden, kopieren oder als Datei exportieren.', 'Find links, copy them, or export them as a file.'], ['Upload-Verlauf', 'Upload history'], ['Verlauf exportieren', 'Export history'], ['Verlauf löschen', 'Delete history'], ['Verlauf löschen?', 'Delete history?'], ['Alle Verlaufseinträge werden dauerhaft gelöscht. Dieser Vorgang kann nicht rückgängig gemacht werden.', 'All history entries will be permanently deleted. This action cannot be undone.'], ['Ausgewählte starten', 'Start selected'], ['Upload-Ziele auswählen', 'Choose upload destinations'], ['Dateien wurden hinzugefügt. Wähle jetzt die Hoster für den Upload.', 'Files were added. Now choose the hosts for the upload.'], ['Alle', 'All'], ['Keine', 'None'], ['Keine Hoster mit Zugangsdaten vorhanden. Bitte zuerst in den Accounts einen Login oder API-Key hinterlegen.', 'No hosts with credentials are available. Add a login or API key under Accounts first.'], ['Keine Hoster mit Zugangsdaten für einen Check.', 'No hosts with credentials are available for a check.'], ['Die Auswahl wird für neue Queue-Einträge verwendet.', 'The selection is used for new queue entries.'], ['Nach Aktualisierungen suchen', 'Check for updates'], ['Anwendungsmenüs', 'Application menus'], ['Parallele Uploads erhöhen', 'Increase parallel uploads'], ['Geschwindigkeitslimit aktivieren', 'Enable speed limit'], ['Geschwindigkeitslimit in Megabyte pro Sekunde', 'Speed limit in megabytes per second'], ['Geschwindigkeitslimit erhöhen', 'Increase speed limit'], ['Geschwindigkeitslimit verringern', 'Decrease speed limit'], ['Hilfe und Support', 'Help and support'], ['Update-Fortschritt', 'Update progress'], ['Alle Dateien anzeigen', 'Show all files'], ['Aktive Uploads anzeigen', 'Show active uploads'], ['Wartende Uploads anzeigen', 'Show queued uploads'], ['Fertige Uploads anzeigen', 'Show completed uploads'], ['Fehlgeschlagene Uploads anzeigen', 'Show failed uploads'], ['Alle Uploads starten', 'Start all uploads'], ['Ausgewählte Uploads starten', 'Start selected uploads'], ['Ausgewählte Datei erneut hochladen', 'Upload selected file again'], ['Ausgewählten Upload abbrechen', 'Cancel selected upload'], ['Aktive Uploads beenden und stoppen', 'Stop active uploads'], ['Alle Uploads abbrechen', 'Cancel all uploads'], ['Nach oben', 'Move up'], ['Nach unten', 'Move down'], ['Alle Zeilen als Datei exportieren (Zeit, Hoster, Link, Dateiname)', 'Export all rows as a file (time, host, link, file name)'], ['Alle Links aus diesem Panel entfernen', 'Remove all links from this panel'], ['Alle Accounts anzeigen', 'Show all accounts'], ['Bereite Accounts anzeigen', 'Show ready accounts'], ['Fehlerhafte Accounts anzeigen', 'Show accounts with errors'], ['Einstellungen durchsuchen', 'Search settings'], ['Ordner wählen...', 'Choose folder...'], ['Standardpfad verwenden', 'Use default path'], ['Log-Ordner im Explorer öffnen', 'Open log folder in File Explorer'], ['Sammelt alle Logs + sanitierte Config (Credentials maskiert) + App-Versionen in eine einzelne .txt-Datei zum Teilen.', 'Collects all logs, sanitized configuration with masked credentials, and application versions in a single shareable .txt file.'], ['Neu generieren', 'Generate new'], ['Neu generieren (macht alte Codes ungültig)', 'Generate new (invalidates old codes)'], ['Nach dem Export erscheint hier der 75-stellige Schlüssel', 'The 75-character key appears here after export'], ['Verlaufsübersicht', 'History overview'], ['Verlaufsstatus', 'History status'], ['Gesamten Verlauf anzeigen', 'Show all history'], ['Erfolgreiche Uploads anzeigen', 'Show successful uploads'], ['Fehlgeschlagene Uploads anzeigen', 'Show failed uploads'], ['Gespeichert!', 'Saved!'], ['Speichert…', 'Saving…'], ['Changelog', 'Changelog'], ['— bitte Diagnose-Paket exportieren oder Programm neu starten.', '— please export a diagnostics package or restart the application.'], ['• Bereit', '• Ready'], ['• Fehler', '• Failed'], ['', ''], ['Noch keine Uploads.', 'No uploads yet.'], ['Pfade nicht verfügbar.', 'Paths unavailable.'], ['Noch keine Uploads in dieser Session.', 'No uploads in this session yet.'], ['Account bearbeiten', 'Edit account'], ['Account nicht mehr in der Config — wurde extern gelöscht. Modal schließen und neu anlegen.', 'The account is no longer in the configuration because it was deleted externally. Close the dialog and add it again.'], ['Account wurde erfolgreich geprüft und gespeichert.', 'Account verified and saved successfully.'], ['Account wurde mit Warnung geprüft und gespeichert.', 'Account verified and saved with a warning.'], ['Account-Check läuft bereits.', 'An account check is already running.'], ['Account-Löschung konnte nicht persistiert werden — bitte erneut versuchen.', 'The account deletion could not be saved. Please try again.'], ['Account-Übersicht', 'Account overview'], ['Account wurde diese Session als fehlerhaft markiert. Klick = Wieder als aktiv markieren.', 'The account was marked as failed for this session. Click to reactivate it.'], ['Pausiert (Session)', 'Paused (session)'], ['Wieder aktivieren', 'Reactivate'], ['Accounts mit Handlungsbedarf anzeigen', 'Show accounts requiring action'], ['Alle Accounts und Einstellungen wurden übernommen.', 'All accounts and settings were applied.'], ['Anwendung neu starten?', 'Restart application?'], ['API-Key anzeigen', 'Show API key'], ['Automatisch gespeichert', 'Saved automatically'], ['Beenden', 'Quit'], ['Bekanntes Größen-Limit', 'Known size limit'], ['Backup nicht entschlüsselbar', 'Backup could not be decrypted'], ['Bitte mindestens einen Hoster auswählen.', 'Select at least one host.'], ['CSRF token nicht gefunden', 'CSRF token not found'], ['Deaktiviert', 'Disabled'], ['Der Schlüssel muss exakt 75 Zeichen lang sein.', 'The key must be exactly 75 characters long.'], ['Der Schlüssel muss mit MHU2- beginnen und exakt 75 Zeichen lang sein.', 'The key must start with MHU2- and be exactly 75 characters long.'], ['Diagnose-Paket wird erstellt…', 'Creating diagnostics package…'], ['Die Anwendung konnte nach dem fehlgeschlagenen Speichern nicht entsperrt werden', 'The application could not be unlocked after saving failed'], ['Die Anwendung wird gerade beendet', 'The application is shutting down'], ['Download wird geprüft…', 'Verifying download…'], ['Download wird vorbereitet…', 'Preparing download…'], ['Ein Einstellungsimport läuft bereits', 'A settings import is already running'], ['Einstellungen konnten vor dem Beenden nicht gespeichert werden', 'Settings could not be saved before quitting'], ['Einstellungen werden gerade importiert', 'Settings are being imported'], ['Einstellungen werden gespeichert…', 'Saving settings…'], ['Einstellungen wurden durch einen Import ersetzt', 'Settings were replaced by an import'], ['Ganz nach oben', 'Move to top'], ['Ganz nach unten', 'Move to bottom'], ['Hoster entfernen ▸', 'Remove host ▸'], ['Kein gültiger Account', 'No valid account'], ['Kein Update verfügbar', 'No update available'], ['Kein Upload aktiv', 'No active upload'], ['Kein Verlauf zum Exportieren vorhanden.', 'There is no history to export.'], ['Keine Antwort vom Hoster erhalten', 'No response received from the host'], ['Keine Einträge im Log gefunden', 'No log entries found'], ['Keine Einträge zum Exportieren.', 'No entries to export.'], ['Keine Jobs hinzugefuegt', 'No jobs added'], ['Keine Log-Einträge für diesen Job (entweder noch nichts passiert oder aus vorherigem Batch und schon geräumt).', 'No log entries for this job. Nothing has happened yet, or entries from a previous batch were already cleared.'], ['Keine passenden Jobs für Retry gefunden.', 'No matching jobs found for retry.'], ['Keine startbaren Jobs ausgewählt (alle laufen schon oder sind fertig).', 'No startable jobs selected because all are already running or completed.'], ['Keine transienten Fehler', 'No transient errors'], ['Keine URL eingetragen.', 'No URL entered.'], ['Keine Zugangsdaten', 'No credentials'], ['Lade und entschlüssele Einstellungen…', 'Loading and decrypting settings…'], ['Link kopieren', 'Copy link'], ['Links kopieren', 'Copy links'], ['Log anzeigen', 'Show log'], ['Log importieren', 'Import log'], ['Log importieren — bereits hochgeladene aus Queue entfernen', 'Import log — remove already uploaded jobs from queue'], ['Log-Datei', 'Log file'], ['MB/s · 0 = unbegrenzt', 'MB/s · 0 = unlimited'], ['Log-Pfad automatisch auf funktionierenden Ordner gesetzt', 'Log path automatically changed to a writable folder'], ['Neuer Schlüssel erstellt. Ältere Schlüssel bleiben gültig.', 'New key created. Older keys remain valid.'], ['Nicht alle Einstellungen konnten gespeichert werden', 'Not all settings could be saved'], ['Online-Schlüssel erstellt', 'Online key created'], ['Online-Schlüssel kopiert', 'Online key copied'], ['Online-Sicherung konnte nicht erstellt werden', 'Online backup could not be created'], ['Online-Sicherung konnte nicht importiert werden', 'Online backup could not be imported'], ['OTP wird geprüft…', 'Checking OTP…'], ['OTP-Prüfung fehlgeschlagen', 'OTP check failed'], ['Passwort anzeigen', 'Show password'], ['Prüfe Zugangsdaten…', 'Checking credentials…'], ['Prüfen…', 'Checking…'], ['Prüfung fehlgeschlagen', 'Check failed'], ['Prüfung oder Speichern fehlgeschlagen', 'Check or save failed'], ['Speichere aktuelle Einstellungen…', 'Saving current settings…'], ['Speichern vor dem Beenden hat zu lange gedauert', 'Saving before quitting took too long'], ['Stoppt nach aktiven Uploads...', 'Stopping after active uploads...'], ['Suche nach Aktualisierungen…', 'Checking for updates…'], ['Suche nach Updates…', 'Checking for updates…'], ['System wird heruntergefahren in', 'System will shut down in'], ['Übernehmen', 'Apply'], ['Übersprungen', 'Skipped'], ['Ungespeicherte Änderungen', 'Unsaved changes'], ['Update installiert. Die Anwendung startet neu…', 'Update installed. The application is restarting…'], ['Update konnte nicht gestartet werden', 'Update could not be started'], ['Update verfügbar', 'Update available'], ['Update ist bereit. Einstellungen werden gespeichert…', 'The update is ready. Saving settings…'], ['Update wird installiert. Die Anwendung startet neu…', 'Installing update. The application is restarting…'], ['Updateprüfung fehlgeschlagen', 'Update check failed'], ['Upload läuft...', 'Uploading...'], ['Upload-Log', 'Upload log'], ['Upload-Status', 'Upload status'], ['Upload-Übersicht', 'Upload overview'], ['Verlauf als CSV exportieren?\n\nOK = CSV\nAbbrechen = JSON', 'Export history as CSV?\n\nOK = CSV\nCancel = JSON'], ['Verlauf wirklich löschen?', 'Are you sure you want to delete the history?'], ['Verschlüssele und speichere Einstellungen…', 'Encrypting and saving settings…'], ['Zeit', 'Time'], ['Wenn das Backup mit der alten Passwort-Option (vor v3.0) erstellt wurde, hier eingeben.', 'If the backup was created with the legacy password option before v3.0, enter it here.'], ['Verlauf', 'History'] ]; const deToEn = new Map(pairs); const enToDe = new Map(pairs.map(([de, en]) => [en, de])); function normalizeLanguage(value) { return value === 'de' ? 'de' : 'en'; } function translateText(value, language) { const text = String(value ?? ''); const target = normalizeLanguage(language); const leading = text.match(/^\s*/)?.[0] || ''; const trailing = text.match(/\s*$/)?.[0] || ''; const core = text.slice(leading.length, text.length - trailing.length); const exact = target === 'en' ? deToEn.get(core) : enToDe.get(core); if (exact) return `${leading}${exact}${trailing}`; const patterns = target === 'en' ? [ [/^Update v(.+) verfügbar$/, 'Update v$1 available'], [/^Aktives Ziel: (.+)$/, 'Active destination: $1'], [/^(\d+) Fehler$/, '$1 errors'], [/^Gesamt (\d+)$/, 'Total $1'], [/^Verbindungen (\d+)$/, 'Connections $1'], [/^Verbleibend (\d+)$/, 'Remaining $1'], [/^(\d+) deaktiviert$/, '$1 disabled'], [/^(.+) verbergen$/, 'Hide $1'], [/^(.+) anzeigen$/, 'Show $1'], [/^(.+) Account wieder aktiv — nächste Batch verwendet ihn$/, '$1 account reactivated — the next batch will use it'], [/^(.+): Alle Accounts ausgeschöpft$/, '$1: all accounts exhausted'], [/^(.+): Keine weiteren Fallback-Accounts verfügbar$/, '$1: no additional fallback accounts available'], [/^(\d+) Ziele aktiv: (.+)$/, '$1 destinations active: $2'], [/^(\d+) Job\(s\) zum erneuten Upload zurückgesetzt$/, '$1 job(s) reset for upload'], [/^(\d+) bereits hochgeladene Jobs aus Queue entfernt \((\d+) Log-Einträge gelesen\)$/, '$1 already uploaded jobs removed from the queue ($2 log entries read)'], [/^(\d+) Einträge exportiert$/, '$1 entries exported'], [/^(\d+) Verlaufseinträge werden dauerhaft entfernt\.\n\nFortfahren\?$/, '$1 history entries will be permanently removed.\n\nContinue?'], [/^Account "(.+)" wirklich löschen\?$/, 'Are you sure you want to delete account "$1"?'], [/^Aktiv auf (.+) \((.+)\) — (\d+) Client\(s\) — Letzter Zugriff: (.+)$/, 'Active at $1 ($2) — $3 client(s) — Last access: $4'], [/^Aktiv auf Port (\d+) — (\d+) Client\(s\) verbunden$/, 'Active on port $1 — $2 client(s) connected'], [/^Alle Fehler erneut versuchen \((\d+)\)$/, 'Retry all failed uploads ($1)'], [/^API: (.+)$/, 'API: $1'], [/^Ausgewählte starten \((\d+)\)$/, 'Start selected ($1)'], [/^Auto-Retry Runde (\d+)\/(\d+): (\d+) transiente Fehler werden in (.+) min neu versucht\.$/, 'Auto-retry round $1/$2: $3 transient errors will be retried in $4 min.'], [/^Backup importiert\. Bitte prüfen: (.+)\.$/, 'Backup imported. Please review: $1.'], [/^Code erstellt: (.+)$/, 'Code created: $1'], [/^Diagnose-Paket gespeichert \((.+) KB\)$/, 'Diagnostics package saved ($1 KB)'], [/^Einstellungen übernommen\. Bitte prüfen: (.+)\.$/, 'Settings applied. Please review: $1.'], [/^Entfernen \((\d+)\)$/, 'Remove ($1)'], [/^Fehler (\d+)$/, 'Failed $1'], [/^Fehler: (.+)$/, 'Error: $1'], [/^Fertig (\d+)$/, 'Completed $1'], [/^Fertig:$/, 'Completed:'], [/^Gespeichert: (.+) \((.+) KB\)$/, 'Saved: $1 ($2 KB)'], [/^Import übernommen\. Warteschlange konnte nicht vollständig gespeichert werden: (.+)$/, 'Import applied. The queue could not be saved completely: $1'], [/^Jobs konnten nicht hinzugefuegt werden: (.+)$/, 'Jobs could not be added: $1'], [/^Links kopieren \((\d+)\)$/, 'Copy links ($1)'], [/^Log-Pfad nicht beschreibbar — schreibe nach: (.+)$/, 'Log path is not writable — writing to: $1'], [/^Login: (.+)$/, 'Login: $1'], [/^Speichern fehlgeschlagen: (.+)$/, 'Saving failed: $1'], [/^Test erfolgreich gesendet \(HTTP (\d+)\)\.$/, 'Test sent successfully (HTTP $1).'], [/^Übersprungen: (.+)$/, 'Skipped: $1'], [/^Update fehlgeschlagen: (.+)$/, 'Update failed: $1'], [/^Update wird heruntergeladen… (\d+)%$/, 'Downloading update… $1%'], [/^Verlauf exportiert \((\d+) Zeilen\)$/, 'History exported ($1 rows)'], [/^Verlauf gekürzt: (\d+) entfernt$/, 'History trimmed: $1 removed'], [/^Zeige neueste (.+) von (.+) Einträgen\. Der vollständige Verlauf bleibt gespeichert und ist über „Verlauf exportieren“ verfügbar\.$/, 'Showing the newest $1 of $2 entries. The complete history remains saved and is available through “Export history”.'], [/^Wirklich alle (\d+) Links aus diesem Panel entfernen\?$/, 'Remove all $1 links from this panel?'], [/^Zugangsdaten für (.+) bearbeiten und prüfen\.$/, 'Edit and verify credentials for $1.'], [/^Läuft (\d+)$/, 'Running $1'], [/^Fehler (\d+)$/, 'Failed $1'], [/^Update v(.+) verfügbar\. Klicken zum Installieren\.$/, 'Update v$1 available. Click to install.'] ] : [ [/^Update v(.+) available$/, 'Update v$1 verfügbar'], [/^Active destination: (.+)$/, 'Aktives Ziel: $1'], [/^Running (\d+)$/, 'Läuft $1'], [/^Failed (\d+)$/, 'Fehler $1'], [/^Update v(.+) available\. Click to install\.$/, 'Update v$1 verfügbar. Klicken zum Installieren.'] ]; for (const [pattern, replacement] of patterns) { if (pattern.test(core)) return `${leading}${core.replace(pattern, replacement)}${trailing}`; } return text; } function createDomLocalizer(documentRef) { const textSources = new WeakMap(); const textRendered = new WeakMap(); const attributeSources = new WeakMap(); const attributes = ['aria-label', 'placeholder', 'title', 'data-tooltip']; let language = 'en'; let observer = null; function renderTextNode(node) { const current = node.nodeValue || ''; if (!textSources.has(node) || current !== textRendered.get(node)) textSources.set(node, current); const source = textSources.get(node); const rendered = language === 'de' ? source : translateText(source, language); textRendered.set(node, rendered); if (current !== rendered) node.nodeValue = rendered; } function renderAttributes(element) { let sources = attributeSources.get(element); if (!sources) { sources = new Map(); attributeSources.set(element, sources); } for (const name of attributes) { if (!element.hasAttribute(name)) continue; const current = element.getAttribute(name) || ''; const known = sources.get(name); if (!known || current !== known.rendered) sources.set(name, { source: current, rendered: current }); const entry = sources.get(name); const rendered = language === 'de' ? entry.source : translateText(entry.source, language); entry.rendered = rendered; if (current !== rendered) element.setAttribute(name, rendered); } } function renderNode(node) { if (!node) return; if (node.nodeType === 3) { renderTextNode(node); return; } if (node.nodeType !== 1 && node.nodeType !== 9 && node.nodeType !== 11) return; if (node.nodeType === 1) renderAttributes(node); const walker = documentRef.createTreeWalker(node, 5); let current = walker.nextNode(); while (current) { if (current.nodeType === 3) renderTextNode(current); else renderAttributes(current); current = walker.nextNode(); } } function setLanguage(value) { language = normalizeLanguage(value); documentRef.documentElement.lang = language; renderNode(documentRef.body || documentRef.documentElement); return language; } function start(value = 'en') { setLanguage(value); if (!observer && documentRef.defaultView?.MutationObserver) { observer = new documentRef.defaultView.MutationObserver(records => { for (const record of records) { if (record.type === 'characterData') renderTextNode(record.target); else if (record.type === 'attributes') renderAttributes(record.target); else record.addedNodes.forEach(renderNode); } }); observer.observe(documentRef.documentElement, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: attributes }); } return language; } return { start, setLanguage, translate: renderNode, getLanguage: () => language }; } return { normalizeLanguage, translateText, createDomLocalizer }; });