Compare commits

..

77 Commits

Author SHA1 Message Date
Philip Okugbe 371c796afd New translations translation.json (Russian)
[ci skip]
2026-05-10 00:59:36 +01:00
Philip Okugbe 65f048e6c4 New translations translation.json (Russian)
[ci skip]
2026-05-09 19:03:28 +01:00
Philip Okugbe da61d464b2 New translations translation.json (Portuguese, Brazilian)
[ci skip]
2026-05-09 17:57:56 +01:00
Philip Okugbe 8eb8de6df7 New translations translation.json (English)
[ci skip]
2026-05-09 17:57:54 +01:00
Philip Okugbe 10d922eb71 New translations translation.json (Chinese Simplified)
[ci skip]
2026-05-09 17:57:53 +01:00
Philip Okugbe ab4605c4ad New translations translation.json (Ukrainian)
[ci skip]
2026-05-09 17:57:51 +01:00
Philip Okugbe a95f3d254d New translations translation.json (Russian)
[ci skip]
2026-05-09 17:57:50 +01:00
Philip Okugbe 5451efaf5d New translations translation.json (Dutch)
[ci skip]
2026-05-09 17:57:49 +01:00
Philip Okugbe 4ee65525c9 New translations translation.json (Korean)
[ci skip]
2026-05-09 17:57:47 +01:00
Philip Okugbe d39ba67834 New translations translation.json (Japanese)
[ci skip]
2026-05-09 17:57:46 +01:00
Philip Okugbe 253c9a5d88 New translations translation.json (Italian)
[ci skip]
2026-05-09 17:57:45 +01:00
Philip Okugbe cdf00a96a9 New translations translation.json (Spanish)
[ci skip]
2026-05-09 17:57:43 +01:00
Philip Okugbe 73b726c7a8 New translations translation.json (French)
[ci skip]
2026-05-09 17:57:42 +01:00
Philip Okugbe d9d6a8e2ae New translations translation.json (German)
[ci skip]
2026-05-09 17:57:41 +01:00
Philip Okugbe 3602860979 Merge branch 'main' into i10n_main 2026-05-09 17:23:02 +01:00
Philip Okugbe 537e45bc11 feat: page details section and backlinks (#2186)
* feat: page details section and backlinks
2026-05-09 17:03:08 +01:00
Philip Okugbe 79b79348ba New translations translation.json (Portuguese, Brazilian)
[ci skip]
2026-05-09 14:39:52 +01:00
Philip Okugbe b44d6e3138 New translations translation.json (Chinese Simplified)
[ci skip]
2026-05-09 14:39:51 +01:00
Philip Okugbe cdd9c5cf66 New translations translation.json (Ukrainian)
[ci skip]
2026-05-09 14:39:49 +01:00
Philip Okugbe c866c07219 New translations translation.json (Russian)
[ci skip]
2026-05-09 14:39:48 +01:00
Philip Okugbe 6638ca806c New translations translation.json (Dutch)
[ci skip]
2026-05-09 14:39:46 +01:00
Philip Okugbe adc2341029 New translations translation.json (Korean)
[ci skip]
2026-05-09 14:39:45 +01:00
Philip Okugbe 27ebcd248f New translations translation.json (Japanese)
[ci skip]
2026-05-09 14:39:43 +01:00
Philip Okugbe 366b8fbdc1 New translations translation.json (Italian)
[ci skip]
2026-05-09 14:39:42 +01:00
Philip Okugbe 44cba3c581 New translations translation.json (Spanish)
[ci skip]
2026-05-09 14:39:41 +01:00
Philip Okugbe 23c5bf6b66 New translations translation.json (French)
[ci skip]
2026-05-09 14:39:40 +01:00
Philip Okugbe a6b49f49bd New translations translation.json (German)
[ci skip]
2026-05-09 14:39:38 +01:00
Philip Okugbe 24a9403f09 New translations translation.json (Portuguese, Brazilian)
[ci skip]
2026-05-09 13:32:45 +01:00
Philip Okugbe e8323708d7 New translations translation.json (English)
[ci skip]
2026-05-09 13:32:44 +01:00
Philip Okugbe b9d28223d9 New translations translation.json (Chinese Simplified)
[ci skip]
2026-05-09 13:32:43 +01:00
Philip Okugbe 57ca56744d New translations translation.json (Ukrainian)
[ci skip]
2026-05-09 13:32:41 +01:00
Philip Okugbe f45c6bead3 New translations translation.json (Russian)
[ci skip]
2026-05-09 13:32:40 +01:00
Philip Okugbe e02cdf6d59 New translations translation.json (Dutch)
[ci skip]
2026-05-09 13:32:38 +01:00
Philip Okugbe 0f6d0fb440 New translations translation.json (Korean)
[ci skip]
2026-05-09 13:32:37 +01:00
Philip Okugbe 7025e3c947 New translations translation.json (Japanese)
[ci skip]
2026-05-09 13:32:36 +01:00
Philip Okugbe 53a803383b New translations translation.json (Italian)
[ci skip]
2026-05-09 13:32:35 +01:00
Philip Okugbe 1d5b5a3002 New translations translation.json (Spanish)
[ci skip]
2026-05-09 13:32:33 +01:00
Philip Okugbe 08a9df37ef New translations translation.json (French)
[ci skip]
2026-05-09 13:32:32 +01:00
Philip Okugbe 63be9a58c1 New translations translation.json (German)
[ci skip]
2026-05-09 13:32:31 +01:00
Philip Okugbe bdc369fce0 feat(editor): fixed toolbar preference (#2185)
* feat(editor): fixed toolbar preference

* remove key

* cleanup translation strings

* update axios
2026-05-09 13:27:03 +01:00
Philip Okugbe 696aa430f4 New translations translation.json (Portuguese, Brazilian)
[ci skip]
2026-05-04 23:55:59 +01:00
Philip Okugbe ed9d85ca95 New translations translation.json (English)
[ci skip]
2026-05-04 23:55:58 +01:00
Philip Okugbe d992abf8d8 New translations translation.json (Chinese Simplified)
[ci skip]
2026-05-04 23:55:57 +01:00
Philip Okugbe 149bcc14f1 New translations translation.json (Ukrainian)
[ci skip]
2026-05-04 23:55:55 +01:00
Philip Okugbe 8ed4f4b7aa New translations translation.json (Russian)
[ci skip]
2026-05-04 23:55:54 +01:00
Philip Okugbe fd0200331c New translations translation.json (Dutch)
[ci skip]
2026-05-04 23:55:53 +01:00
Philip Okugbe 44ab6e5485 New translations translation.json (Korean)
[ci skip]
2026-05-04 23:55:51 +01:00
Philip Okugbe 505d7923db New translations translation.json (Japanese)
[ci skip]
2026-05-04 23:55:50 +01:00
Philip Okugbe 3112709d03 New translations translation.json (Italian)
[ci skip]
2026-05-04 23:55:48 +01:00
Philip Okugbe 8c9d0389f4 New translations translation.json (Spanish)
[ci skip]
2026-05-04 23:55:47 +01:00
Philip Okugbe afafc8451f New translations translation.json (French)
[ci skip]
2026-05-04 23:55:46 +01:00
Philip Okugbe 0a4bbd5d30 New translations translation.json (German)
[ci skip]
2026-05-04 23:55:44 +01:00
Philip Okugbe c802222562 New translations translation.json (Portuguese, Brazilian)
[ci skip]
2026-05-04 22:16:52 +01:00
Philip Okugbe be2d93877a New translations translation.json (English)
[ci skip]
2026-05-04 22:16:50 +01:00
Philip Okugbe 34da8d3fb4 New translations translation.json (Chinese Simplified)
[ci skip]
2026-05-04 22:16:49 +01:00
Philip Okugbe f55bd21b08 New translations translation.json (Ukrainian)
[ci skip]
2026-05-04 22:16:47 +01:00
Philip Okugbe f6f9cc14df New translations translation.json (Russian)
[ci skip]
2026-05-04 22:16:45 +01:00
Philip Okugbe 1790ee8f6f New translations translation.json (Dutch)
[ci skip]
2026-05-04 22:16:44 +01:00
Philip Okugbe 58840da7f4 New translations translation.json (Korean)
[ci skip]
2026-05-04 22:16:43 +01:00
Philip Okugbe db77b31782 New translations translation.json (Japanese)
[ci skip]
2026-05-04 22:16:41 +01:00
Philip Okugbe 77ba4facb1 New translations translation.json (Italian)
[ci skip]
2026-05-04 22:16:40 +01:00
Philip Okugbe 6fa08e487e New translations translation.json (Spanish)
[ci skip]
2026-05-04 22:16:38 +01:00
Philip Okugbe 979e8faeee New translations translation.json (French)
[ci skip]
2026-05-04 22:16:37 +01:00
Philip Okugbe 1839418430 New translations translation.json (German)
[ci skip]
2026-05-04 22:16:35 +01:00
Philip Okugbe 94461e90a3 New translations translation.json (Portuguese, Brazilian)
[ci skip]
2026-05-01 16:02:26 +01:00
Philip Okugbe 58aa02340e New translations translation.json (English)
[ci skip]
2026-05-01 16:02:24 +01:00
Philip Okugbe 592e6a39e8 New translations translation.json (Chinese Simplified)
[ci skip]
2026-05-01 16:02:23 +01:00
Philip Okugbe 56526c6c1c New translations translation.json (Ukrainian)
[ci skip]
2026-05-01 16:02:21 +01:00
Philip Okugbe 6f9387b8b4 New translations translation.json (Russian)
[ci skip]
2026-05-01 16:02:20 +01:00
Philip Okugbe aa2ca3ef91 New translations translation.json (Dutch)
[ci skip]
2026-05-01 16:02:18 +01:00
Philip Okugbe 21848b91bf New translations translation.json (Korean)
[ci skip]
2026-05-01 16:02:17 +01:00
Philip Okugbe 989231d818 New translations translation.json (Japanese)
[ci skip]
2026-05-01 16:02:15 +01:00
Philip Okugbe d50986453b New translations translation.json (Italian)
[ci skip]
2026-05-01 16:02:14 +01:00
Philip Okugbe 2c21af4e91 New translations translation.json (Spanish)
[ci skip]
2026-05-01 16:02:12 +01:00
Philip Okugbe 574f687335 New translations translation.json (French)
[ci skip]
2026-05-01 16:02:10 +01:00
Philip Okugbe 9956a98d1f New translations translation.json (German)
[ci skip]
2026-05-01 16:02:08 +01:00
Philip Okugbe 14fd3eb956 New translations translation.json (German)
[ci skip]
2026-05-01 00:49:11 +01:00
32 changed files with 2152 additions and 87 deletions
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} ist verfügbar",
"Default page edit mode": "Standard-Bearbeitungsmodus für Seiten",
"Choose your preferred page edit mode. Avoid accidental edits.": "Wählen Sie Ihren bevorzugten Seitenbearbeitungsmodus. Vermeiden Sie versehentliche Bearbeitungen.",
"Choose {{format}} file": "{{format}}-Datei auswählen",
"Reading": "Lesen",
"Delete member": "Mitglied löschen",
"Member deleted successfully": "Mitglied erfolgreich gelöscht",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "Bild überschreitet das Limit von 10 MB.",
"Image removed successfully": "Bild erfolgreich entfernt",
"API key": "API-Schlüssel",
"API key created successfully": "API-Schlüssel erfolgreich erstellt",
"API keys": "API-Schlüssel",
"API management": "API-Verwaltung",
"Are you sure you want to revoke this API key": "Sind Sie sicher, dass Sie diesen API-Schlüssel widerrufen möchten?",
"Create API Key": "API-Schlüssel erstellen",
"Custom expiration date": "Benutzerdefiniertes Ablaufdatum",
"Enter a descriptive token name": "Geben Sie einen beschreibenden Token-Namen ein",
"Expiration": "Ablauf",
"Expired": "Abgelaufen",
"Expires": "Läuft ab",
"I've saved my API key": "Ich habe meinen API-Schlüssel gespeichert",
"Last use": "Zuletzt verwendet",
"No API keys found": "Keine API-Schlüssel gefunden",
"No expiration": "Kein Ablauf",
"Revoke API key": "API-Schlüssel widerrufen",
"Revoked successfully": "Erfolgreich widerrufen",
"Select expiration date": "Ablaufdatum wählen",
"This action cannot be undone. Any applications using this API key will stop working.": "Diese Aktion kann nicht rückgängig gemacht werden. Alle Anwendungen, die diesen API-Schlüssel verwenden, werden nicht mehr funktionieren.",
"Update API key": "API-Schlüssel aktualisieren",
"Update": "Aktualisieren",
"Update {{credential}}": "{{credential}} aktualisieren",
"Manage API keys for all users in the workspace": "Verwalten Sie API-Schlüssel für alle Benutzer im Arbeitsbereich",
"Restrict API key creation to admins": "API-Schlüsselerstellung auf Administratoren beschränken",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Nur Administratoren und Eigentümer können neue API-Schlüssel erstellen. Bestehende Mitgliederschlüssel funktionieren weiterhin.",
@@ -873,6 +870,12 @@
"Previous 7 days": "Letzte 7 Tage",
"Previous 30 days": "Letzte 30 Tage",
"Search chats...": "Chats durchsuchen...",
"Search chats": "Chats durchsuchen",
"Ask anything... Use @ to mention pages": "Frag etwas ... Verwende @, um Seiten zu erwähnen",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "Starten Sie einen neuen Chat, damit er hier angezeigt wird.",
"Summarize this page": "Diese Seite zusammenfassen",
"Toggle AI Chat": "KI-Chat umschalten",
@@ -880,5 +883,105 @@
"Try a different search term.": "Versuchen Sie einen anderen Suchbegriff.",
"Try again": "Erneut versuchen",
"Untitled chat": "Chat ohne Titel",
"What can I help you with?": "Womit kann ich Ihnen helfen?"
"What can I help you with?": "Womit kann ich Ihnen helfen?",
"Are you sure you want to revoke this {{credential}}": "Sind Sie sicher, dass Sie diese(n) {{credential}} widerrufen möchten?",
"Automatically provision users and groups from your identity provider via SCIM.": "Stellen Sie Benutzer und Gruppen automatisch über SCIM von Ihrem Identitätsanbieter bereit.",
"Configure your identity provider with this URL to provision users and groups.": "Konfigurieren Sie Ihren Identitätsanbieter mit dieser URL, um Benutzer und Gruppen bereitzustellen.",
"Create {{credential}}": "{{credential}} erstellen",
"{{credential}} created": "{{credential}} erstellt",
"{{credential}} created successfully": "{{credential}} erfolgreich erstellt",
"Created by": "Erstellt von",
"Custom": "Benutzerdefiniert",
"Enable SCIM": "SCIM aktivieren",
"Enter a descriptive name": "Geben Sie einen beschreibenden Namen ein",
"I've saved my {{credential}}": "Ich habe meine(n) {{credential}} gespeichert",
"Important": "Wichtig",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Stellen Sie sicher, dass Sie Ihre(n) {{credential}} jetzt kopieren. Sie können sie/ihn später nicht erneut anzeigen!",
"Never": "Nie",
"Revoke {{credential}}": "{{credential}} widerrufen",
"SCIM endpoint URL": "SCIM-Endpunkt-URL",
"SCIM provisioning": "SCIM-Bereitstellung",
"SCIM takes precedence over SSO group sync while enabled.": "SCIM hat Vorrang vor der SSO-Gruppensynchronisierung, solange es aktiviert ist.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "Sie haben die maximale Anzahl von {{max}} SCIM-Token erreicht. Löschen Sie ein vorhandenes Token, um ein neues zu erstellen.",
"SCIM token": "SCIM-Token",
"SCIM tokens": "SCIM-Token",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Diese Aktion kann nicht rückgängig gemacht werden. Ihr Identitätsanbieter wird die Synchronisierung sofort beenden.",
"Toggle SCIM provisioning": "SCIM-Bereitstellung umschalten",
"Token": "Token",
"Page menu": "Seitenmenü",
"Expand": "Erweitern",
"Collapse": "Reduzieren",
"Comment menu": "Kommentarmenü",
"Group menu": "Gruppenmenü",
"Show hidden breadcrumbs": "Ausgeblendete Breadcrumbs anzeigen",
"Breadcrumbs": "Navigationspfade",
"Page actions": "Seitenaktionen",
"Pick emoji": "Emoji auswählen",
"Template menu": "Vorlagenmenü",
"Chat menu": "Chatmenü",
"API key menu": "API-Schlüssel-Menü",
"Jump to comment selection": "Zur Kommentarauswahl springen",
"Slash commands": "Slash-Befehle",
"Mention suggestions": "Erwähnungsvorschläge",
"Link suggestions": "Linkvorschläge",
"Diagram editor": "Diagrammeditor",
"Add comment": "Kommentar hinzufügen",
"Find and replace": "Suchen und ersetzen",
"Main navigation": "Hauptnavigation",
"Space navigation": "Bereichsnavigation",
"Settings navigation": "Einstellungsnavigation",
"AI navigation": "KI-Navigation",
"Breadcrumb": "Navigationspfad",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -970,5 +970,18 @@
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo"
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} está disponible",
"Default page edit mode": "Modo de edición predeterminado de la página",
"Choose your preferred page edit mode. Avoid accidental edits.": "Elige tu modo de edición de página preferido. Evita ediciones accidentales.",
"Choose {{format}} file": "Elegir archivo {{format}}",
"Reading": "Lectura",
"Delete member": "Eliminar miembro",
"Member deleted successfully": "Miembro eliminado correctamente",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "La imagen excede del límite de 10 MB",
"Image removed successfully": "Imagen eliminada correctamente",
"API key": "Clave API",
"API key created successfully": "Clave API creada correctamente",
"API keys": "Claves API",
"API management": "Gestión de API",
"Are you sure you want to revoke this API key": "¿Está seguro de que desea revocar esta clave API? ",
"Create API Key": "Crear clave API",
"Custom expiration date": "Fecha de vencimiento personalizada",
"Enter a descriptive token name": "Introduce un nombre descriptivo del token",
"Expiration": "Vencimiento",
"Expired": "Vencido",
"Expires": "Vence",
"I've saved my API key": "He guardado mi clave API",
"Last use": "Último uso",
"No API keys found": "No se han encontrado claves API",
"No expiration": "Sin vencimiento",
"Revoke API key": "Revocar clave API",
"Revoked successfully": "Revocada correctamente",
"Select expiration date": "Seleccionar fecha de vencimiento",
"This action cannot be undone. Any applications using this API key will stop working.": "Esta acción no se puede deshacer. Las aplicaciones que utilicen esta clave API dejarán de funcionar.",
"Update API key": "Actualizar clave API",
"Update": "Actualizar",
"Update {{credential}}": "Actualizar {{credential}}",
"Manage API keys for all users in the workspace": "Gestionar claves API para todos los usuarios en el espacio de trabajo",
"Restrict API key creation to admins": "Restringir la creación de claves API a administradores",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Solo los administradores y propietarios pueden crear nuevas claves API. Las claves de miembros existentes seguirán funcionando.",
@@ -873,6 +870,12 @@
"Previous 7 days": "Últimos 7 días",
"Previous 30 days": "Últimos 30 días",
"Search chats...": "Buscar chats...",
"Search chats": "Buscar chats",
"Ask anything... Use @ to mention pages": "Pregunta lo que sea... Usa @ para mencionar páginas",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "Inicia un nuevo chat para verlo aquí.",
"Summarize this page": "Resumir esta página",
"Toggle AI Chat": "Alternar chat de IA",
@@ -880,5 +883,105 @@
"Try a different search term.": "Prueba con otro término de búsqueda.",
"Try again": "Intentar de nuevo",
"Untitled chat": "Chat sin título",
"What can I help you with?": "¿En qué puedo ayudarte?"
"What can I help you with?": "¿En qué puedo ayudarte?",
"Are you sure you want to revoke this {{credential}}": "¿Está seguro de que desea revocar esta {{credential}}?",
"Automatically provision users and groups from your identity provider via SCIM.": "Aprovisione automáticamente usuarios y grupos desde su proveedor de identidad mediante SCIM.",
"Configure your identity provider with this URL to provision users and groups.": "Configure su proveedor de identidad con esta URL para aprovisionar usuarios y grupos.",
"Create {{credential}}": "Crear {{credential}}",
"{{credential}} created": "{{credential}} creada",
"{{credential}} created successfully": "{{credential}} creada con éxito",
"Created by": "Creado por",
"Custom": "Personalizado",
"Enable SCIM": "Habilitar SCIM",
"Enter a descriptive name": "Introduzca un nombre descriptivo",
"I've saved my {{credential}}": "He guardado mi {{credential}}",
"Important": "Importante",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Asegúrese de copiar su {{credential}} ahora. ¡No podrá volver a verla!",
"Never": "Nunca",
"Revoke {{credential}}": "Revocar {{credential}}",
"SCIM endpoint URL": "URL del endpoint de SCIM",
"SCIM provisioning": "Aprovisionamiento SCIM",
"SCIM takes precedence over SSO group sync while enabled.": "SCIM tiene prioridad sobre la sincronización de grupos de SSO mientras esté habilitado.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "Ha alcanzado el máximo de {{max}} tokens SCIM. Elimine un token existente para crear uno nuevo.",
"SCIM token": "Token SCIM",
"SCIM tokens": "Tokens SCIM",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Esta acción no se puede deshacer. Su proveedor de identidad dejará de sincronizarse inmediatamente.",
"Toggle SCIM provisioning": "Activar o desactivar el aprovisionamiento SCIM",
"Token": "Token",
"Page menu": "Menú de la página",
"Expand": "Expandir",
"Collapse": "Contraer",
"Comment menu": "Menú de comentarios",
"Group menu": "Menú del grupo",
"Show hidden breadcrumbs": "Mostrar rutas de navegación ocultas",
"Breadcrumbs": "Rutas de navegación",
"Page actions": "Acciones de la página",
"Pick emoji": "Elegir emoji",
"Template menu": "Menú de plantillas",
"Chat menu": "Menú del chat",
"API key menu": "Menú de la clave API",
"Jump to comment selection": "Ir a la selección de comentarios",
"Slash commands": "Comandos de barra",
"Mention suggestions": "Sugerencias de menciones",
"Link suggestions": "Sugerencias de enlaces",
"Diagram editor": "Editor de diagramas",
"Add comment": "Agregar comentario",
"Find and replace": "Buscar y reemplazar",
"Main navigation": "Navegación principal",
"Space navigation": "Navegación del espacio",
"Settings navigation": "Navegación de configuración",
"AI navigation": "Navegación de IA",
"Breadcrumb": "Ruta de navegación",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} est disponible",
"Default page edit mode": "Mode d’édition par défaut de la page",
"Choose your preferred page edit mode. Avoid accidental edits.": "Choisissez votre mode d'édition de page préféré. Évitez les modifications accidentelles.",
"Choose {{format}} file": "Choisir un fichier {{format}}",
"Reading": "Lecture",
"Delete member": "Supprimer le membre",
"Member deleted successfully": "Membre supprimé avec succès",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "L'image dépasse la limite de 10 Mo.",
"Image removed successfully": "Image supprimée avec succès",
"API key": "Clé API",
"API key created successfully": "Clé API créée avec succès",
"API keys": "Clés API",
"API management": "Gestion des API",
"Are you sure you want to revoke this API key": "Êtes-vous sûr de vouloir révoquer cette clé API",
"Create API Key": "Créer une clé API",
"Custom expiration date": "Date d'expiration personnalisée",
"Enter a descriptive token name": "Entrez un nom descriptif pour le jeton",
"Expiration": "Expiration",
"Expired": "Expiré(e)",
"Expires": "Expire",
"I've saved my API key": "J'ai enregistré ma clé API",
"Last use": "Dernière utilisation",
"No API keys found": "Aucune clé API trouvée",
"No expiration": "Pas d'expiration",
"Revoke API key": "Révoquer la clé API",
"Revoked successfully": "Révoqué(e) avec succès",
"Select expiration date": "Sélectionnez la date d'expiration",
"This action cannot be undone. Any applications using this API key will stop working.": "Cette action ne peut pas être annulée. Toutes les applications utilisant cette clé API cesseront de fonctionner.",
"Update API key": "Mettre à jour la clé API",
"Update": "Mettre à jour",
"Update {{credential}}": "Mettre à jour {{credential}}",
"Manage API keys for all users in the workspace": "Gérer les clés API pour tous les utilisateurs dans l'espace de travail",
"Restrict API key creation to admins": "Restreindre la création de clés API aux administrateurs",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Seuls les administrateurs et les propriétaires peuvent créer de nouvelles clés API. Les clés des membres existants continueront de fonctionner.",
@@ -873,6 +870,12 @@
"Previous 7 days": "7 derniers jours",
"Previous 30 days": "30 derniers jours",
"Search chats...": "Rechercher des discussions...",
"Search chats": "Rechercher des discussions",
"Ask anything... Use @ to mention pages": "Demandez nimporte quoi… Utilisez @ pour mentionner des pages",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "Commencez une nouvelle discussion pour la voir ici.",
"Summarize this page": "Résumer cette page",
"Toggle AI Chat": "Basculer le chat IA",
@@ -880,5 +883,105 @@
"Try a different search term.": "Essayez un autre terme de recherche.",
"Try again": "Réessayer",
"Untitled chat": "Discussion sans titre",
"What can I help you with?": "Que puis-je faire pour vous aider ?"
"What can I help you with?": "Que puis-je faire pour vous aider ?",
"Are you sure you want to revoke this {{credential}}": "Êtes-vous sûr de vouloir révoquer ce/cette {{credential}}",
"Automatically provision users and groups from your identity provider via SCIM.": "Provisionnez automatiquement les utilisateurs et les groupes depuis votre fournisseur didentité via SCIM.",
"Configure your identity provider with this URL to provision users and groups.": "Configurez votre fournisseur didentité avec cette URL pour provisionner les utilisateurs et les groupes.",
"Create {{credential}}": "Créer {{credential}}",
"{{credential}} created": "{{credential}} créé",
"{{credential}} created successfully": "{{credential}} créé avec succès",
"Created by": "Créé par",
"Custom": "Personnalisé",
"Enable SCIM": "Activer SCIM",
"Enter a descriptive name": "Saisissez un nom descriptif",
"I've saved my {{credential}}": "Jai enregistré mon/ma {{credential}}",
"Important": "Important",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Assurez-vous de copier votre {{credential}} maintenant. Vous ne pourrez plus le/la voir ensuite !",
"Never": "Jamais",
"Revoke {{credential}}": "Révoquer {{credential}}",
"SCIM endpoint URL": "URL du point de terminaison SCIM",
"SCIM provisioning": "Provisionnement SCIM",
"SCIM takes precedence over SSO group sync while enabled.": "SCIM a priorité sur la synchronisation des groupes SSO lorsquil est activé.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "Vous avez atteint le maximum de {{max}} jetons SCIM. Supprimez un jeton existant pour en créer un nouveau.",
"SCIM token": "Jeton SCIM",
"SCIM tokens": "Jetons SCIM",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Cette action est irréversible. Votre fournisseur didentité cessera immédiatement la synchronisation.",
"Toggle SCIM provisioning": "Activer/désactiver le provisionnement SCIM",
"Token": "Jeton",
"Page menu": "Menu de la page",
"Expand": "Développer",
"Collapse": "Réduire",
"Comment menu": "Menu du commentaire",
"Group menu": "Menu du groupe",
"Show hidden breadcrumbs": "Afficher les fils dAriane masqués",
"Breadcrumbs": "Fils dAriane",
"Page actions": "Actions de la page",
"Pick emoji": "Choisir un emoji",
"Template menu": "Menu du modèle",
"Chat menu": "Menu du chat",
"API key menu": "Menu de la clé API",
"Jump to comment selection": "Aller à la sélection de commentaires",
"Slash commands": "Commandes slash",
"Mention suggestions": "Suggestions de mention",
"Link suggestions": "Suggestions de liens",
"Diagram editor": "Éditeur de diagrammes",
"Add comment": "Ajouter un commentaire",
"Find and replace": "Rechercher et remplacer",
"Main navigation": "Navigation principale",
"Space navigation": "Navigation de lespace",
"Settings navigation": "Navigation des paramètres",
"AI navigation": "Navigation IA",
"Breadcrumb": "Fil dAriane",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} è disponibile",
"Default page edit mode": "Modalità di modifica predefinita della pagina",
"Choose your preferred page edit mode. Avoid accidental edits.": "Scegli la tua modalità di modifica della pagina preferita. Evita modifiche accidentali.",
"Choose {{format}} file": "Scegli file {{format}}",
"Reading": "Lettura",
"Delete member": "Elimina membro",
"Member deleted successfully": "Membro eliminato con successo",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "L'immagine supera il limite di 10MB.",
"Image removed successfully": "Immagine rimossa con successo",
"API key": "Chiave API",
"API key created successfully": "Chiave API creata con successo",
"API keys": "Chiavi API",
"API management": "Gestione API",
"Are you sure you want to revoke this API key": "Sei sicuro di voler revocare questa chiave API",
"Create API Key": "Crea Chiave API",
"Custom expiration date": "Data di scadenza personalizzata",
"Enter a descriptive token name": "Inserisci un nome descrittivo del token",
"Expiration": "Scadenza",
"Expired": "Scaduto",
"Expires": "Scade",
"I've saved my API key": "Ho salvato la mia chiave API",
"Last use": "Ultimo utilizzo",
"No API keys found": "Nessuna chiave API trovata",
"No expiration": "Nessuna scadenza",
"Revoke API key": "Revoca chiave API",
"Revoked successfully": "Revocata con successo",
"Select expiration date": "Seleziona la data di scadenza",
"This action cannot be undone. Any applications using this API key will stop working.": "Questa azione non può essere annullata. Qualsiasi applicazione che utilizza questa chiave API smetterà di funzionare.",
"Update API key": "Aggiorna chiave API",
"Update": "Aggiorna",
"Update {{credential}}": "Aggiorna {{credential}}",
"Manage API keys for all users in the workspace": "Gestisci le chiavi API per tutti gli utenti nell'area di lavoro",
"Restrict API key creation to admins": "Limita la creazione delle chiavi API agli amministratori",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Solo gli amministratori e i proprietari possono creare nuove chiavi API. Le chiavi dei membri esistenti continueranno a funzionare.",
@@ -873,6 +870,12 @@
"Previous 7 days": "Ultimi 7 giorni",
"Previous 30 days": "Ultimi 30 giorni",
"Search chats...": "Cerca nelle chat...",
"Search chats": "Cerca nelle chat",
"Ask anything... Use @ to mention pages": "Chiedi qualsiasi cosa... Usa @ per menzionare le pagine",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "Avvia una nuova chat per vederla qui.",
"Summarize this page": "Riassumi questa pagina",
"Toggle AI Chat": "Attiva/disattiva Chat IA",
@@ -880,5 +883,105 @@
"Try a different search term.": "Prova un termine di ricerca diverso.",
"Try again": "Riprova",
"Untitled chat": "Chat senza titolo",
"What can I help you with?": "Con cosa posso aiutarti?"
"What can I help you with?": "Con cosa posso aiutarti?",
"Are you sure you want to revoke this {{credential}}": "Sei sicuro di voler revocare questa {{credential}}",
"Automatically provision users and groups from your identity provider via SCIM.": "Esegui automaticamente il provisioning di utenti e gruppi dal tuo provider di identità tramite SCIM.",
"Configure your identity provider with this URL to provision users and groups.": "Configura il tuo provider di identità con questo URL per eseguire il provisioning di utenti e gruppi.",
"Create {{credential}}": "Crea {{credential}}",
"{{credential}} created": "{{credential}} creata",
"{{credential}} created successfully": "{{credential}} creata con successo",
"Created by": "Creata da",
"Custom": "Personalizzato",
"Enable SCIM": "Abilita SCIM",
"Enter a descriptive name": "Inserisci un nome descrittivo",
"I've saved my {{credential}}": "Ho salvato la mia {{credential}}",
"Important": "Importante",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Assicurati di copiare subito la tua {{credential}}. Non potrai più visualizzarla!",
"Never": "Mai",
"Revoke {{credential}}": "Revoca {{credential}}",
"SCIM endpoint URL": "URL dell'endpoint SCIM",
"SCIM provisioning": "Provisioning SCIM",
"SCIM takes precedence over SSO group sync while enabled.": "SCIM ha la precedenza sulla sincronizzazione dei gruppi SSO quando è abilitato.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "Hai raggiunto il numero massimo di {{max}} token SCIM. Elimina un token esistente per crearne uno nuovo.",
"SCIM token": "Token SCIM",
"SCIM tokens": "Token SCIM",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Questa azione non può essere annullata. Il tuo provider di identità smetterà di sincronizzarsi immediatamente.",
"Toggle SCIM provisioning": "Attiva/disattiva il provisioning SCIM",
"Token": "Token",
"Page menu": "Menu della pagina",
"Expand": "Espandi",
"Collapse": "Comprimi",
"Comment menu": "Menu dei commenti",
"Group menu": "Menu del gruppo",
"Show hidden breadcrumbs": "Mostra breadcrumb nascosti",
"Breadcrumbs": "Breadcrumb",
"Page actions": "Azioni della pagina",
"Pick emoji": "Scegli emoji",
"Template menu": "Menu del modello",
"Chat menu": "Menu della chat",
"API key menu": "Menu della chiave API",
"Jump to comment selection": "Vai alla selezione dei commenti",
"Slash commands": "Comandi slash",
"Mention suggestions": "Suggerimenti di menzione",
"Link suggestions": "Suggerimenti di link",
"Diagram editor": "Editor di diagrammi",
"Add comment": "Aggiungi commento",
"Find and replace": "Trova e sostituisci",
"Main navigation": "Navigazione principale",
"Space navigation": "Navigazione dello spazio",
"Settings navigation": "Navigazione delle impostazioni",
"AI navigation": "Navigazione AI",
"Breadcrumb": "Percorso di navigazione",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} が利用可能です",
"Default page edit mode": "デフォルトのページ編集モード",
"Choose your preferred page edit mode. Avoid accidental edits.": "お好みのページ編集モードを選択してください(誤編集を防止します)",
"Choose {{format}} file": "{{format}} ファイルを選択",
"Reading": "閲覧",
"Delete member": "メンバーを削除",
"Member deleted successfully": "メンバーが正常に削除されました",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "画像が10MBの制限を超えています",
"Image removed successfully": "画像を削除しました",
"API key": "APIキー",
"API key created successfully": "APIキーを作成しました",
"API keys": "APIキー",
"API management": "API管理",
"Are you sure you want to revoke this API key": "このAPIキーを無効にしてもよろしいですか",
"Create API Key": "APIキーを作成",
"Custom expiration date": "カスタム有効期限",
"Enter a descriptive token name": "説明的なトークン名を入力してください",
"Expiration": "有効期限",
"Expired": "期限切れ",
"Expires": "期限が切れます",
"I've saved my API key": "APIキーを保存しました",
"Last use": "最終使用",
"No API keys found": "APIキーが見つかりません",
"No expiration": "期限なし",
"Revoke API key": "APIキーを無効にする",
"Revoked successfully": "無効にしました",
"Select expiration date": "有効期限を選択してください",
"This action cannot be undone. Any applications using this API key will stop working.": "この操作は取り消せません。このAPIキーを使用しているアプリケーションは動作しなくなります",
"Update API key": "APIキーを更新",
"Update": "更新",
"Update {{credential}}": "{{credential}}を更新",
"Manage API keys for all users in the workspace": "ワークスペース内のすべてのユーザーのAPIキーを管理",
"Restrict API key creation to admins": "APIキーの作成を管理者のみに制限する",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "新しいAPIキーを作成できるのは管理者とオーナーのみです。既存のメンバーキーは引き続き有効です。",
@@ -873,6 +870,12 @@
"Previous 7 days": "過去 7 日間",
"Previous 30 days": "過去 30 日間",
"Search chats...": "チャットを検索...",
"Search chats": "チャットを検索",
"Ask anything... Use @ to mention pages": "何でも質問してください… @ を使ってページにメンションできます",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "ここに表示するには新しいチャットを開始してください。",
"Summarize this page": "このページを要約",
"Toggle AI Chat": "AI チャットを切り替え",
@@ -880,5 +883,105 @@
"Try a different search term.": "別の検索語を試してください。",
"Try again": "再試行",
"Untitled chat": "無題のチャット",
"What can I help you with?": "何をお手伝いしましょうか?"
"What can I help you with?": "何をお手伝いしましょうか?",
"Are you sure you want to revoke this {{credential}}": "この{{credential}}を無効にしてもよろしいですか",
"Automatically provision users and groups from your identity provider via SCIM.": "SCIM を介して、ID プロバイダーからユーザーとグループを自動的にプロビジョニングします。",
"Configure your identity provider with this URL to provision users and groups.": "この URL を使用して ID プロバイダーを設定し、ユーザーとグループをプロビジョニングします。",
"Create {{credential}}": "{{credential}}を作成",
"{{credential}} created": "{{credential}}を作成しました",
"{{credential}} created successfully": "{{credential}}を正常に作成しました",
"Created by": "作成者",
"Custom": "カスタム",
"Enable SCIM": "SCIM を有効にする",
"Enter a descriptive name": "説明的な名前を入力してください",
"I've saved my {{credential}}": "{{credential}}を保存しました",
"Important": "重要",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "今すぐ {{credential}} をコピーしてください。後でもう一度表示することはできません!",
"Never": "なし",
"Revoke {{credential}}": "{{credential}}を無効にする",
"SCIM endpoint URL": "SCIM エンドポイント URL",
"SCIM provisioning": "SCIM プロビジョニング",
"SCIM takes precedence over SSO group sync while enabled.": "有効になっている間は、SCIM が SSO グループ同期より優先されます。",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "SCIM トークンの上限 {{max}} に達しました。新しいトークンを作成するには、既存のトークンを削除してください。",
"SCIM token": "SCIM トークン",
"SCIM tokens": "SCIM トークン",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "この操作は元に戻せません。ID プロバイダーは直ちに同期を停止します。",
"Toggle SCIM provisioning": "SCIM プロビジョニングを切り替える",
"Token": "トークン",
"Page menu": "ページメニュー",
"Expand": "展開",
"Collapse": "折りたたむ",
"Comment menu": "コメントメニュー",
"Group menu": "グループメニュー",
"Show hidden breadcrumbs": "非表示のパンくずリストを表示",
"Breadcrumbs": "パンくずリスト",
"Page actions": "ページアクション",
"Pick emoji": "絵文字を選択",
"Template menu": "テンプレートメニュー",
"Chat menu": "チャットメニュー",
"API key menu": "API キーメニュー",
"Jump to comment selection": "コメント選択に移動",
"Slash commands": "スラッシュコマンド",
"Mention suggestions": "メンション候補",
"Link suggestions": "リンク候補",
"Diagram editor": "ダイアグラムエディター",
"Add comment": "コメントを追加",
"Find and replace": "検索と置換",
"Main navigation": "メインナビゲーション",
"Space navigation": "スペースナビゲーション",
"Settings navigation": "設定ナビゲーション",
"AI navigation": "AI ナビゲーション",
"Breadcrumb": "パンくずリスト",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} 버전을 사용할 수 있습니다",
"Default page edit mode": "기본 페이지 편집 모드",
"Choose your preferred page edit mode. Avoid accidental edits.": "선호하는 페이지 편집 모드를 선택하세요. 실수로 인한 편집을 방지하세요.",
"Choose {{format}} file": "{{format}} 파일 선택",
"Reading": "읽기",
"Delete member": "멤버 삭제",
"Member deleted successfully": "멤버가 성공적으로 삭제되었습니다",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "이미지가 10MB 용량 제한을 초과합니다.",
"Image removed successfully": "이미지가 성공적으로 제거되었습니다",
"API key": "API 키",
"API key created successfully": "API 키 생성 완료",
"API keys": "API 키",
"API management": "API 관리",
"Are you sure you want to revoke this API key": "이 API 키를 취소하시겠습니까?",
"Create API Key": "API 키 생성",
"Custom expiration date": "사용자 정의 만료일",
"Enter a descriptive token name": "토큰 이름을 입력하세요",
"Expiration": "만료",
"Expired": "만료됨",
"Expires": "만료일",
"I've saved my API key": "API 키를 저장했습니다",
"Last use": "최근 사용",
"No API keys found": "API 키를 찾을 수 없습니다",
"No expiration": "유효기간 없음",
"Revoke API key": "API 키 취소",
"Revoked successfully": "성공적으로 취소되었습니다",
"Select expiration date": "만료일 선택",
"This action cannot be undone. Any applications using this API key will stop working.": "이 작업은 되돌릴 수 없습니다. 이 API 키를 사용하는 모든 응용 프로그램이 작동을 멈출 것입니다.",
"Update API key": "API 키 갱신",
"Update": "업데이트",
"Update {{credential}}": "{{credential}} 업데이트",
"Manage API keys for all users in the workspace": "워크스페이스 내 모든 사용자의 API 키 관리",
"Restrict API key creation to admins": "API 키 생성 권한을 관리자에게만 제한합니다",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "새로운 API 키는 관리자와 소유자만 생성할 수 있습니다. 기존 멤버 키는 계속 사용할 수 있습니다.",
@@ -873,6 +870,12 @@
"Previous 7 days": "지난 7일",
"Previous 30 days": "지난 30일",
"Search chats...": "채팅 검색...",
"Search chats": "채팅 검색",
"Ask anything... Use @ to mention pages": "무엇이든 물어보세요... 페이지를 언급하려면 @를 사용하세요",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "여기에 표시하려면 새 채팅을 시작하세요.",
"Summarize this page": "이 페이지 요약",
"Toggle AI Chat": "AI 채팅 전환",
@@ -880,5 +883,105 @@
"Try a different search term.": "다른 검색어를 사용해 보세요.",
"Try again": "다시 시도",
"Untitled chat": "제목 없는 채팅",
"What can I help you with?": "무엇을 도와드릴까요?"
"What can I help you with?": "무엇을 도와드릴까요?",
"Are you sure you want to revoke this {{credential}}": "이 {{credential}}을 취소하시겠습니까?",
"Automatically provision users and groups from your identity provider via SCIM.": "SCIM을 통해 ID 공급자에서 사용자와 그룹을 자동으로 프로비저닝합니다.",
"Configure your identity provider with this URL to provision users and groups.": "사용자와 그룹을 프로비저닝할 수 있도록 이 URL로 ID 공급자를 구성하세요.",
"Create {{credential}}": "{{credential}} 만들기",
"{{credential}} created": "{{credential}} 생성됨",
"{{credential}} created successfully": "{{credential}} 생성 완료",
"Created by": "생성한 사람",
"Custom": "사용자 지정",
"Enable SCIM": "SCIM 활성화",
"Enter a descriptive name": "설명적인 이름을 입력하세요",
"I've saved my {{credential}}": "내 {{credential}}를 저장했습니다",
"Important": "중요",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "지금 {{credential}}를 복사해 두세요. 다시는 볼 수 없습니다!",
"Never": "안 함",
"Revoke {{credential}}": "{{credential}} 취소",
"SCIM endpoint URL": "SCIM 엔드포인트 URL",
"SCIM provisioning": "SCIM 프로비저닝",
"SCIM takes precedence over SSO group sync while enabled.": "SCIM이 활성화되어 있는 동안에는 SSO 그룹 동기화보다 SCIM이 우선 적용됩니다.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "SCIM 토큰은 최대 {{max}}개까지 만들 수 있습니다. 새 토큰을 만들려면 기존 토큰을 삭제하세요.",
"SCIM token": "SCIM 토큰",
"SCIM tokens": "SCIM 토큰",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "이 작업은 되돌릴 수 없습니다. ID 공급자가 즉시 동기화를 중지합니다.",
"Toggle SCIM provisioning": "SCIM 프로비저닝 전환",
"Token": "토큰",
"Page menu": "페이지 메뉴",
"Expand": "펼치기",
"Collapse": "접기",
"Comment menu": "댓글 메뉴",
"Group menu": "그룹 메뉴",
"Show hidden breadcrumbs": "숨겨진 이동 경로 표시",
"Breadcrumbs": "이동 경로",
"Page actions": "페이지 작업",
"Pick emoji": "이모지 선택",
"Template menu": "템플릿 메뉴",
"Chat menu": "채팅 메뉴",
"API key menu": "API 키 메뉴",
"Jump to comment selection": "댓글 선택으로 이동",
"Slash commands": "슬래시 명령어",
"Mention suggestions": "멘션 추천",
"Link suggestions": "링크 추천",
"Diagram editor": "다이어그램 편집기",
"Add comment": "댓글 추가",
"Find and replace": "찾기 및 바꾸기",
"Main navigation": "기본 탐색",
"Space navigation": "스페이스 탐색",
"Settings navigation": "설정 탐색",
"AI navigation": "AI 탐색",
"Breadcrumb": "이동 경로",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} is beschikbaar",
"Default page edit mode": "Standaard bewerkingsmodus voor pagina",
"Choose your preferred page edit mode. Avoid accidental edits.": "Kies uw voorkeurs bewerkmodus voor pagina's. Vermijd per ongeluk bewerken.",
"Choose {{format}} file": "Kies {{format}}-bestand",
"Reading": "Lezen",
"Delete member": "Lid verwijderen",
"Member deleted successfully": "Lid succesvol verwijderd",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "Afbeelding overschrijdt de limiet van 10MB.",
"Image removed successfully": "Afbeelding succesvol verwijderd",
"API key": "API-sleutel",
"API key created successfully": "API-sleutel succesvol aangemaakt",
"API keys": "API-sleutels",
"API management": "API-beheer",
"Are you sure you want to revoke this API key": "Weet u zeker dat u deze API-sleutel wilt intrekken",
"Create API Key": "API-sleutel aanmaken",
"Custom expiration date": "Aangepaste vervaldatum",
"Enter a descriptive token name": "Voer een beschrijvende tokennaam in",
"Expiration": "Vervaldatum",
"Expired": "Verlopen",
"Expires": "Verloopt",
"I've saved my API key": "Ik heb mijn API-sleutel opgeslagen",
"Last use": "Laatst gebruikt",
"No API keys found": "Geen API-sleutels gevonden",
"No expiration": "Geen vervaldatum",
"Revoke API key": "API-sleutel intrekken",
"Revoked successfully": "Succesvol ingetrokken",
"Select expiration date": "Selecteer vervaldatum",
"This action cannot be undone. Any applications using this API key will stop working.": "Deze actie kan niet ongedaan worden gemaakt. Alle toepassingen die deze API-sleutel gebruiken, zullen niet meer werken.",
"Update API key": "API-sleutel bijwerken",
"Update": "Bijwerken",
"Update {{credential}}": "{{credential}} bijwerken",
"Manage API keys for all users in the workspace": "Beheer API-sleutels voor alle gebruikers in de werkruimte",
"Restrict API key creation to admins": "Beperk het aanmaken van API-sleutels tot beheerders.",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Alleen beheerders en eigenaren kunnen nieuwe API-sleutels aanmaken. Bestaande leden-sleutels blijven werken.",
@@ -873,6 +870,12 @@
"Previous 7 days": "Afgelopen 7 dagen",
"Previous 30 days": "Afgelopen 30 dagen",
"Search chats...": "Chats zoeken...",
"Search chats": "Chats zoeken",
"Ask anything... Use @ to mention pages": "Vraag iets... Gebruik @ om pagina's te vermelden",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "Start een nieuwe chat om die hier te zien.",
"Summarize this page": "Vat deze pagina samen",
"Toggle AI Chat": "AI-chat in-/uitschakelen",
@@ -880,5 +883,105 @@
"Try a different search term.": "Probeer een andere zoekterm.",
"Try again": "Probeer opnieuw",
"Untitled chat": "Chat zonder titel",
"What can I help you with?": "Waar kan ik je mee helpen?"
"What can I help you with?": "Waar kan ik je mee helpen?",
"Are you sure you want to revoke this {{credential}}": "Weet u zeker dat u deze {{credential}} wilt intrekken",
"Automatically provision users and groups from your identity provider via SCIM.": "Voorzie gebruikers en groepen automatisch vanuit uw identiteitsprovider via SCIM.",
"Configure your identity provider with this URL to provision users and groups.": "Configureer uw identiteitsprovider met deze URL om gebruikers en groepen te provisioneren.",
"Create {{credential}}": "{{credential}} maken",
"{{credential}} created": "{{credential}} aangemaakt",
"{{credential}} created successfully": "{{credential}} succesvol aangemaakt",
"Created by": "Aangemaakt door",
"Custom": "Aangepast",
"Enable SCIM": "SCIM inschakelen",
"Enter a descriptive name": "Voer een beschrijvende naam in",
"I've saved my {{credential}}": "Ik heb mijn {{credential}} opgeslagen",
"Important": "Belangrijk",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Zorg ervoor dat u uw {{credential}} nu kopieert. U kunt deze niet meer bekijken!",
"Never": "Nooit",
"Revoke {{credential}}": "{{credential}} intrekken",
"SCIM endpoint URL": "SCIM-eindpunt-URL",
"SCIM provisioning": "SCIM-provisioning",
"SCIM takes precedence over SSO group sync while enabled.": "SCIM heeft voorrang op SSO-groepssynchronisatie zolang het is ingeschakeld.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "U heeft het maximum van {{max}} SCIM-tokens bereikt. Verwijder een bestaand token om een nieuw token aan te maken.",
"SCIM token": "SCIM-token",
"SCIM tokens": "SCIM-tokens",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Deze actie kan niet ongedaan worden gemaakt. Uw identiteitsprovider stopt onmiddellijk met synchroniseren.",
"Toggle SCIM provisioning": "SCIM-provisioning in-/uitschakelen",
"Token": "Token",
"Page menu": "Paginamenu",
"Expand": "Uitvouwen",
"Collapse": "Samenvouwen",
"Comment menu": "Reactiemenu",
"Group menu": "Groepsmenu",
"Show hidden breadcrumbs": "Verborgen broodkruimels weergeven",
"Breadcrumbs": "Broodkruimels",
"Page actions": "Pagina-acties",
"Pick emoji": "Emoji kiezen",
"Template menu": "Sjabloonmenu",
"Chat menu": "Chatmenu",
"API key menu": "API-sleutelmenu",
"Jump to comment selection": "Naar reactieselectie springen",
"Slash commands": "Slash-opdrachten",
"Mention suggestions": "Vermeldingssuggesties",
"Link suggestions": "Linksuggesties",
"Diagram editor": "Diagrameditor",
"Add comment": "Reactie toevoegen",
"Find and replace": "Zoeken en vervangen",
"Main navigation": "Hoofdnavigatie",
"Space navigation": "Ruimtenavigatie",
"Settings navigation": "Instellingennavigatie",
"AI navigation": "AI-navigatie",
"Breadcrumb": "Broodkruimel",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} está disponível",
"Default page edit mode": "Modo padrão de edição da página",
"Choose your preferred page edit mode. Avoid accidental edits.": "Escolha o modo de edição de página preferido. Evite edições acidentais.",
"Choose {{format}} file": "Escolher arquivo {{format}}",
"Reading": "Leitura",
"Delete member": "Excluir membro",
"Member deleted successfully": "Membro excluído com sucesso",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "A imagem excede o limite de 10MB.",
"Image removed successfully": "Imagem removida com sucesso",
"API key": "Chave API",
"API key created successfully": "Chave API criada com sucesso",
"API keys": "Chaves API",
"API management": "Gestão de API",
"Are you sure you want to revoke this API key": "Tem certeza de que deseja revogar esta chave API",
"Create API Key": "Criar Chave API",
"Custom expiration date": "Data de expiração personalizada",
"Enter a descriptive token name": "Insira um nome descritivo para o token",
"Expiration": "Expiração",
"Expired": "Expirado",
"Expires": "Expira",
"I've saved my API key": "Salvei minha chave API",
"Last use": "Último uso",
"No API keys found": "Nenhuma chave API encontrada",
"No expiration": "Sem expiração",
"Revoke API key": "Revogar chave API",
"Revoked successfully": "Revogada com sucesso",
"Select expiration date": "Selecionar data de expiração",
"This action cannot be undone. Any applications using this API key will stop working.": "Esta ação não pode ser desfeita. Qualquer aplicação usando esta chave API deixará de funcionar.",
"Update API key": "Atualizar chave API",
"Update": "Atualizar",
"Update {{credential}}": "Atualizar {{credential}}",
"Manage API keys for all users in the workspace": "Gerenciar chaves API para todos os usuários no espaço de trabalho",
"Restrict API key creation to admins": "Restringir a criação de chave de API aos administradores",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Somente administradores e proprietários podem criar novas chaves de API. As chaves de membros já existentes continuarão funcionando.",
@@ -873,6 +870,12 @@
"Previous 7 days": "Últimos 7 dias",
"Previous 30 days": "Últimos 30 dias",
"Search chats...": "Pesquisar chats...",
"Search chats": "Pesquisar chats",
"Ask anything... Use @ to mention pages": "Pergunte qualquer coisa... Use @ para mencionar páginas",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "Inicie um novo chat para vê-lo aqui.",
"Summarize this page": "Resumir esta página",
"Toggle AI Chat": "Alternar chat com IA",
@@ -880,5 +883,105 @@
"Try a different search term.": "Tente um termo de pesquisa diferente.",
"Try again": "Tentar novamente",
"Untitled chat": "Chat sem título",
"What can I help you with?": "Com o que posso ajudar você?"
"What can I help you with?": "Com o que posso ajudar você?",
"Are you sure you want to revoke this {{credential}}": "Tem certeza de que deseja revogar esta {{credential}}",
"Automatically provision users and groups from your identity provider via SCIM.": "Provisione automaticamente usuários e grupos do seu provedor de identidade via SCIM.",
"Configure your identity provider with this URL to provision users and groups.": "Configure seu provedor de identidade com esta URL para provisionar usuários e grupos.",
"Create {{credential}}": "Criar {{credential}}",
"{{credential}} created": "{{credential}} criada",
"{{credential}} created successfully": "{{credential}} criada com sucesso",
"Created by": "Criado por",
"Custom": "Personalizado",
"Enable SCIM": "Ativar SCIM",
"Enter a descriptive name": "Insira um nome descritivo",
"I've saved my {{credential}}": "Salvei minha {{credential}}",
"Important": "Importante",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Copie sua {{credential}} agora. Você não poderá vê-la novamente!",
"Never": "Nunca",
"Revoke {{credential}}": "Revogar {{credential}}",
"SCIM endpoint URL": "URL do endpoint SCIM",
"SCIM provisioning": "Provisionamento SCIM",
"SCIM takes precedence over SSO group sync while enabled.": "O SCIM tem precedência sobre a sincronização de grupos por SSO enquanto estiver ativado.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "Você atingiu o máximo de {{max}} tokens SCIM. Exclua um token existente para criar um novo.",
"SCIM token": "Token SCIM",
"SCIM tokens": "Tokens SCIM",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Esta ação não pode ser desfeita. Seu provedor de identidade deixará de sincronizar imediatamente.",
"Toggle SCIM provisioning": "Alternar provisionamento SCIM",
"Token": "Token",
"Page menu": "Menu da página",
"Expand": "Expandir",
"Collapse": "Recolher",
"Comment menu": "Menu de comentários",
"Group menu": "Menu do grupo",
"Show hidden breadcrumbs": "Mostrar breadcrumbs ocultos",
"Breadcrumbs": "Trilhas de navegação",
"Page actions": "Ações da página",
"Pick emoji": "Escolher emoji",
"Template menu": "Menu do modelo",
"Chat menu": "Menu do chat",
"API key menu": "Menu da chave de API",
"Jump to comment selection": "Ir para a seleção de comentários",
"Slash commands": "Comandos de barra",
"Mention suggestions": "Sugestões de menção",
"Link suggestions": "Sugestões de links",
"Diagram editor": "Editor de diagramas",
"Add comment": "Adicionar comentário",
"Find and replace": "Localizar e substituir",
"Main navigation": "Navegação principal",
"Space navigation": "Navegação do espaço",
"Settings navigation": "Navegação de configurações",
"AI navigation": "Navegação de IA",
"Breadcrumb": "Trilha de navegação",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "Доступна версия {{latestVersion}}",
"Default page edit mode": "Режим редактирования страницы по умолчанию",
"Choose your preferred page edit mode. Avoid accidental edits.": "Выберите предпочитаемый режим редактирования страницы. Избегайте случайных изменений.",
"Choose {{format}} file": "Выберите файл {{format}}",
"Reading": "Чтение",
"Delete member": "Удалить участника",
"Member deleted successfully": "Участник успешно удалён",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "Изображение превышает предел 10MB.",
"Image removed successfully": "Изображение успешно удалено",
"API key": "API ключ",
"API key created successfully": "API ключ успешно создан",
"API keys": "API ключи",
"API management": "Управление API",
"Are you sure you want to revoke this API key": "Вы уверены, что хотите отозвать этот API ключ",
"Create API Key": "Создать API ключ",
"Custom expiration date": "Пользовательская дата срока действия",
"Enter a descriptive token name": "Введите понятное имя токена",
"Expiration": "Срок действия",
"Expired": "Истек",
"Expires": "Истекает",
"I've saved my API key": "Я сохранил мой API ключ",
"Last use": "Последнее использование",
"No API keys found": "API ключи не найдены",
"No expiration": "Не истекает",
"Revoke API key": "Отозвать API ключ",
"Revoked successfully": "Отозван успешно",
"Select expiration date": "Выберете срок действия",
"This action cannot be undone. Any applications using this API key will stop working.": "Это действие необратимо. Любые приложения, использующие этот API ключ, перестанут работать.",
"Update API key": "Обновить API ключ",
"Update": "Обновить",
"Update {{credential}}": "Обновить {{credential}}",
"Manage API keys for all users in the workspace": "Управлять API ключами для всех пользователей в рабочей области",
"Restrict API key creation to admins": "Ограничить создание API-ключей только администраторами.",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Только администраторы и владельцы могут создавать новые API-ключи. Существующие ключи участников продолжат работать.",
@@ -873,6 +870,12 @@
"Previous 7 days": "Предыдущие 7 дней",
"Previous 30 days": "Предыдущие 30 дней",
"Search chats...": "Поиск чатов...",
"Search chats": "Поиск чатов",
"Ask anything... Use @ to mention pages": "Спросите что угодно... Используйте @, чтобы упомянуть страницы",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Добро пожаловать в {{name}}",
"Add files": "Добавить файлы",
"Mention a page": "Упомянуть страницу",
"Start a new chat to see it here.": "Начните новый чат, чтобы увидеть его здесь.",
"Summarize this page": "Суммировать эту страницу",
"Toggle AI Chat": "Переключить чат с ИИ",
@@ -880,5 +883,105 @@
"Try a different search term.": "Попробуйте другой поисковый запрос.",
"Try again": "Попробовать снова",
"Untitled chat": "Чат без названия",
"What can I help you with?": "Чем я могу вам помочь?"
"What can I help you with?": "Чем я могу вам помочь?",
"Are you sure you want to revoke this {{credential}}": "Вы уверены, что хотите отозвать этот {{credential}}",
"Automatically provision users and groups from your identity provider via SCIM.": "Автоматически предоставляйте доступ пользователям и группам из вашего провайдера удостоверений через SCIM.",
"Configure your identity provider with this URL to provision users and groups.": "Настройте ваш провайдер удостоверений с этим URL для предоставления доступа пользователям и группам.",
"Create {{credential}}": "Создать {{credential}}",
"{{credential}} created": "{{credential}} создан",
"{{credential}} created successfully": "{{credential}} успешно создан",
"Created by": "Создан",
"Custom": "Пользовательский",
"Enable SCIM": "Включить SCIM",
"Enter a descriptive name": "Введите понятное имя",
"I've saved my {{credential}}": "Я сохранил свой {{credential}}",
"Important": "Важно",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Обязательно скопируйте ваш {{credential}} сейчас. Позже вы не сможете увидеть его снова!",
"Never": "Никогда",
"Revoke {{credential}}": "Отозвать {{credential}}",
"SCIM endpoint URL": "URL конечной точки SCIM",
"SCIM provisioning": "SCIM-подготовка учетных записей",
"SCIM takes precedence over SSO group sync while enabled.": "Пока SCIM включен, он имеет приоритет над синхронизацией групп через SSO.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "Вы достигли максимального количества токенов SCIM: {{max}}. Удалите существующий токен, чтобы создать новый.",
"SCIM token": "Токен SCIM",
"SCIM tokens": "Токены SCIM",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Это действие нельзя отменить. Ваш провайдер удостоверений немедленно прекратит синхронизацию.",
"Toggle SCIM provisioning": "Переключить подготовку учетных записей SCIM",
"Token": "Токен",
"Page menu": "Меню страницы",
"Expand": "Развернуть",
"Collapse": "Свернуть",
"Comment menu": "Меню комментария",
"Group menu": "Меню группы",
"Show hidden breadcrumbs": "Показать скрытые хлебные крошки",
"Breadcrumbs": "Хлебные крошки",
"Page actions": "Действия со страницей",
"Pick emoji": "Выбрать эмодзи",
"Template menu": "Меню шаблона",
"Chat menu": "Меню чата",
"API key menu": "Меню API-ключа",
"Jump to comment selection": "Перейти к выбору комментария",
"Slash commands": "Команды со слешем",
"Mention suggestions": "Подсказки упоминаний",
"Link suggestions": "Подсказки ссылок",
"Diagram editor": "Редактор диаграмм",
"Add comment": "Добавить комментарий",
"Find and replace": "Найти и заменить",
"Main navigation": "Основная навигация",
"Space navigation": "Навигация по пространству",
"Settings navigation": "Навигация по настройкам",
"AI navigation": "Навигация ИИ",
"Breadcrumb": "Хлебная крошка",
"Synced block": "Синхронизированный блок",
"Create a block that stays in sync across pages.": "Создайте блок, который будет синхронизироваться между страницами.",
"Editing original": "Редактирование оригинала",
"Copy synced block": "Скопировать синхронизированный блок",
"Unsync": "Не синхронизировать",
"Delete synced block": "Удалить синхронизированный блок",
"Synced to {{count}} other page_one": "Синхронизировано с {{count}} с другой страницей",
"Synced to {{count}} other page_other": "Синхронизировано с {{count}} с другими страницами",
"ORIGINAL": "ОРИГИНАЛ",
"THIS PAGE": "ЭТА СТРАНИЦА",
"No pages": "Нет страниц",
"The original synced block no longer exists": "Исходный синхронизированный блок больше не существует",
"You don't have access to this synced block": "У вас нет доступа к этому синхронизированному блоку",
"Failed to load this synced block": "Не удалось загрузить этот синхронизированный блок",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Подстрочный",
"Superscript": "Надстрочный",
"Inline code": "Встроенный код",
"Insert media": "Вставить медиа",
"Mention": "Упоминание",
"Emoji": "Эмодзи",
"Columns": "Столбцы",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Диаграммы",
"Advanced": "Дополнительно",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Очистить форматирование",
"Code block": "Блок кода",
"Experimental": "Experimental",
"Strikethrough": "Зачеркивание",
"Undo": "Отменить",
"Redo": "Повторить",
"Backlinks": "Обратные ссылки",
"Last updated by": "Последний изменивший",
"Last updated": "Последнее обновление",
"Stats": "Статистика",
"Word count": "Количество слов",
"Characters": "Символы",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "На эту страницу пока что нет ссылок.",
"This page doesn't link to other pages yet.": "Эта страница пока не содержит ссылок на другие страницы.",
"Verified until {{date}}": "Подтверждено до: {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "Доступна версія {{latestVersion}}",
"Default page edit mode": "Режим редагування сторінки за замовчуванням",
"Choose your preferred page edit mode. Avoid accidental edits.": "Виберіть бажаний режим редагування сторінки. Уникайте випадкових редагувань.",
"Choose {{format}} file": "Виберіть файл {{format}}",
"Reading": "Читання",
"Delete member": "Видалити учасника",
"Member deleted successfully": "Учасника успішно видалено",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "Зображення має займати менше, ніж 10 МБ.",
"Image removed successfully": "Зображення видалено",
"API key": "Ключ API",
"API key created successfully": "Ключ API успішно створено",
"API keys": "Ключі API",
"API management": "Управління API",
"Are you sure you want to revoke this API key": "Ви впевнені, що хочете відкликати цей ключ API",
"Create API Key": "Створити ключ API",
"Custom expiration date": "Користувацька дата закінчення",
"Enter a descriptive token name": "Введіть описову назву токена",
"Expiration": "Термін дії",
"Expired": "Закінчився",
"Expires": "Закінчується",
"I've saved my API key": "Я зберіг свій ключ API",
"Last use": "Останнє використання",
"No API keys found": "Ключі API не знайдено",
"No expiration": "Без терміну дії",
"Revoke API key": "Відкликати ключ API",
"Revoked successfully": "Успішно відкликано",
"Select expiration date": "Виберіть дату закінчення",
"This action cannot be undone. Any applications using this API key will stop working.": "Цю дію не можна скасувати. Будь-які додатки, що використовують цей ключ API, перестануть працювати.",
"Update API key": "Оновити ключ API",
"Update": "Оновити",
"Update {{credential}}": "Оновити {{credential}}",
"Manage API keys for all users in the workspace": "Керувати ключами API для всіх користувачів у робочій області",
"Restrict API key creation to admins": "Обмежити створення API-ключів лише для адміністраторів",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "Тільки адміністратори та власники можуть створювати нові API-ключі. Існуючі ключі учасників і надалі працюватимуть.",
@@ -873,6 +870,12 @@
"Previous 7 days": "Попередні 7 днів",
"Previous 30 days": "Попередні 30 днів",
"Search chats...": "Шукати чати...",
"Search chats": "Шукати чати",
"Ask anything... Use @ to mention pages": "Запитайте будь-що... Використовуйте @, щоб згадувати сторінки",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "Почніть новий чат, щоб побачити його тут.",
"Summarize this page": "Підсумувати цю сторінку",
"Toggle AI Chat": "Перемкнути AI-чат",
@@ -880,5 +883,105 @@
"Try a different search term.": "Спробуйте інший пошуковий запит.",
"Try again": "Спробувати ще раз",
"Untitled chat": "Чат без назви",
"What can I help you with?": "Чим я можу вам допомогти?"
"What can I help you with?": "Чим я можу вам допомогти?",
"Are you sure you want to revoke this {{credential}}": "Ви впевнені, що хочете відкликати цей {{credential}}",
"Automatically provision users and groups from your identity provider via SCIM.": "Автоматично надавайте користувачів і групи від вашого постачальника ідентифікації через SCIM.",
"Configure your identity provider with this URL to provision users and groups.": "Налаштуйте свого постачальника ідентифікації за допомогою цієї URL-адреси для надання користувачів і груп.",
"Create {{credential}}": "Створити {{credential}}",
"{{credential}} created": "{{credential}} створено",
"{{credential}} created successfully": "{{credential}} успішно створено",
"Created by": "Створено",
"Custom": "Користувацький",
"Enable SCIM": "Увімкнути SCIM",
"Enter a descriptive name": "Введіть описову назву",
"I've saved my {{credential}}": "Я зберіг(ла) свій {{credential}}",
"Important": "Важливо",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "Обов’язково скопіюйте свій {{credential}} зараз. Ви більше не зможете побачити його знову!",
"Never": "Ніколи",
"Revoke {{credential}}": "Відкликати {{credential}}",
"SCIM endpoint URL": "URL-адреса кінцевої точки SCIM",
"SCIM provisioning": "Надання SCIM",
"SCIM takes precedence over SSO group sync while enabled.": "SCIM має пріоритет над синхронізацією груп SSO, коли його ввімкнено.",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "Ви досягли максимальної кількості токенів SCIM: {{max}}. Видаліть наявний токен, щоб створити новий.",
"SCIM token": "Токен SCIM",
"SCIM tokens": "Токени SCIM",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "Цю дію не можна скасувати. Ваш постачальник ідентифікації негайно припинить синхронізацію.",
"Toggle SCIM provisioning": "Перемкнути надання SCIM",
"Token": "Токен",
"Page menu": "Меню сторінки",
"Expand": "Розгорнути",
"Collapse": "Згорнути",
"Comment menu": "Меню коментаря",
"Group menu": "Меню групи",
"Show hidden breadcrumbs": "Показати приховані \"хлібні крихти\"",
"Breadcrumbs": "\"Хлібні крихти\"",
"Page actions": "Дії сторінки",
"Pick emoji": "Вибрати емодзі",
"Template menu": "Меню шаблону",
"Chat menu": "Меню чату",
"API key menu": "Меню ключа API",
"Jump to comment selection": "Перейти до вибору коментаря",
"Slash commands": "Слеш-команди",
"Mention suggestions": "Підказки згадок",
"Link suggestions": "Підказки посилань",
"Diagram editor": "Редактор діаграм",
"Add comment": "Додати коментар",
"Find and replace": "Знайти й замінити",
"Main navigation": "Основна навігація",
"Space navigation": "Навігація простору",
"Settings navigation": "Навігація налаштувань",
"AI navigation": "Навігація AI",
"Breadcrumb": "Хлібна крихта",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -416,6 +416,7 @@
"{{latestVersion}} is available": "{{latestVersion}} 可用",
"Default page edit mode": "默认页面编辑模式",
"Choose your preferred page edit mode. Avoid accidental edits.": "选择您偏好的页面编辑模式。避免意外编辑。",
"Choose {{format}} file": "选择 {{format}} 文件",
"Reading": "阅读",
"Delete member": "删除成员",
"Member deleted successfully": "成员删除成功",
@@ -608,25 +609,21 @@
"Image exceeds 10MB limit.": "图片超过10MB限制。",
"Image removed successfully": "图片删除成功",
"API key": "API密钥",
"API key created successfully": "API密钥创建成功",
"API keys": "API密钥",
"API management": "API管理",
"Are you sure you want to revoke this API key": "确定要撤销此API密钥吗",
"Create API Key": "创建API密钥",
"Custom expiration date": "自定义到期日期",
"Enter a descriptive token name": "输入描述性令牌名称",
"Expiration": "到期",
"Expired": "已过期",
"Expires": "到期",
"I've saved my API key": "我已保存我的API密钥",
"Last use": "上次使用",
"No API keys found": "找不到API密钥",
"No expiration": "无到期",
"Revoke API key": "撤销API密钥",
"Revoked successfully": "撤销成功",
"Select expiration date": "选择到期日期",
"This action cannot be undone. Any applications using this API key will stop working.": "此操作无法撤销。使用此API密钥的任何应用程序将停止工作。",
"Update API key": "更新API密钥",
"Update": "更新",
"Update {{credential}}": "更新{{credential}}",
"Manage API keys for all users in the workspace": "管理工作空间中所有用户的API密钥",
"Restrict API key creation to admins": "仅限管理员创建 API 密钥。",
"Only admins and owners can create new API keys. Existing member keys will continue to work.": "只有管理员和所有者可以创建新的 API 密钥。现有成员密钥将继续有效。",
@@ -873,6 +870,12 @@
"Previous 7 days": "前 7 天",
"Previous 30 days": "前 30 天",
"Search chats...": "搜索聊天...",
"Search chats": "搜索聊天",
"Ask anything... Use @ to mention pages": "询问任何内容……使用 @ 提及页面",
"Ask anything or search your workspace": "Ask anything or search your workspace",
"Welcome to {{name}}": "Welcome to {{name}}",
"Add files": "Add files",
"Mention a page": "Mention a page",
"Start a new chat to see it here.": "开始新的聊天后会显示在这里。",
"Summarize this page": "总结此页面",
"Toggle AI Chat": "切换 AI 聊天",
@@ -880,5 +883,105 @@
"Try a different search term.": "请尝试其他搜索词。",
"Try again": "重试",
"Untitled chat": "未命名聊天",
"What can I help you with?": "我能帮您做什么?"
"What can I help you with?": "我能帮您做什么?",
"Are you sure you want to revoke this {{credential}}": "确定要撤销此{{credential}}吗",
"Automatically provision users and groups from your identity provider via SCIM.": "通过 SCIM 从您的身份提供商自动预配用户和群组。",
"Configure your identity provider with this URL to provision users and groups.": "使用此 URL 配置您的身份提供商以预配用户和群组。",
"Create {{credential}}": "创建{{credential}}",
"{{credential}} created": "已创建{{credential}}",
"{{credential}} created successfully": "已成功创建{{credential}}",
"Created by": "创建者",
"Custom": "自定义",
"Enable SCIM": "启用 SCIM",
"Enter a descriptive name": "输入描述性名称",
"I've saved my {{credential}}": "我已保存我的{{credential}}",
"Important": "重要",
"Make sure to copy your {{credential}} now. You won't be able to see it again!": "请务必立即复制您的{{credential}}。之后您将无法再次查看!",
"Never": "从不",
"Revoke {{credential}}": "撤销{{credential}}",
"SCIM endpoint URL": "SCIM 端点 URL",
"SCIM provisioning": "SCIM 预配",
"SCIM takes precedence over SSO group sync while enabled.": "启用后,SCIM 的优先级高于 SSO 群组同步。",
"You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "您已达到 {{max}} 个 SCIM 令牌的上限。请删除一个现有令牌以创建新令牌。",
"SCIM token": "SCIM 令牌",
"SCIM tokens": "SCIM 令牌",
"This action cannot be undone. Your identity provider will stop syncing immediately.": "此操作无法撤销。您的身份提供商将立即停止同步。",
"Toggle SCIM provisioning": "切换 SCIM 预配",
"Token": "令牌",
"Page menu": "页面菜单",
"Expand": "展开",
"Collapse": "折叠",
"Comment menu": "评论菜单",
"Group menu": "群组菜单",
"Show hidden breadcrumbs": "显示隐藏的面包屑",
"Breadcrumbs": "面包屑",
"Page actions": "页面操作",
"Pick emoji": "选择表情符号",
"Template menu": "模板菜单",
"Chat menu": "聊天菜单",
"API key menu": "API 密钥菜单",
"Jump to comment selection": "跳转到评论选择",
"Slash commands": "斜杠命令",
"Mention suggestions": "提及建议",
"Link suggestions": "链接建议",
"Diagram editor": "图表编辑器",
"Add comment": "添加评论",
"Find and replace": "查找和替换",
"Main navigation": "主导航",
"Space navigation": "空间导航",
"Settings navigation": "设置导航",
"AI navigation": "AI 导航",
"Breadcrumb": "面包屑",
"Synced block": "Synced block",
"Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.",
"Editing original": "Editing original",
"Copy synced block": "Copy synced block",
"Unsync": "Unsync",
"Delete synced block": "Delete synced block",
"Synced to {{count}} other page_one": "Synced to {{count}} other page",
"Synced to {{count}} other page_other": "Synced to {{count}} other pages",
"ORIGINAL": "ORIGINAL",
"THIS PAGE": "THIS PAGE",
"No pages": "No pages",
"The original synced block no longer exists": "The original synced block no longer exists",
"You don't have access to this synced block": "You don't have access to this synced block",
"Failed to load this synced block": "Failed to load this synced block",
"Fixed editor toolbar": "Fixed editor toolbar",
"Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.",
"Toggle fixed editor toolbar": "Toggle fixed editor toolbar",
"Normal text": "Normal text",
"More inline formatting": "More inline formatting",
"Subscript": "Subscript",
"Superscript": "Superscript",
"Inline code": "Inline code",
"Insert media": "Insert media",
"Mention": "Mention",
"Emoji": "Emoji",
"Columns": "Columns",
"More inserts": "More inserts",
"Embeds": "Embeds",
"Diagrams": "Diagrams",
"Advanced": "Advanced",
"Utility": "Utility",
"Decrease indent": "Decrease indent",
"Increase indent": "Increase indent",
"Clear formatting": "Clear formatting",
"Code block": "Code block",
"Experimental": "Experimental",
"Strikethrough": "Strikethrough",
"Undo": "Undo",
"Redo": "Redo",
"Backlinks": "Backlinks",
"Last updated by": "Last updated by",
"Last updated": "Last updated",
"Stats": "Stats",
"Word count": "Word count",
"Characters": "Characters",
"Incoming links": "Incoming links",
"Outgoing links": "Outgoing links",
"Incoming links ({{count}})": "Incoming links ({{count}})",
"Outgoing links ({{count}})": "Outgoing links ({{count}})",
"No pages link here yet.": "No pages link here yet.",
"This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.",
"Verified until {{date}}": "Verified until {{date}}"
}
@@ -8,6 +8,7 @@ import { TableOfContents } from "@/features/editor/components/table-of-contents/
import { useAtomValue } from "jotai";
import { pageEditorAtom } from "@/features/editor/atoms/editor-atoms.ts";
import AsideChatPanel from "@/ee/ai-chat/components/aside-chat-panel";
import { PageDetailsAside } from "@/features/page-details/components/page-details-aside.tsx";
export default function Aside() {
const [{ tab }] = useAtom(asideStateAtom);
@@ -30,6 +31,10 @@ export default function Aside() {
component = <AsideChatPanel />;
title = "AI Chat";
break;
case "details":
component = <PageDetailsAside />;
title = "Details";
break;
default:
component = null;
title = null;
@@ -147,7 +147,9 @@ export default function GlobalAppShell({
? t("Table of contents")
: asideTab === "chat"
? t("AI Chat")
: undefined
: asideTab === "details"
? t("Details")
: undefined
}
>
<Aside />
@@ -10,6 +10,7 @@ export const desktopSidebarAtom = atomWithWebStorage<boolean>(
export const desktopAsideAtom = atom<boolean>(false);
// Valid `tab` values: "" | "comments" | "toc" | "chat" | "details"
type AsideStateType = {
tab: string;
isAsideOpen: boolean;
@@ -118,10 +118,20 @@ export function PageVerificationBadge({
if (status === "none" && readOnly) return null;
const tooltipLabel =
status === "verified" && verificationInfo?.expiresAt
? t("Verified until {{date}}", {
date: new Date(verificationInfo.expiresAt).toLocaleDateString(
undefined,
{ month: "long", day: "numeric", year: "numeric" },
),
})
: getStatusLabel(status, t);
return (
<>
{status !== "none" ? (
<Tooltip label={getStatusLabel(status, t)} withArrow openDelay={250}>
<Tooltip label={tooltipLabel} withArrow openDelay={250}>
<Group
gap={4}
onClick={open}
@@ -3,14 +3,17 @@ import React from "react";
import { TitleEditor } from "@/features/editor/title-editor";
import PageEditor from "@/features/editor/page-editor";
import {
ActionIcon,
Container,
Divider,
Group,
Popover,
Stack,
Text,
Tooltip,
UnstyledButton,
} from "@mantine/core";
import { IconInfoCircle } from "@tabler/icons-react";
import { useAtom } from "jotai";
import { userAtom } from "@/features/user/atoms/current-user-atom.ts";
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
@@ -19,6 +22,8 @@ import { useTranslation } from "react-i18next";
import { IContributor } from "@/features/page/types/page.types.ts";
import { FixedToolbar } from "@/features/editor/components/fixed-toolbar/fixed-toolbar";
import { PageEditMode } from "@/features/user/types/user.types.ts";
import useToggleAside from "@/hooks/use-toggle-aside.tsx";
import clsx from "clsx";
const MemoizedTitleEditor = React.memo(TitleEditor);
const MemoizedPageEditor = React.memo(PageEditor);
@@ -101,6 +106,7 @@ function PageByline({
readOnly,
}: PageBylineProps) {
const { t } = useTranslation();
const toggleAside = useToggleAside();
const otherContributors = (contributors ?? []).filter(
(c) => c.id !== creator?.id,
@@ -110,8 +116,8 @@ function PageByline({
<Group
gap="sm"
mb="md"
className="print-hide"
style={{ marginTop: "-0.5em", paddingLeft: "3rem" }}
className={clsx("print-hide", classes.byline)}
style={{ marginTop: "-0.5em" }}
>
{creator && (
<Popover position="bottom-start" shadow="md" width={280} withArrow>
@@ -173,6 +179,17 @@ function PageByline({
</Popover.Dropdown>
</Popover>
)}
<Tooltip label={t("Details")} withArrow openDelay={250}>
<ActionIcon
variant="subtle"
color="gray"
aria-label={t("Details")}
onClick={() => toggleAside("details")}
>
<IconInfoCircle size={20} stroke={1.5} />
</ActionIcon>
</Tooltip>
<PageVerificationBadge readOnly={readOnly} />
</Group>
);
@@ -9,3 +9,15 @@
}
}
.byline {
padding-left: 3rem;
@media (max-width: $mantine-breakpoint-sm) {
padding-left: 1rem;
}
@media print {
padding-left: 0;
}
}
@@ -0,0 +1,113 @@
import {
Button,
Center,
Group,
Loader,
Stack,
Text,
UnstyledButton,
} from "@mantine/core";
import { Link } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useBacklinksQuery } from "@/features/page-details/queries/backlinks-query.ts";
import {
BacklinkDirection,
IBacklinkPageItem,
} from "@/features/page-details/types/backlink.types.ts";
import { buildPageUrl } from "@/features/page/page.utils.ts";
import { getPageIcon } from "@/lib";
interface BacklinksListProps {
pageId: string;
direction: BacklinkDirection;
enabled: boolean;
onItemClick: () => void;
}
export function BacklinksList({
pageId,
direction,
enabled,
onItemClick,
}: BacklinksListProps) {
const { t } = useTranslation();
const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } =
useBacklinksQuery(pageId, direction, enabled);
if (!enabled) return null;
if (isLoading) {
return (
<Center py="sm">
<Loader size="sm" />
</Center>
);
}
const items: IBacklinkPageItem[] =
data?.pages.flatMap((page) => page.items) ?? [];
if (items.length === 0) {
return (
<Text c="dimmed" size="sm" py="md">
{direction === "incoming"
? t("No pages link here yet.")
: t("This page doesn't link to other pages yet.")}
</Text>
);
}
const handleClick = (e: React.MouseEvent) => {
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) {
return;
}
onItemClick();
};
return (
<Stack gap={4}>
{items.map((item) => (
<UnstyledButton
key={item.id}
component={Link}
to={
item.space?.slug
? buildPageUrl(
item.space.slug,
item.slugId,
item.title ?? undefined,
)
: "#"
}
onClick={handleClick}
style={{ padding: "8px 4px", borderRadius: 4, userSelect: "none" }}
>
<Group gap="xs" wrap="nowrap">
{getPageIcon(item.icon ?? "")}
<Stack gap={0} style={{ flex: 1, minWidth: 0 }}>
<Text size="sm" fw={500} lineClamp={1}>
{item.title || t("Untitled")}
</Text>
{item.space?.name && (
<Text size="xs" c="dimmed" lineClamp={1}>
{item.space.name}
</Text>
)}
</Stack>
</Group>
</UnstyledButton>
))}
{hasNextPage && (
<Button
variant="subtle"
size="xs"
loading={isFetchingNextPage}
onClick={() => fetchNextPage()}
mt="xs"
>
{t("Load more")}
</Button>
)}
</Stack>
);
}
@@ -0,0 +1,62 @@
import { Modal, Stack, Text } from "@mantine/core";
import { useTranslation } from "react-i18next";
import { useBacklinksCountQuery } from "@/features/page-details/queries/backlinks-query.ts";
import { BacklinksList } from "./backlinks-list";
interface BacklinksModalProps {
pageId: string;
opened: boolean;
onClose: () => void;
}
export function BacklinksModal({
pageId,
opened,
onClose,
}: BacklinksModalProps) {
const { t } = useTranslation();
const { data: counts } = useBacklinksCountQuery(pageId);
return (
<Modal.Root opened={opened} onClose={onClose} size={640} yOffset="10vh">
<Modal.Overlay />
<Modal.Content>
<Modal.Header>
<Modal.Title fw={500}>{t("Backlinks")}</Modal.Title>
<Modal.CloseButton />
</Modal.Header>
<Modal.Body>
<Stack gap="lg">
<Stack gap="xs">
<Text size="sm" fw={500} c="dimmed">
{t("Incoming links ({{count}})", {
count: counts?.incoming ?? 0,
})}
</Text>
<BacklinksList
pageId={pageId}
direction="incoming"
enabled={opened}
onItemClick={onClose}
/>
</Stack>
<Stack gap="xs">
<Text size="sm" fw={500} c="dimmed">
{t("Outgoing links ({{count}})", {
count: counts?.outgoing ?? 0,
})}
</Text>
<BacklinksList
pageId={pageId}
direction="outgoing"
enabled={opened}
onItemClick={onClose}
/>
</Stack>
</Stack>
</Modal.Body>
</Modal.Content>
</Modal.Root>
);
}
@@ -0,0 +1,233 @@
import {
Divider,
Group,
Skeleton,
Stack,
Text,
UnstyledButton,
} from "@mantine/core";
import { IconChevronRight } from "@tabler/icons-react";
import { useDisclosure } from "@mantine/hooks";
import { useAtomValue } from "jotai";
import { useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { extractPageSlugId } from "@/lib";
import { usePageQuery } from "@/features/page/queries/page-query.ts";
import { pageEditorAtom } from "@/features/editor/atoms/editor-atoms.ts";
import { useBacklinksCountQuery } from "@/features/page-details/queries/backlinks-query.ts";
import { BacklinksModal } from "./backlinks-modal";
import { formattedDate, timeAgo } from "@/lib/time.ts";
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
export function PageDetailsAside() {
const { pageSlug } = useParams();
const { data: page } = usePageQuery({
pageId: extractPageSlugId(pageSlug),
});
const pageEditor = useAtomValue(pageEditorAtom);
const { data: counts, isLoading: countsLoading } = useBacklinksCountQuery(page?.id);
const [modalOpened, { open: openModal, close: closeModal }] =
useDisclosure(false);
if (!page) return null;
const wordCount: number =
pageEditor?.storage?.characterCount?.words?.() ?? 0;
const characterCount: number =
pageEditor?.storage?.characterCount?.characters?.() ?? 0;
return (
<>
<Stack gap="md">
<PeopleSection
creator={page.creator}
lastUpdatedBy={page.lastUpdatedBy}
/>
<Divider />
<StatsSection
wordCount={wordCount}
characterCount={characterCount}
createdAt={page.createdAt}
updatedAt={page.updatedAt}
/>
<Divider />
<BacklinksSection
incomingCount={counts?.incoming ?? 0}
outgoingCount={counts?.outgoing ?? 0}
isLoading={countsLoading}
onClick={openModal}
/>
</Stack>
<BacklinksModal
pageId={page.id}
opened={modalOpened}
onClose={closeModal}
/>
</>
);
}
function PeopleSection({
creator,
lastUpdatedBy,
}: {
creator: { id: string; name: string; avatarUrl: string } | null;
lastUpdatedBy: { id: string; name: string; avatarUrl: string } | null;
}) {
const { t } = useTranslation();
return (
<Stack gap="xs">
<PersonRow label={t("Created by")} person={creator} />
<PersonRow label={t("Last updated by")} person={lastUpdatedBy} />
</Stack>
);
}
function PersonRow({
label,
person,
}: {
label: string;
person: { id: string; name: string; avatarUrl: string } | null;
}) {
return (
<Group justify="space-between" wrap="nowrap">
<Text size="sm" c="dimmed">
{label}
</Text>
{person ? (
<Group gap={6} wrap="nowrap">
<CustomAvatar
avatarUrl={person.avatarUrl}
name={person.name}
size={20}
radius="xl"
/>
<Text size="sm" lineClamp={1}>
{person.name}
</Text>
</Group>
) : (
<Text size="sm" c="dimmed">
</Text>
)}
</Group>
);
}
function StatsSection({
wordCount,
characterCount,
createdAt,
updatedAt,
}: {
wordCount: number;
characterCount: number;
createdAt: Date | string;
updatedAt: Date | string;
}) {
const { t } = useTranslation();
return (
<Stack gap="xs">
<Text size="xs" fw={500} c="dimmed">
{t("Stats")}
</Text>
<StatRow label={t("Word count")} value={String(wordCount)} />
<StatRow label={t("Characters")} value={String(characterCount)} />
<StatRow
label={t("Created")}
value={formattedDate(new Date(createdAt))}
/>
<StatRow
label={t("Last updated")}
value={timeAgo(new Date(updatedAt))}
/>
</Stack>
);
}
function StatRow({ label, value }: { label: string; value: string }) {
return (
<Group justify="space-between" wrap="nowrap">
<Text size="sm" c="dimmed">
{label}
</Text>
<Text size="sm">{value}</Text>
</Group>
);
}
function BacklinksSection({
incomingCount,
outgoingCount,
isLoading,
onClick,
}: {
incomingCount: number;
outgoingCount: number;
isLoading: boolean;
onClick: () => void;
}) {
const { t } = useTranslation();
return (
<Stack gap="xs">
<Text size="xs" fw={500} c="dimmed">
{t("Backlinks")}
</Text>
<BacklinksRow
label={t("Incoming links")}
count={incomingCount}
isLoading={isLoading}
onClick={onClick}
/>
<BacklinksRow
label={t("Outgoing links")}
count={outgoingCount}
isLoading={isLoading}
onClick={onClick}
/>
</Stack>
);
}
function BacklinksRow({
label,
count,
isLoading,
onClick,
}: {
label: string;
count: number;
isLoading: boolean;
onClick: () => void;
}) {
return (
<UnstyledButton
onClick={onClick}
style={{
padding: "4px 4px",
borderRadius: 4,
}}
>
<Group justify="space-between" wrap="nowrap">
<Text size="sm" c="dimmed">
{label}
</Text>
<Group gap={6} wrap="nowrap">
{isLoading ? (
<Skeleton height={18} width={20} />
) : (
<Text size="sm">{count}</Text>
)}
<IconChevronRight size={16} stroke={2} color="var(--mantine-color-dimmed)" />
</Group>
</Group>
</UnstyledButton>
);
}
@@ -0,0 +1,45 @@
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
import {
getBacklinks,
getBacklinksCount,
} from "@/features/page-details/services/backlinks-service.ts";
import {
BacklinkDirection,
IBacklinkCount,
} from "@/features/page-details/types/backlink.types.ts";
const BACKLINKS_STALE_TIME = 30 * 1000;
const BACKLINKS_PAGE_LIMIT = 100;
export function useBacklinksCountQuery(pageId: string | undefined) {
return useQuery<IBacklinkCount>({
queryKey: ["backlinks-count", pageId],
queryFn: () => getBacklinksCount(pageId as string),
enabled: !!pageId,
staleTime: BACKLINKS_STALE_TIME,
});
}
export function useBacklinksQuery(
pageId: string | undefined,
direction: BacklinkDirection,
enabled: boolean,
) {
return useInfiniteQuery({
queryKey: ["backlinks", pageId, direction],
queryFn: ({ pageParam }) =>
getBacklinks({
pageId: pageId as string,
direction,
cursor: pageParam,
limit: BACKLINKS_PAGE_LIMIT,
}),
enabled: enabled && !!pageId,
initialPageParam: undefined as string | undefined,
getNextPageParam: (lastPage) =>
lastPage.meta.hasNextPage
? (lastPage.meta.nextCursor ?? undefined)
: undefined,
staleTime: BACKLINKS_STALE_TIME,
});
}
@@ -0,0 +1,26 @@
import api from "@/lib/api-client";
import { IPagination } from "@/lib/types.ts";
import {
IBacklinkCount,
IBacklinkPageItem,
IBacklinksListParams,
} from "@/features/page-details/types/backlink.types.ts";
export async function getBacklinksCount(
pageId: string,
): Promise<IBacklinkCount> {
const req = await api.post<IBacklinkCount>("/pages/backlinks-count", {
pageId,
});
return req.data;
}
export async function getBacklinks(
params: IBacklinksListParams,
): Promise<IPagination<IBacklinkPageItem>> {
const req = await api.post<IPagination<IBacklinkPageItem>>(
"/pages/backlinks",
params,
);
return req.data;
}
@@ -0,0 +1,23 @@
export type BacklinkDirection = "incoming" | "outgoing";
export interface IBacklinkCount {
incoming: number;
outgoing: number;
}
export interface IBacklinkPageItem {
id: string;
slugId: string;
title: string | null;
icon: string | null;
spaceId: string;
space: { id: string; slug: string; name: string } | null;
updatedAt: string;
}
export interface IBacklinksListParams {
pageId: string;
direction: BacklinkDirection;
cursor?: string;
limit?: number;
}
@@ -0,0 +1,11 @@
import { IsIn, IsNotEmpty, IsString } from 'class-validator';
import { PageIdDto } from './page.dto';
export type BacklinkDirection = 'incoming' | 'outgoing';
export class BacklinksListDto extends PageIdDto {
@IsString()
@IsNotEmpty()
@IsIn(['incoming', 'outgoing'])
direction: BacklinkDirection;
}
@@ -11,6 +11,7 @@ import {
UseGuards,
} from '@nestjs/common';
import { PageService } from './services/page.service';
import { BacklinkService } from './services/backlink.service';
import { PageAccessService } from './page-access/page-access.service';
import { CreatePageDto } from './dto/create-page.dto';
import { UpdatePageDto } from './dto/update-page.dto';
@@ -38,6 +39,7 @@ import { RecentPageDto } from './dto/recent-page.dto';
import { CreatedByUserDto } from './dto/created-by-user.dto';
import { DuplicatePageDto } from './dto/duplicate-page.dto';
import { DeletedPageDto } from './dto/deleted-page.dto';
import { BacklinksListDto } from './dto/backlink.dto';
import {
jsonToHtml,
jsonToMarkdown,
@@ -58,6 +60,7 @@ export class PageController {
private readonly pageHistoryService: PageHistoryService,
private readonly spaceAbility: SpaceAbilityFactory,
private readonly pageAccessService: PageAccessService,
private readonly backlinkService: BacklinkService,
@Inject(AUDIT_SERVICE) private readonly auditService: IAuditService,
) {}
@@ -96,6 +99,42 @@ export class PageController {
return { ...page, permissions };
}
@HttpCode(HttpStatus.OK)
@Post('backlinks-count')
async getBacklinksCount(
@Body() dto: PageIdDto,
@AuthUser() user: User,
): Promise<{ incoming: number; outgoing: number }> {
const page = await this.pageRepo.findById(dto.pageId);
if (!page) {
throw new NotFoundException('Page not found');
}
await this.pageAccessService.validateCanView(page, user);
return this.backlinkService.countByPageId(page.id, user.id);
}
@HttpCode(HttpStatus.OK)
@Post('backlinks')
async getBacklinks(
@Body() dto: BacklinksListDto,
@Body() pagination: PaginationOptions,
@AuthUser() user: User,
) {
const page = await this.pageRepo.findById(dto.pageId);
if (!page) {
throw new NotFoundException('Page not found');
}
await this.pageAccessService.validateCanView(page, user);
return this.backlinkService.findByPageId(
page.id,
dto.direction,
user.id,
pagination,
);
}
@HttpCode(HttpStatus.OK)
@Post('create')
async create(
+13 -2
View File
@@ -3,6 +3,7 @@ import { PageService } from './services/page.service';
import { PageController } from './page.controller';
import { PageHistoryService } from './services/page-history.service';
import { TrashCleanupService } from './services/trash-cleanup.service';
import { BacklinkService } from './services/backlink.service';
import { StorageModule } from '../../integrations/storage/storage.module';
import { CollaborationModule } from '../../collaboration/collaboration.module';
import { WatcherModule } from '../watcher/watcher.module';
@@ -10,8 +11,18 @@ import { TransclusionModule } from './transclusion/transclusion.module';
@Module({
controllers: [PageController],
providers: [PageService, PageHistoryService, TrashCleanupService],
providers: [
PageService,
PageHistoryService,
TrashCleanupService,
BacklinkService,
],
exports: [PageService, PageHistoryService],
imports: [StorageModule, CollaborationModule, WatcherModule, TransclusionModule],
imports: [
StorageModule,
CollaborationModule,
WatcherModule,
TransclusionModule,
],
})
export class PageModule {}
@@ -0,0 +1,163 @@
import { Test } from '@nestjs/testing';
import { BacklinkService } from './backlink.service';
import { BacklinkRepo } from '@docmost/db/repos/backlink/backlink.repo';
import { PagePermissionRepo } from '@docmost/db/repos/page/page-permission.repo';
describe('BacklinkService.countByPageId', () => {
let service: BacklinkService;
let backlinkRepo: jest.Mocked<BacklinkRepo>;
let permissionRepo: jest.Mocked<PagePermissionRepo>;
const pageId = '00000000-0000-0000-0000-000000000001';
const userId = '00000000-0000-0000-0000-000000000099';
beforeEach(async () => {
const backlinkRepoMock: jest.Mocked<Partial<BacklinkRepo>> = {
findRelatedPageIds: jest.fn(),
findPagesByIdsPaginated: jest.fn(),
};
const permissionRepoMock: jest.Mocked<Partial<PagePermissionRepo>> = {
filterAccessiblePageIds: jest.fn(),
};
const module = await Test.createTestingModule({
providers: [
BacklinkService,
{ provide: BacklinkRepo, useValue: backlinkRepoMock },
{ provide: PagePermissionRepo, useValue: permissionRepoMock },
],
}).compile();
service = module.get(BacklinkService);
backlinkRepo = module.get(BacklinkRepo) as jest.Mocked<BacklinkRepo>;
permissionRepo = module.get(
PagePermissionRepo,
) as jest.Mocked<PagePermissionRepo>;
});
it('returns post-filter counts for both directions', async () => {
backlinkRepo.findRelatedPageIds.mockImplementation(async (_id, dir) =>
dir === 'incoming' ? ['a', 'b', 'c'] : ['x', 'y'],
);
permissionRepo.filterAccessiblePageIds.mockImplementation(
async ({ pageIds }) =>
pageIds.filter((id) => id !== 'b' && id !== 'y'),
);
const result = await service.countByPageId(pageId, userId);
expect(result).toEqual({ incoming: 2, outgoing: 1 });
expect(permissionRepo.filterAccessiblePageIds).toHaveBeenCalledWith({
pageIds: ['a', 'b', 'c'],
userId,
});
expect(permissionRepo.filterAccessiblePageIds).toHaveBeenCalledWith({
pageIds: ['x', 'y'],
userId,
});
});
it('skips the permission filter when there are no candidates', async () => {
backlinkRepo.findRelatedPageIds.mockResolvedValue([]);
permissionRepo.filterAccessiblePageIds.mockResolvedValue([]);
const result = await service.countByPageId(pageId, userId);
expect(result).toEqual({ incoming: 0, outgoing: 0 });
expect(permissionRepo.filterAccessiblePageIds).not.toHaveBeenCalled();
});
it('passes the userId to findRelatedPageIds so the repo can apply space membership filtering', async () => {
backlinkRepo.findRelatedPageIds.mockResolvedValue([]);
await service.countByPageId(pageId, userId);
expect(backlinkRepo.findRelatedPageIds).toHaveBeenCalledWith(
pageId,
'incoming',
userId,
);
expect(backlinkRepo.findRelatedPageIds).toHaveBeenCalledWith(
pageId,
'outgoing',
userId,
);
});
});
describe('BacklinkService.findByPageId', () => {
let service: BacklinkService;
let backlinkRepo: jest.Mocked<BacklinkRepo>;
let permissionRepo: jest.Mocked<PagePermissionRepo>;
const pageId = '00000000-0000-0000-0000-000000000001';
const userId = '00000000-0000-0000-0000-000000000099';
beforeEach(async () => {
const backlinkRepoMock: jest.Mocked<Partial<BacklinkRepo>> = {
findRelatedPageIds: jest.fn(),
findPagesByIdsPaginated: jest.fn(),
};
const permissionRepoMock: jest.Mocked<Partial<PagePermissionRepo>> = {
filterAccessiblePageIds: jest.fn(),
};
const module = await Test.createTestingModule({
providers: [
BacklinkService,
{ provide: BacklinkRepo, useValue: backlinkRepoMock },
{ provide: PagePermissionRepo, useValue: permissionRepoMock },
],
}).compile();
service = module.get(BacklinkService);
backlinkRepo = module.get(BacklinkRepo) as jest.Mocked<BacklinkRepo>;
permissionRepo = module.get(
PagePermissionRepo,
) as jest.Mocked<PagePermissionRepo>;
});
it('passes filtered ids through to the paginated repo call', async () => {
backlinkRepo.findRelatedPageIds.mockResolvedValue(['a', 'b']);
permissionRepo.filterAccessiblePageIds.mockResolvedValue(['a']);
backlinkRepo.findPagesByIdsPaginated.mockResolvedValue({
items: [],
meta: {
limit: 20,
hasNextPage: false,
hasPrevPage: false,
nextCursor: null,
prevCursor: null,
},
} as any);
await service.findByPageId(pageId, 'incoming', userId, { limit: 20 } as any);
expect(backlinkRepo.findPagesByIdsPaginated).toHaveBeenCalledWith(
['a'],
expect.objectContaining({ limit: 20 }),
);
});
it('hands an empty list to the repo when there are no accessible ids', async () => {
backlinkRepo.findRelatedPageIds.mockResolvedValue([]);
backlinkRepo.findPagesByIdsPaginated.mockResolvedValue({
items: [],
meta: {
limit: 20,
hasNextPage: false,
hasPrevPage: false,
nextCursor: null,
prevCursor: null,
},
} as any);
await service.findByPageId(pageId, 'incoming', userId, { limit: 20 } as any);
expect(backlinkRepo.findPagesByIdsPaginated).toHaveBeenCalledWith(
[],
expect.objectContaining({ limit: 20 }),
);
expect(permissionRepo.filterAccessiblePageIds).not.toHaveBeenCalled();
});
});
@@ -0,0 +1,56 @@
import { Injectable } from '@nestjs/common';
import { BacklinkRepo } from '@docmost/db/repos/backlink/backlink.repo';
import { PagePermissionRepo } from '@docmost/db/repos/page/page-permission.repo';
import { PaginationOptions } from '@docmost/db/pagination/pagination-options';
export type BacklinkDirection = 'incoming' | 'outgoing';
@Injectable()
export class BacklinkService {
constructor(
private readonly backlinkRepo: BacklinkRepo,
private readonly pagePermissionRepo: PagePermissionRepo,
) {}
async countByPageId(
pageId: string,
userId: string,
): Promise<{ incoming: number; outgoing: number }> {
const [incomingIds, outgoingIds] = await Promise.all([
this.accessibleRelatedIds(pageId, 'incoming', userId),
this.accessibleRelatedIds(pageId, 'outgoing', userId),
]);
return { incoming: incomingIds.length, outgoing: outgoingIds.length };
}
async findByPageId(
pageId: string,
direction: BacklinkDirection,
userId: string,
pagination: PaginationOptions,
) {
const accessibleIds = await this.accessibleRelatedIds(
pageId,
direction,
userId,
);
return this.backlinkRepo.findPagesByIdsPaginated(accessibleIds, pagination);
}
private async accessibleRelatedIds(
pageId: string,
direction: BacklinkDirection,
userId: string,
): Promise<string[]> {
const candidateIds = await this.backlinkRepo.findRelatedPageIds(
pageId,
direction,
userId,
);
if (candidateIds.length === 0) return [];
return this.pagePermissionRepo.filterAccessiblePageIds({
pageIds: candidateIds,
userId,
});
}
}
@@ -7,10 +7,20 @@ import { KyselyDB, KyselyTransaction } from '@docmost/db/types/kysely.types';
import { dbOrTx } from '@docmost/db/utils';
import { Injectable } from '@nestjs/common';
import { InjectKysely } from 'nestjs-kysely';
import { PaginationOptions } from '@docmost/db/pagination/pagination-options';
import {
executeWithCursorPagination,
emptyCursorPaginationResult,
} from '@docmost/db/pagination/cursor-pagination';
import { SpaceMemberRepo } from '@docmost/db/repos/space/space-member.repo';
import { jsonObjectFrom } from 'kysely/helpers/postgres';
@Injectable()
export class BacklinkRepo {
constructor(@InjectKysely() private readonly db: KyselyDB) {}
constructor(
@InjectKysely() private readonly db: KyselyDB,
private readonly spaceMemberRepo: SpaceMemberRepo,
) {}
async findById(
backlinkId: string,
@@ -69,4 +79,84 @@ export class BacklinkRepo {
const db = dbOrTx(this.db, trx);
await db.deleteFrom('backlinks').where('id', '=', backlinkId).execute();
}
async findRelatedPageIds(
pageId: string,
direction: 'incoming' | 'outgoing',
userId: string,
): Promise<string[]> {
const userSpaceIds = this.spaceMemberRepo.getUserSpaceIdsQuery(userId);
if (direction === 'incoming') {
const rows = await this.db
.selectFrom('backlinks')
.innerJoin('pages', 'pages.id', 'backlinks.sourcePageId')
.select('backlinks.sourcePageId as relatedId')
.where('backlinks.targetPageId', '=', pageId)
.where('pages.deletedAt', 'is', null)
.where('pages.spaceId', 'in', userSpaceIds)
.execute();
return rows.map((r) => r.relatedId);
}
const rows = await this.db
.selectFrom('backlinks')
.innerJoin('pages', 'pages.id', 'backlinks.targetPageId')
.select('backlinks.targetPageId as relatedId')
.where('backlinks.sourcePageId', '=', pageId)
.where('pages.deletedAt', 'is', null)
.where('pages.spaceId', 'in', userSpaceIds)
.execute();
return rows.map((r) => r.relatedId);
}
async findPagesByIdsPaginated(
pageIds: string[],
pagination: PaginationOptions,
) {
if (pageIds.length === 0) {
return emptyCursorPaginationResult<{
id: string;
slugId: string;
title: string | null;
icon: string | null;
spaceId: string;
updatedAt: Date;
space: { id: string; slug: string; name: string } | null;
}>(pagination.limit);
}
const query = this.db
.selectFrom('pages')
.select((eb) => [
'pages.id',
'pages.slugId',
'pages.title',
'pages.icon',
'pages.spaceId',
'pages.updatedAt',
jsonObjectFrom(
eb
.selectFrom('spaces')
.select(['spaces.id', 'spaces.slug', 'spaces.name'])
.whereRef('spaces.id', '=', 'pages.spaceId'),
).as('space'),
])
.where('pages.deletedAt', 'is', null)
.where('pages.id', 'in', pageIds);
return executeWithCursorPagination(query, {
perPage: pagination.limit,
cursor: pagination.cursor,
beforeCursor: pagination.beforeCursor,
fields: [
{ expression: 'pages.updatedAt', direction: 'desc', key: 'updatedAt' },
{ expression: 'pages.id', direction: 'desc', key: 'id' },
],
parseCursor: (cursor) => ({
updatedAt: new Date(cursor.updatedAt),
id: cursor.id,
}),
});
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ import { TableCell as TiptapTableCell } from "@tiptap/extension-table";
export const TableCell = TiptapTableCell.extend({
name: "tableCell",
content:
"(paragraph | heading | bulletList | orderedList | taskList | blockquote | callout | image | video | attachment | mathBlock | details | codeBlock)+",
"(paragraph | heading | bulletList | orderedList | taskList | blockquote | callout | image | video | audio | subpages | attachment | mathBlock | details | codeBlock)+",
addAttributes() {
return {
+1 -1
View File
@@ -3,7 +3,7 @@ import { TableHeader as TiptapTableHeader } from "@tiptap/extension-table";
export const TableHeader = TiptapTableHeader.extend({
name: "tableHeader",
content:
"(paragraph | heading | bulletList | orderedList | taskList | blockquote | callout | image | video | attachment | mathBlock | details | codeBlock)+",
"(paragraph | heading | bulletList | orderedList | taskList | blockquote | callout | image | video | audio | subpages | attachment | mathBlock | details | codeBlock)+",
addAttributes() {
return {