Some checks failed
CD / Build and push images (push) Successful in 4m5s
CD / Deploy to Test (push) Successful in 9s
CI / Lint, typecheck, test (push) Failing after 4m21s
CI / Auth e2e pack (push) Has been skipped
CI / Import/export fidelity gate (push) Has been skipped
CI / Build container images (push) Has been skipped
CD / Smoke tests against Test (push) Successful in 1m22s
CD / Promote to Int (push) Successful in 11s
POST /ponds/:pondId/import/vault (pond-admin-gated; a vault import
creates a subtree, uploads files, and creates labels — administration,
not everyday editing) takes the ZIP plus a JSON options field
{parentPageId?, labelIds?, frontmatterMode}. The archive is parsed at
enqueue for fast 400s; the job (new kind import_vault, riding the
existing isImportKind worker routing) re-parses and runs the #116
transform, then: containers top-down → notes (asset placeholders →
uploaded pond files; non-images become page attachments) → tags to
labels (nested tags build a label hierarchy via LabelsService, so
locking and cache invalidation apply) plus the dialog labels.
All-or-nothing: any failure hard-deletes the created pages (children
first) and removes the stored files (quota restored), then surfaces as
import_vault_invalid_zip / import_vault_too_large / quota_exceeded /
conversion_failed — and makes the worker's retry policy safe.
Supporting changes:
- conversion_jobs gains a nullable options jsonb column; enqueue takes
kind-specific options and a maxInputBytes override (the 25 MiB
default protects the pandoc sidecar, which a vault never touches —
vaults use the 64 MiB upload limit).
- insertPage accepts a pre-reserved slug (the batch reserves all slugs
up front against pond ∪ batch).
- NEW: pages born with content seed their outgoing page_links rows
(deriveContent now returns wikilinkSlugs) — imported pages would
otherwise stay invisible to backlinks and the graph until their
first collab save. Collab still rewrites the rows on every save, and
the existing phantom resolution heals batch creation order.
import-vault.e2e.db.test.ts (4 tests, real worker drained): gating +
input rejection, the full fixture import (tree under a mount page,
collision suffixes, link rows incl. phantom, nested tag labels, extra
label everywhere, frontmatter stripped, image embedded + PDF attached),
complete quota rollback, and a clean re-import with fresh suffixes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
112 lines
7.8 KiB
JSON
112 lines
7.8 KiB
JSON
{
|
|
"bad_request": "Die Anfrage ist ungültig.",
|
|
"unauthorized": "Bitte melde dich an, um fortzufahren.",
|
|
"forbidden": "Dir fehlt die Berechtigung für diese Aktion.",
|
|
"not_found": "Die angeforderte Ressource existiert nicht.",
|
|
"conflict": "Die Anfrage steht im Widerspruch zum aktuellen Zustand.",
|
|
"gone": "Diese Ressource ist nicht mehr verfügbar.",
|
|
"payload_too_large": "Die übermittelten Daten sind zu groß.",
|
|
"rate_limited": "Zu viele Anfragen — bitte versuche es später erneut.",
|
|
"internal_error": "Interner Serverfehler.",
|
|
"registration_closed": "Die Registrierung ist auf dieser Instanz derzeit geschlossen.",
|
|
"token_invalid": "Dieser Link ist ungültig oder abgelaufen.",
|
|
"login_failed": "Benutzername/E-Mail oder Passwort ist falsch.",
|
|
"login_backoff": "Zu viele Fehlversuche — bitte warte ein paar Minuten.",
|
|
"email_unverified": "Bitte bestätige zuerst deine E-Mail-Adresse.",
|
|
"account_disabled": "Dieses Konto wurde deaktiviert.",
|
|
"password_incorrect": "Das aktuelle Passwort ist falsch.",
|
|
"csrf_origin_mismatch": "Die Anfrage kam von einer unerwarteten Herkunft.",
|
|
"cannot_revoke_current_session": "Beende deine aktuelle Sitzung über die Abmeldung.",
|
|
"personal_pond_undeletable": "Der persönliche Teich kann nicht gelöscht werden.",
|
|
"quota_exceeded": "Das Kontingent ist erreicht (Limit: {{limit}}).",
|
|
"slug_taken": "Dieser Adressname ist in diesem Teich bereits vergeben.",
|
|
"page_document_too_large": "Die Seite ist zu groß (Limit: {{limitBytes}} Bytes).",
|
|
"invalid_page_state": "Der übermittelte Seiteninhalt ist ungültig.",
|
|
"page_trashed": "Diese Seite wurde in den Papierkorb verschoben.",
|
|
"page_cycle": "Eine Seite kann nicht in ihren eigenen Teilbaum verschoben werden.",
|
|
"page_depth_exceeded": "Seiten lassen sich höchstens {{max}} Ebenen tief verschachteln.",
|
|
"label_name_taken": "Ein Label mit diesem Namen existiert auf dieser Ebene bereits.",
|
|
"label_cycle": "Ein Label kann nicht in seinen eigenen Teilbaum verschoben werden.",
|
|
"label_depth_exceeded": "Labels lassen sich höchstens {{max}} Ebenen tief verschachteln.",
|
|
"label_has_pages": "Diesem Label sind noch Seiten zugeordnet; bitte bestätigen, um sie zu lösen.",
|
|
"label_wrong_pond": "Dieses Label gehört zu einem anderen Teich.",
|
|
"unsupported_file_type": "Dieser Dateityp wird nicht unterstützt.",
|
|
"upload_type_not_allowed": "Dieser Dateityp ist auf dieser Instanz nicht erlaubt.",
|
|
"file_too_large": "Die Datei ist zu groß (Limit: {{limitBytes}} Bytes).",
|
|
"converter_unavailable": "Der Dokument-Konverter ist derzeit nicht verfügbar. Bitte versuche es später erneut.",
|
|
"converter_timeout": "Die Konvertierung hat zu lange gedauert und wurde abgebrochen.",
|
|
"conversion_failed": "Dieses Dokument konnte nicht konvertiert werden.",
|
|
"renderer_unavailable": "Der PDF-Renderer ist derzeit nicht verfügbar. Bitte versuche es später erneut.",
|
|
"render_failed": "Diese Seite konnte nicht als PDF gerendert werden.",
|
|
"import_unsupported_format": "Nur Word- (.docx) und OpenDocument-Dokumente (.odt) können importiert werden.",
|
|
"import_vault_invalid_zip": "Das Archiv ist kein gültiger Obsidian-Vault (ZIP mit Markdown-Notizen).",
|
|
"import_vault_too_large": "Der entpackte Vault ist zu groß für einen Import.",
|
|
"network": "Der Server war nicht erreichbar.",
|
|
"grant_exists": "Diese Berechtigung existiert bereits.",
|
|
"plugin_invalid_zip": "Die hochgeladene Datei ist kein gültiges ZIP-Archiv.",
|
|
"plugin_bad_structure": "Das Plugin-Paket hat eine ungültige Struktur.",
|
|
"plugin_invalid_manifest": "Das Plugin-Manifest ist ungültig.",
|
|
"plugin_api_incompatible": "Dieses Plugin benötigt eine nicht unterstützte Plugin-API-Version.",
|
|
"plugin_too_large": "Das Plugin-Paket ist zu groß (Limit: {{limitBytes}} Bytes).",
|
|
"plugin_missing_bundle": "Ein Code-Plugin muss ein plugin.js-Bundle enthalten.",
|
|
"plugin_missing_styles": "Ein Style-Plugin muss eine styles.css-Datei enthalten.",
|
|
"plugin_css_unsafe": "Das Plugin-Stylesheet verwendet nicht erlaubte Konstrukte.",
|
|
"plugin_version_not_higher": "Ein Update muss eine höhere Version als das installierte haben.",
|
|
"plugin_required_cannot_uninstall": "Ein erforderliches Plugin kann nicht deinstalliert werden.",
|
|
"plugin_not_found": "Dieses Plugin ist nicht installiert.",
|
|
"plugin_not_optional": "Nur optionale Plugins können pro Teich aktiviert werden.",
|
|
"grant_pond_admin_scope": "Eine Teich-Admin-Berechtigung muss für den ganzen Teich und eine bestimmte Person gelten.",
|
|
"grant_pond_admin_personal_pond": "Der einzige Administrator eines persönlichen Teichs ist dessen Eigentümer.",
|
|
"grant_subject_id_mismatch": "Das Subjekt der Berechtigung ist widersprüchlich.",
|
|
"grant_scope_id_mismatch": "Der Geltungsbereich der Berechtigung ist widersprüchlich.",
|
|
"grant_scope_not_found": "Das Label oder die Seite, auf die sich diese Berechtigung bezieht, existiert in diesem Teich nicht.",
|
|
"grant_subject_not_found": "Diese Person existiert nicht.",
|
|
"grant_last_admin": "Die letzte Teich-Admin-Berechtigung kann nicht entfernt werden.",
|
|
"member_not_found": "Es existiert keine Person mit diesem Benutzernamen oder dieser E-Mail.",
|
|
"member_exists": "Diese Person ist bereits Mitglied dieses Teichs.",
|
|
"member_not_a_member": "Diese Person ist kein Mitglied dieses Teichs.",
|
|
"member_is_owner": "Die Mitgliedschaft des Teich-Eigentümers kann hier nicht geändert werden.",
|
|
"cannot_modify_self": "Du kannst diese Aktion nicht auf dein eigenes Konto anwenden.",
|
|
"last_site_admin": "Der letzte Site-Admin kann nicht entfernt werden.",
|
|
"setup_required": "Diese Instanz ist noch nicht eingerichtet. Bitte führe zuerst die Ersteinrichtung aus.",
|
|
"setup_locked": "Die Ersteinrichtung ist bereits abgeschlossen.",
|
|
"setup_admin_exists": "Es existiert bereits ein Site-Admin-Konto.",
|
|
"setup_admin_missing": "Lege zuerst das Site-Admin-Konto an.",
|
|
"smtp_test_failed": "Der SMTP-Test ist fehlgeschlagen. Bitte prüfe die Verbindungsdaten.",
|
|
"validation": {
|
|
"required": "Dieses Feld ist erforderlich.",
|
|
"taken": "Dieser Wert ist bereits vergeben.",
|
|
"username": {
|
|
"tooShort": "Der Benutzername braucht mindestens 3 Zeichen.",
|
|
"tooLong": "Der Benutzername darf höchstens 32 Zeichen haben.",
|
|
"charset": "Erlaubt sind nur Buchstaben, Ziffern und Bindestriche."
|
|
},
|
|
"password": {
|
|
"tooShort": "Das Passwort braucht mindestens 10 Zeichen.",
|
|
"tooLong": "Das Passwort darf höchstens 128 Zeichen haben.",
|
|
"tooCommon": "Dieses Passwort ist zu verbreitet."
|
|
},
|
|
"email": {
|
|
"invalid": "Bitte gib eine gültige E-Mail-Adresse ein."
|
|
},
|
|
"displayName": {
|
|
"required": "Bitte gib einen Anzeigenamen ein."
|
|
},
|
|
"labelColor": "Bitte gib eine Farbe wie #a1b2c3 ein.",
|
|
"tooLong": "Die Eingabe ist zu lang."
|
|
},
|
|
"comments_editors_only": "Kommentare sind in diesem Teich auf Bearbeitende beschränkt.",
|
|
"comment_not_author": "Nur die Autorin/der Autor kann diesen Kommentar ändern.",
|
|
"comment_has_replies": "Dieser Kommentar hat Antworten — den ganzen Thread kann nur eine Teich-Administration löschen.",
|
|
"comment_parent_invalid": "Antworten müssen sich auf einen Kommentar der obersten Ebene derselben Seite beziehen.",
|
|
"comment_not_root": "Nur Kommentare der obersten Ebene können als erledigt markiert werden.",
|
|
"maintenance_mode": "Die Instanz ist im Wartungsmodus, während ein Backup wiederhergestellt wird.",
|
|
"backup_connection_failed": "Der Nextcloud-Verbindungstest ist fehlgeschlagen.",
|
|
"backup_restore_confirm_mismatch": "Der Bestätigungstext stimmt nicht mit der Backup-ID überein.",
|
|
"backup_restore_running": "Es läuft bereits eine Wiederherstellung.",
|
|
"backup_remote_not_configured": "Es ist kein Nextcloud-Backup-Ziel konfiguriert.",
|
|
"backup_set_not_found": "Das gewählte Backup-Set wurde nicht gefunden.",
|
|
"scope_required": "Dieses API-Token hat nicht den erforderlichen Scope.",
|
|
"pond_not_found": "Der Teich existiert nicht."
|
|
}
|