From a49783da5b033690d873e102c75884cec4b9ea45 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 19 Oct 2021 02:25:40 +0200 Subject: [PATCH 1/3] Translated using Weblate (German) Currently translated at 100.0% (1423 of 1423 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/de/ --- www/common/translations/messages.de.json | 82 +++++++++++++----------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/www/common/translations/messages.de.json b/www/common/translations/messages.de.json index 30bd5a217..317f9dad2 100644 --- a/www/common/translations/messages.de.json +++ b/www/common/translations/messages.de.json @@ -5,7 +5,7 @@ "code": "Code", "poll": "Umfrage", "kanban": "Kanban", - "slide": "Präsentation", + "slide": "Markdown-Folien", "drive": "CryptDrive", "whiteboard": "Whiteboard", "file": "Datei", @@ -383,7 +383,7 @@ "settings_importConfirm": "Bist du sicher, dass du die kürzlich besuchten Dokumente in das CryptDrive deines Accounts importieren möchtest?", "settings_importDone": "Import abgeschlossen", "settings_autostoreTitle": "Speichern von Pads im CryptDrive", - "settings_autostoreHint": "Automatisch: Alle Pads werden in deinem CryptDrive gespeichert.
Manuell (immer nachfragen): Wenn du ein Pad noch nicht gespeichert hast, wirst du gefragt, ob du es im CryptDrive speichern willst.
Manuell (nie nachfragen): Pads werden nicht automatisch im CryptDrive gespeichert. Die Option zum Speichern wird versteckt.", + "settings_autostoreHint": "Automatisch: Alle Dokumente werden in deinem CryptDrive gespeichert.
Manuell (immer nachfragen): Wenn du ein Dokument noch nicht gespeichert hast, wirst du gefragt, ob du es im CryptDrive speichern willst.
Manuell (nie nachfragen): Dokumente werden nicht automatisch im CryptDrive gespeichert. Die Option zum Speichern wird nicht mehr angezeigt.", "settings_autostoreYes": "Automatisch", "settings_autostoreNo": "Manuell (nie nachfragen)", "settings_autostoreMaybe": "Manuell (immer nachfragen)", @@ -567,11 +567,11 @@ "password_submit": "Abschicken", "properties_addPassword": "Passwort hinzufügen", "properties_changePassword": "Passwort ändern", - "properties_confirmNew": "Bist du sicher? Das Hinzufügen eines Passworts wird die URL dieses Pads ändern und den Verlauf löschen. Benutzer ohne das Passwort werden den Zugang zu diesem Pad verlieren", - "properties_confirmChange": "Bist du sicher? Das Ändern des Passworts wird den Verlauf löschen. Benutzer ohne das neue Passwort werden den Zugang zu diesem Pad verlieren", + "properties_confirmNew": "Bist du sicher? Das Hinzufügen eines Passworts wird die URL dieses Dokuments ändern und den Verlauf löschen. Benutzer ohne das Passwort werden den Zugang zu diesem Dokument verlieren", + "properties_confirmChange": "Bist du sicher? Das Ändern des Passworts wird den Verlauf löschen. Benutzer ohne das neue Passwort werden den Zugang zu diesem Dokument verlieren", "properties_passwordSame": "Das neue Passwort muss sich von dem alten Passwort unterscheiden.", "properties_passwordError": "Beim Versuch das Passwort zu ändern ist ein Fehler aufgetreten. Bitte versuche es nochmal.", - "properties_passwordWarning": "Das Passwort wurde erfolgreich geändert, aber dein CryptDrive konnte nicht aktualisiert werden. Du musst möglicherweise die alte Version des Pads manuell entfernen.
Klicke auf OK, um die Seite neu zu laden und die Zugriffsrechte zu aktualisieren.", + "properties_passwordWarning": "Das Passwort wurde erfolgreich geändert, aber dein CryptDrive konnte nicht aktualisiert werden. Du musst möglicherweise die alte Version des Dokuments manuell entfernen.
Klicke auf OK, um die Seite neu zu laden und die Zugriffsrechte zu aktualisieren.", "properties_passwordSuccess": "Das Passwort wurde erfolgreich geändert.
Klicke auf OK, um die Seite neu zu laden und die Zugriffsrechte zu aktualisieren.", "properties_changePasswordButton": "Absenden", "share_linkCategory": "Link", @@ -584,8 +584,8 @@ "share_linkCopy": "Link kopieren", "share_embedCategory": "Einbetten", "share_mediatagCopy": "Media-Tag in die Zwischenablage kopieren", - "sharedFolders_forget": "Dieses Pad ist nur in einem geteilten Ordner gespeichert. Du kannst es nicht in den Papierkorb verschieben. Aber du kannst es in deinem CryptDrive löschen.", - "sharedFolders_duplicate": "Einige zu verschiebende Pads waren schon im Zielordner geteilt.", + "sharedFolders_forget": "Dieses Dokument ist nur in einem geteilten Ordner gespeichert. Du kannst es nicht in den Papierkorb verschieben. Aber du kannst es in deinem CryptDrive löschen.", + "sharedFolders_duplicate": "Einige zu verschiebende Dokumente waren schon im Zielordner geteilt.", "sharedFolders_create": "Erstelle einen geteilten Ordner", "sharedFolders_create_name": "Neuer Ordner", "sharedFolders_create_owned": "Eigener Ordner", @@ -595,13 +595,13 @@ "autostore_sf": "Dieser Ordner", "autostore_pad": "Dieses Dokument", "autostore_notstored": "{0} ist nicht in deinem CryptDrive. Möchtest du es jetzt dort speichern?", - "autostore_settings": "Du kannst die automatische Speicherung in deinen Einstellungen aktivieren!", + "autostore_settings": "Du kannst die automatische Speicherung von Dokumenten in deinen Einstellungen aktivieren.", "autostore_store": "Speichern", "autostore_hide": "Nicht speichern", - "autostore_error": "Unerwarteter Fehler: Wir konnten das Pad nicht speichern, bitte versuche es nochmal.", - "autostore_saved": "Das Pad wurde erfolgreich in deinem CryptDrive gespeichert!", + "autostore_error": "Unerwarteter Fehler: Wir konnten das Dokument nicht speichern, bitte versuche es nochmal.", + "autostore_saved": "Das Dokument wurde erfolgreich in deinem CryptDrive gespeichert!", "autostore_forceSave": "Speichere die Datei in deinem CryptDrive", - "autostore_notAvailable": "Du musst dieses Pad in deinem CryptDrive speichern, bevor du diese Funktion benutzen kannst.", + "autostore_notAvailable": "Du musst dieses Dokument in deinem CryptDrive speichern, bevor du diese Funktion benutzen kannst.", "crowdfunding_button": "Unterstütze CryptPad", "crowdfunding_popup_text": "

Wir brauchen deine Hilfe!

Um sicherzustellen, dass CryptPad weiter aktiv entwickelt wird, unterstütze bitte das Projekt über die OpenCollective Seite, wo du unsere Roadmap und Funding-Ziele lesen kannst.", "crowdfunding_popup_no": "Nicht jetzt", @@ -618,7 +618,7 @@ "adminPage": "Administration", "admin_activeSessionsTitle": "Aktive Verbindungen", "admin_activeSessionsHint": "Anzahl aktiver Websocket-Verbindungen (und verbundener IP-Adressen)", - "admin_activePadsTitle": "Aktive Pads", + "admin_activePadsTitle": "Aktive Dokumente", "admin_activePadsHint": "Anzahl der Dokumente, die gerade angesehen oder bearbeitet werden", "admin_registeredTitle": "Registrierte Nutzer", "admin_registeredHint": "Anzahl der auf deiner Instanz registrierten Nutzer", @@ -651,7 +651,7 @@ "drive_active1Day": "Letzte 24 Stunden", "drive_active7Days": "Letzte 7 Tage", "drive_active28Days": "Letzte 4 Wochen", - "drive_activeOld": "Ältere Pads", + "drive_activeOld": "Ältere Dokumente", "friendRequest_later": "Später entscheiden", "friendRequest_accept": "Akzeptieren (Enter)", "friendRequest_decline": "Ablehnen", @@ -665,7 +665,7 @@ "profile_addLink": "Link zu deiner Website hinzufügen", "profile_info": "Andere Nutzer können dein Profil finden, indem sie auf deinen Avatar in der Benutzerliste eines Dokumentes klicken.", "profile_friendRequestSent": "Kontaktanfrage gesendet...", - "notification_padShared": "{0} hat ein Pad mit dir geteilt: {1}", + "notification_padShared": "{0} hat ein Dokument mit dir geteilt: {1}", "notification_fileShared": "{0} hat eine Datei mit dir geteilt: {1}", "notification_folderShared": "{0} hat einen Ordner mit dir geteilt: {1}", "share_filterFriend": "Nach Namen suchen", @@ -714,11 +714,11 @@ "notifications_dismissAll": "Alle verbergen", "support_notification": "Ein Administrator hat dein Support-Ticket beantwortet", "requestEdit_button": "Bearbeitungsrechte anfragen", - "requestEdit_confirm": "{1} hat Bearbeitungsrechte für das Pad {0} angefragt. Möchtest du die Rechte vergeben?", - "requestEdit_viewPad": "Pad in neuem Tab öffnen", + "requestEdit_confirm": "{1} hat Bearbeitungsrechte für das Dokument {0} angefragt. Möchtest du die Rechte vergeben?", + "requestEdit_viewPad": "Dokument in neuem Tab öffnen", "later": "Später entscheiden", - "requestEdit_request": "{1} möchte das Pad {0} bearbeiten", - "requestEdit_accepted": "{1} hat dir Bearbeitungsrechte für das Pad {0} gegeben", + "requestEdit_request": "{1} möchte das Dokument {0} bearbeiten", + "requestEdit_accepted": "{1} hat dir Bearbeitungsrechte für das Dokument {0} gegeben", "requestEdit_sent": "Anfrage gesendet", "uploadFolderButton": "Ordner hochladen", "properties_unknownUser": "{0} unbekannte(r) Benutzer", @@ -743,7 +743,7 @@ "owner_unknownUser": "unbekannt", "owner_removeConfirm": "Bist du sicher, dass die Eigentümerschaft der ausgewählten Benutzer entfernen möchtest? Sie werden über diese Aktion informiert.", "owner_removeMeConfirm": "Du bist dabei, deine Rechte als Eigentümer aufzugeben. Diese Aktion kannst du nicht rückgängig machen. Bist du sicher?", - "owner_add": "{0} möchte ein Eigentümer des Pads {1} sein. Bist du damit einverstanden?", + "owner_add": "{0} möchte ein Eigentümer des Dokuments {1} sein. Bist du damit einverstanden?", "owner_removeText": "Eigentümer", "owner_removePendingText": "Ausstehend", "owner_addConfirm": "Mit-Eigentümer können den Inhalt bearbeiten und dich als Eigentümer entfernen. Bist du sicher?", @@ -756,7 +756,7 @@ "team_inviteModalButton": "Einladen", "team_pickFriends": "Kontakte auswählen, um sie in dieses Team einzuladen", "team_pcsSelectLabel": "Speichern in", - "team_pcsSelectHelp": "Die Erstellung eines eigenen Pads im Drive deines Teams gibt die Eigentümerschaft an das Team.", + "team_pcsSelectHelp": "Die Erstellung eines eigenen Dokuments im Drive deines Teams gibt die Eigentümerschaft an das Team.", "team_invitedToTeam": "{0} hat dich zum Team eingeladen: {1}", "team_kickedFromTeam": "{0} hat dich aus dem Team entfernt: {1}", "team_acceptInvitation": "{0} hat deine Einladung zum Team akzeptiert: {1}", @@ -810,21 +810,21 @@ "team_viewers": "Betrachter", "drive_sfPassword": "Dein geteilter Ordner {0} ist nicht mehr verfügbar. Entweder wurde er von seinem Eigentümer gelöscht oder er ist nun mit einem neuen Passwort geschützt. Du kannst den Ordner aus deinem CryptDrive entfernen oder den Zugriff durch Eingabe des neuen Passworts wiederherstellen.", "drive_sfPasswordError": "Falsches Passwort", - "password_error_seed": "Pad nicht gefunden!
Dieser Fehler kann zwei Ursachen haben: Entweder wurde ein Passwort gesetzt/geändert oder das Pad wurde vom Server gelöscht.", + "password_error_seed": "Dokument nicht gefunden!
Dieser Fehler kann zwei Ursachen haben: Entweder wurde ein Passwort gesetzt/geändert oder das Dokument wurde vom Server gelöscht.", "properties_confirmChangeFile": "Bist du sicher? Benutzer, die das neue Passwort nicht kennen, werden den Zugriff auf die Datei verlieren.", "properties_confirmNewFile": "Bist du sicher? Durch das Hinzufügen eines Passwortes wird sich der Link für die Datei ändern. Benutzer, die das Passwort nicht kennen, werden den Zugriff auf die Datei verlieren.", "properties_passwordWarningFile": "Das Passwort wurde erfolgreich geändert. Allerdings konnten die Daten in deinem CryptDrive nicht aktualisiert werden. Möglicherweise musst du die alte Version der Datei manuell entfernen.", "properties_passwordSuccessFile": "Das Passwort wurde geändert.", - "driveOfflineError": "Die Verbindung zu CryptPad ist verloren gegangen. Änderungen an diesem Pad werden nicht in deinem CryptDrive gespeichert. Bitte schließe alle CryptPad-Tabs und versuche es in einem neuen Fenster erneut. ", + "driveOfflineError": "Die Verbindung zu CryptPad ist verloren gegangen. Änderungen an diesem Dokument werden nicht in deinem CryptDrive gespeichert. Bitte schließe alle CryptPad-Tabs und versuche es in einem neuen Fenster erneut. ", "storageStatus": "Speicher:
{0} von {1} belegt", "teams_table": "Rollen", "teams_table_generic": "Rollen und Berechtigungen", - "teams_table_generic_view": "Ansehen: Zugriff auf Ordner und Pads (nur Lesen)", - "teams_table_generic_edit": "Bearbeiten: Erstellen, Ändern und Löschen von Ordnern und Pads", + "teams_table_generic_view": "Ansehen: Zugriff auf Ordner und Dokumente (nur Lesen)", + "teams_table_generic_edit": "Bearbeiten: Erstellen, Ändern und Löschen von Ordnern und Dokumenten", "teams_table_generic_admin": "Mitglieder verwalten: Einladen und Entfernen von Mitgliedern, Ändern von Benutzerrollen bis maximal Admin", "teams_table_generic_own": "Team verwalten: Ändern von Namen und Avatar des Teams, Hinzufügen oder Entfernen von Eigentümerschaften des Teams, Löschung des Teams", "teams_table_specific": "Ausnahmen", - "teams_table_specificHint": "Dies sind ältere geteilte Ordner, wo Benutzer noch Bearbeitungsrechte haben. Für hier erstellte oder hierhin kopierte Pads gelten Standard-Berechtigungen.", + "teams_table_specificHint": "Dies sind ältere geteilte Ordner, wo Benutzer noch Bearbeitungsrechte haben. Für hier erstellte oder hierhin kopierte Dokumente gelten Standard-Berechtigungen.", "teams_table_admins": "Mitglieder verwalten", "teams_table_owners": "Team verwalten", "teams_table_role": "Rolle", @@ -833,7 +833,7 @@ "share_linkWarning": "Dieser Link enthält die Schlüssel zu deinem Dokument. Empfänger erhalten unwiderruflichen Zugriff zu deinen Inhalten.", "share_linkPasswordAlert": "Dieses Element ist passwortgeschützt. Wenn du diesen Link teilst, muss der Empfänger das Passwort eingeben.", "share_contactPasswordAlert": "Dieses Element ist passwortgeschützt. Weil du es mit einem CryptPad-Kontakt teilst, muss der Empfänger das Passwort nicht eingeben.", - "share_embedPasswordAlert": "Dieses Element ist passwortgeschützt. Wenn du dieses Pad einbettest, werden Betrachter nach dem Passwort gefragt.", + "share_embedPasswordAlert": "Dieses Element ist passwortgeschützt. Wenn du dieses Dokument einbettest, werden Betrachter nach dem Passwort gefragt.", "passwordFaqLink": "Mehr über Passwörter erfahren", "share_noContactsLoggedIn": "Du hast noch keine Kontakte bei CryptPad. Teile den Link zu deinem Profil, damit andere dir Kontaktanfragen senden können.", "share_copyProfileLink": "Profil-Link kopieren", @@ -866,28 +866,28 @@ "team_inviteInvalidLinkError": "Dieser Einladungslink ist ungültig.", "team_inviteLinkError": "Bei der Erstellung des Links ist ein Fehler aufgetreten.", "burnAfterReading_linkBurnAfterReading": "Einmal ansehen mit Selbstzerstörung", - "burnAfterReading_warningLink": "Du hast ausgewählt, dass sich das Pad selbst zerstören soll. Sobald der Empfänger auf den Link klickt, wird er sich das Pad einmal ansehen können. Anschließend wird das Pad endgültig gelöscht.", + "burnAfterReading_warningLink": "Du hast ausgewählt, dass sich das Dokument selbst zerstören soll. Sobald der Empfänger auf den Link klickt, wird er sich das Dokument einmal ansehen können. Anschließend wird das Dokument endgültig gelöscht.", "burnAfterReading_generateLink": "Klicke auf die Schaltfläche unten, um einen Link zu generieren.", "burnAfterReading_warningAccess": "Dieses Dokument wird sich selbst zerstören. Wenn du die Schaltfläche unten anklickst, kannst du dir den Inhalt einmal anzeigen lassen. Anschließend wird er endgültig gelöscht. Wenn du das Fenster schließt, kannst du nicht mehr auf den Inhalt zugreifen. Solltest du darauf nicht vorbereitet sein, schließe das Fenster und komme später zurück.", "burnAfterReading_proceed": "Ansehen und Löschen", - "burnAfterReading_warningDeleted": "Dieses Pad wurde endgültig gelöscht. Nachdem du das Fenster geschlossen hast, wirst du darauf nicht mehr zugreifen können.", + "burnAfterReading_warningDeleted": "Dieses Dokument wurde endgültig gelöscht. Nachdem du das Fenster geschlossen hast, wirst du darauf nicht mehr zugreifen können.", "oo_invalidFormat": "Diese Datei kann nicht importiert werden", "oo_importInProgress": "Import wird durchgeführt", "oo_exportInProgress": "Export wird durchgeführt", - "oo_sheetMigration_loading": "Deine Tabelle wird auf die neueste Version aktualisiert. Bitte warte etwa eine Minute.", + "oo_sheetMigration_loading": "Dein Dokument wird auf die neueste Version aktualisiert. Bitte warte etwa eine Minute.", "oo_sheetMigration_complete": "Eine aktualisierte Version ist verfügbar. Klicke auf OK, um neu zu laden.", - "oo_sheetMigration_anonymousEditor": "Die Bearbeitung dieser Tabelle ist für Gäste deaktiviert, bis sie von einem registrierten Benutzer auf die neueste Version aktualisiert wird.", + "oo_sheetMigration_anonymousEditor": "Dieses Dokument muss auf eine neuere Version aktualisiert werden. Für Gäste ist die Bearbeitung deaktiviert, bis das Dokument von einem registrierten Benutzer geöffnet wird.", "imprint": "Impressum", "isContact": "{0} ist einer deiner Kontakte", "isNotContact": "{0} ist nicht einer deiner Kontakte", "settings_cat_security": "Vertraulichkeit", - "settings_safeLinksHint": "CryptPad fügt den Pad-Links die Schlüssel zum Entschlüsseln der Inhalte hinzu. Jeder, der Zugriff auf den Browserverlauf hat, kann möglicherweise die Daten lesen. Dazu gehören Browsererweiterungen und Browser, die den Verlauf geräteübergreifend synchronisieren. Die Aktivierung von \"sicheren Links\" verhindert, dass die Schlüssel in den Browserverlauf gelangen oder in der Adressleiste angezeigt werden, wann immer dies möglich ist. Wir empfehlen dringend, diese Funktion zu aktivieren und das Menü {0} Teilen zu verwenden.", + "settings_safeLinksHint": "CryptPad fügt den Dokumenten-Links die Schlüssel zum Entschlüsseln der Inhalte hinzu. Jeder, der Zugriff auf den Browserverlauf hat, kann möglicherweise die Daten lesen. Dazu gehören Browsererweiterungen und Browser, die den Verlauf geräteübergreifend synchronisieren. Die Aktivierung von \"sicheren Links\" verhindert, dass die Schlüssel in den Browserverlauf gelangen oder in der Adressleiste angezeigt werden, wann immer dies möglich ist. Wir empfehlen dringend, diese Funktion zu aktivieren und das Menü {0} Teilen zu verwenden, um für die Weitergabe geeignete Links zu erstellen.", "dontShowAgain": "Nicht mehr anzeigen", "profile_login": "Du musst dich einloggen, um diesen Benutzer zu deinen Kontakten hinzuzufügen", "safeLinks_error": "Dieser Link wurde aus der Adresszeile des Browsers kopiert und ermöglicht keinen Zugriff auf das Dokument. Bitte verwende das Menü Teilen, um das Dokument direkt mit Kontakten zu teilen oder den Link zu kopieren. Mehr zu sicheren Links.", "settings_safeLinksCheckbox": "Sichere Links aktivieren", "settings_safeLinksTitle": "Sichere Links", - "settings_trimHistoryHint": "Spare Speicherplatz, indem du den Verlauf deines CryptDrives und der Benachrichtigungen löschst. Dies hat keinen Einfluss auf den Verlauf deiner Pads. Du kannst den Verlauf der Pads in deren Eigenschaften-Dialog löschen.", + "settings_trimHistoryHint": "Spare Speicherplatz, indem du den Verlauf deines CryptDrives und der Benachrichtigungen löschst. Dies hat keinen Einfluss auf den Verlauf deiner Dokumente. Du kannst den Verlauf der Dokumente in deren Eigenschaften-Dialog löschen.", "trimHistory_noHistory": "Kein Verlauf kann gelöscht werden", "settings_trimHistoryTitle": "Verlauf löschen", "trimHistory_currentSize": "Aktuelle Größe des Verlaufs: {0}", @@ -902,8 +902,8 @@ "makeACopy": "Kopie erstellen", "copy_title": "{0} (Kopie)", "access_noContact": "Keine weiteren Kontakte zum Hinzufügen verfügbar", - "access_muteRequests": "Zugriffsanfragen für dieses Pad stummschalten", - "owner_text": "Nur Eigentümer sind berechtigt für: Hinzufügen/Entfernen von Eigentümern, Beschränkung des Zugriffs mit Zugriffslisten und Löschen des Pads.", + "access_muteRequests": "Zugriffsanfragen für dieses Dokument stummschalten", + "owner_text": "Nur Eigentümer sind berechtigt für: Hinzufügen/Entfernen von Eigentümern, Beschränkung des Zugriffs mit Zugriffslisten und Löschen des Dokuments", "accessButton": "Zugriff", "access_allow": "Liste", "allow_label": "Zugriffsliste: {0}", @@ -938,7 +938,7 @@ "cba_disable": "Löschen und Deaktivieren", "cba_show": "Autorenfarben anzeigen", "cba_writtenBy": "Geschrieben von: {0}", - "cba_hint": "Diese Einstellung wird zukünftig verwendet, wenn du ein neues Pad erstellst.", + "cba_hint": "Diese Einstellung wird zukünftig verwendet, wenn du ein neues Dokument erstellst.", "oo_login": "Bitte logge dich ein oder erstelle ein Account, um die Performance von Tabellen zu verbessern.", "cba_title": "Autorenfarben", "comments_resolve": "Abschließen", @@ -952,7 +952,7 @@ "settings_padNotifTitle": "Kommentar-Benachrichtigungen", "settings_padNotifCheckbox": "Kommentar-Benachrichtigungen deaktivieren", "comments_edited": "Bearbeitet", - "unknownPad": "Unbekanntes Pad", + "unknownPad": "Unbekanntes Dokument", "comments_error": "An dieser Stelle kann kein Kommentar hinzugefügt werden", "fm_sort": "Sortieren", "code_editorTheme": "Editor-Theme", @@ -976,7 +976,7 @@ "support_cat_data": "Datenverlust", "notification_folderSharedTeam": "{0} hat einen Ordner mit dem Team {2} geteilt: {1}", "notification_fileSharedTeam": "{0} hat eine Datei mit dem Team {2} geteilt: {1}", - "notification_padSharedTeam": "{0} hat ein Pad mit dem Team {2} geteilt: {1}", + "notification_padSharedTeam": "{0} hat ein Dokument mit dem Team {2} geteilt: {1}", "support_addAttachment": "Anhang hinzufügen", "support_attachments": "Anhänge", "support_cat_bug": "Fehlerbericht", @@ -1417,5 +1417,11 @@ "form_anonAnswer": "Antworten auf dieses Formular sind anonymisiert", "form_viewAllAnswers": "Alle Antworten anzeigen ({0})", "form_alreadyAnswered": "Du hast dieses Formular beantwortet am {0}", - "form_template_poll": "Schnelle Terminumfrage" + "form_template_poll": "Schnelle Terminumfrage", + "creation_new": "Erstellen: {0}", + "download_step3": "Konvertieren...", + "fc_openIn": "In {0} öffnen", + "premiumOnly": "Die Erstellung neuer Dokumente in dieser Anwendung ist derzeit nur für Abonnenten auf {0} möglich. Dies ist eine experimentelle Anwendung für Testzwecke. Sie wird bald für jeden Benutzer auf {0} verfügbar sein.", + "premiumAccess": "Als Abonnent auf {0} kannst du in dieser Anwendung neue Dokumente erstellen. Bitte beachte, dass es sich um eine experimentelle Anwendung handelt, der man noch keine wichtigen Daten anvertrauen sollte.", + "earlyAccessBlocked": "Diese Anwendung ist auf dieser Instanz noch nicht verfügbar" } From 747c1a28d0d457874727bb6f7e35ca4371e95fd0 Mon Sep 17 00:00:00 2001 From: ansuz Date: Tue, 19 Oct 2021 11:29:59 +0530 Subject: [PATCH 2/3] hide 'Open in...' for already-converted docs --- www/common/drive-ui.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 2709e87d3..b56dee169 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -1303,6 +1303,14 @@ define([ if (!metadata || !Util.isPlainTextFile(metadata.fileType, metadata.title)) { hide.push('openincode'); } + + if (metadata && /\/(doc|presentation|sheet)\//.test(metadata.href)) { + console.error(metadata); // XXX + hide.push('openinsheet'); + hide.push('openindoc'); + hide.push('openinpresentation'); + } + if (!metadata || !Util.isSpreadsheet(metadata.fileType, metadata.title) || !priv.supportsWasm) { hide.push('openinsheet'); From b8d6af78919dc2a992e5f448c963f831632069bb Mon Sep 17 00:00:00 2001 From: ansuz Date: Tue, 19 Oct 2021 14:22:06 +0530 Subject: [PATCH 3/3] adjust CSP headers for printing from OnlyOffice * allow outer to load resources from the sandbox (for fonts) * test whether the expected CSP values are present on the checkup page * simplify the nodejs server a bit --- lib/defaults.js | 12 +++++------ lib/env.js | 7 +++++++ server.js | 50 +++++++++++++++++---------------------------- www/checkup/main.js | 27 ++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/lib/defaults.js b/lib/defaults.js index 635e155be..c4cb507cb 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,6 +1,6 @@ var Default = module.exports; -Default.commonCSP = function (domain) { +Default.commonCSP = function (domain, sandbox) { domain = ' ' + domain; // Content-Security-Policy @@ -23,7 +23,7 @@ Default.commonCSP = function (domain) { if you are deploying to production, you'll probably want to remove the ws://* directive, and change '*' to your domain */ - "connect-src 'self' ws: wss: blob:" + domain, + "connect-src 'self' ws: wss: blob: " + domain + (sandbox && sandbox !== domain? ' ' + sandbox: ''), // data: is used by codemirror "img-src 'self' data: blob:" + domain, @@ -35,12 +35,12 @@ Default.commonCSP = function (domain) { ]; }; -Default.contentSecurity = function (domain) { - return (Default.commonCSP(domain).join('; ') + "script-src 'self' resource: " + domain).replace(/\s+/g, ' '); +Default.contentSecurity = function (domain, sandbox) { + return (Default.commonCSP(domain, sandbox).join('; ') + "script-src 'self' resource: " + domain).replace(/\s+/g, ' '); }; -Default.padContentSecurity = function (domain) { - return (Default.commonCSP(domain).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline' resource: " + domain).replace(/\s+/g, ' '); +Default.padContentSecurity = function (domain, sandbox) { + return (Default.commonCSP(domain, sandbox).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline' resource: " + domain).replace(/\s+/g, ' '); }; Default.httpHeaders = function () { diff --git a/lib/env.js b/lib/env.js index 5ad0bbdac..9970bc4f9 100644 --- a/lib/env.js +++ b/lib/env.js @@ -17,6 +17,10 @@ var canonicalizeOrigin = function (s) { return (s || '').trim().replace(/\/+$/, ''); }; +var isValidPort = function (p) { + return typeof(p) === 'number' && p < 65535; +}; + module.exports.create = function (config) { const Env = { version: Package.version, @@ -25,6 +29,9 @@ module.exports.create = function (config) { httpUnsafeOrigin: canonicalizeOrigin(config.httpUnsafeOrigin), httpSafeOrigin: canonicalizeOrigin(config.httpSafeOrigin), removeDonateButton: config.removeDonateButton, + httpPort: isValidPort(config.httpPort)? config.httpPort: 3000, + httpAddress: typeof(config.httpAddress) === 'string'? config.httpAddress: '127.0.0.1', + websocketPath: config.externalWebsocketURL, OFFLINE_MODE: false, FRESH_KEY: '', diff --git a/server.js b/server.js index 07cae4b23..0b95119f9 100644 --- a/server.js +++ b/server.js @@ -23,28 +23,24 @@ var fancyURL = function (domain, path) { return false; }; +var deriveSandboxOrigin = function (unsafe, port) { + var url = new URL(unsafe); + url.port = port; + return url.origin; +}; + (function () { // you absolutely must provide an 'httpUnsafeOrigin' (a truthy string) if (!Env.httpUnsafeOrigin || typeof(Env.httpUnsafeOrigin) !== 'string') { throw new Error("No 'httpUnsafeOrigin' provided"); } - // fall back to listening on a local address - // if httpAddress is not a string - if (typeof(config.httpAddress) !== 'string') { - config.httpAddress = '127.0.0.1'; - } - - // listen on port 3000 if a valid port number was not provided - if (typeof(config.httpPort) !== 'number' || config.httpPort > 65535) { - config.httpPort = 3000; - } - if (typeof(Env.httpSafeOrigin) !== 'string') { Env.NO_SANDBOX = true; - if (typeof(config.httpSafePort) !== 'number') { - config.httpSafePort = config.httpPort + 1; + if (typeof(Env.httpSafePort) !== 'number') { + Env.httpSafePort = Env.httpPort + 1; } + Env.httpSafeOrigin = deriveSandboxOrigin(Env.httpUnsafeOrigin, Env.httpSafePort); } }()); @@ -77,7 +73,7 @@ var setHeaders = (function () { } } else { // use the default CSP headers constructed with your domain - headers['Content-Security-Policy'] = Default.contentSecurity(Env.httpUnsafeOrigin); + headers['Content-Security-Policy'] = Default.contentSecurity(Env.httpUnsafeOrigin, Env.httpSafeOrigin); } const padHeaders = Util.clone(headers); @@ -239,14 +235,14 @@ var makeRouteCache = function (template, cacheName) { var serveConfig = makeRouteCache(function (host) { return [ 'define(function(){', - 'var obj = ' + JSON.stringify({ + 'return ' + JSON.stringify({ requireConf: { waitSeconds: 600, urlArgs: 'ver=' + Env.version + cacheString(), }, removeDonateButton: (Env.removeDonateButton === true), allowSubscriptions: (Env.allowSubscriptions === true), - websocketPath: config.externalWebsocketURL, + websocketPath: Env.websocketPath, httpUnsafeOrigin: Env.httpUnsafeOrigin, adminEmail: Env.adminEmail, adminKeys: Env.admins, @@ -256,16 +252,8 @@ var serveConfig = makeRouteCache(function (host) { maxUploadSize: Env.maxUploadSize, premiumUploadSize: Env.premiumUploadSize, restrictRegistration: Env.restrictRegistration, + httpSafeOrigin: Env.httpSafeOrigin, }, null, '\t'), - 'obj.httpSafeOrigin = ' + (function () { - if (Env.httpSafeOrigin) { return '"' + Env.httpSafeOrigin + '"'; } - if (config.httpSafePort) { - return "(function () { return window.location.origin.replace(/\:[0-9]+$/, ':" + - config.httpSafePort + "'); }())"; - } - return 'window.location.origin'; - }()), - 'return obj', '});' ].join(';\n') }, 'configCache'); @@ -314,11 +302,11 @@ nThen(function (w) { console.log("CryptPad is customizable, see customize.dist/readme.md for details"); })); }).nThen(function (w) { - httpServer.listen(config.httpPort,config.httpAddress,function(){ - var host = config.httpAddress; + httpServer.listen(Env.httpPort, Env.httpAddress, function(){ + var host = Env.httpAddress; var hostName = !host.indexOf(':') ? '[' + host + ']' : host; - var port = config.httpPort; + var port = Env.httpPort; var ps = port === 80? '': ':' + port; var roughAddress = 'http://' + hostName + ps; @@ -336,8 +324,8 @@ nThen(function (w) { } }); - if (config.httpSafePort) { - Http.createServer(app).listen(config.httpSafePort, config.httpAddress, w()); + if (Env.httpSafePort) { + Http.createServer(app).listen(Env.httpSafePort, Env.httpAddress, w()); } }).nThen(function () { var wsConfig = { server: httpServer }; @@ -348,7 +336,7 @@ nThen(function (w) { config.log = _log; if (Env.OFFLINE_MODE) { return; } - if (config.externalWebsocketURL) { return; } + if (Env.websocketPath) { return; } require("./lib/api").create(Env); }); diff --git a/www/checkup/main.js b/www/checkup/main.js index 3118be749..d3841b8bd 100644 --- a/www/checkup/main.js +++ b/www/checkup/main.js @@ -830,6 +830,33 @@ define([ }); }); + assert(function (cb, msg) { // XXX + // check that the sandbox domain is included in connect-src + msg.appendChild(h('span', [ + "This instance's ", + code("Content-Security-Policy"), + " headers do not include the sandboxed domain (", + code(trimmedSafe), + ") in ", + code("connect-src"), + ". This can cause problems with fonts when printing office documents.", + " This is probably due to an incorrectly configured reverse proxy.", + " See the provided NGINX configuration file for an example of how to set this header correctly.", + ])); + + $.ajax(cacheBuster('/'), { + dataType: 'text', + complete: function (xhr) { + var CSP = parseCSP(xhr.getResponseHeader('content-security-policy')); + var connect = (CSP && CSP['connect-src']) || ""; + if (connect.includes(trimmedSafe)) { + return void cb(true); + } + cb(CSP); + }, + }); + }); + /* assert(function (cb, msg) { setWarningClass(msg);