mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-20 11:22:25 +02:00
* feat: API token management in workspace settings Add UI and backend support for creating, listing, and revoking API tokens scoped to workspaces. Includes owner-level workspace token visibility, OpenAPI documentation, Mongo/Postgres persistence, and i18n translations. Signed-off-by: Don Kendall <kendall@donkendall.com> * feat: enforce API token revocation at transactor level Embed apiTokenId in JWT extra field and add a per-token revocation cache (60s TTL) in the transactor REST handler. Revoked tokens are now rejected within ~60 seconds instead of remaining valid until JWT expiry. Adds checkApiTokenRevoked account service method for the transactor to query individual token revocation status. Signed-off-by: Don Kendall <kendall@donkendall.com> * feat: implement Phase 1 API token scopes (read/write/delete) Add coarse-grained scope enforcement for API tokens. Tokens can now be created with scopes ['read:*'], ['read:*','write:*'], or ['read:*','write:*','delete:*']. Existing tokens without scopes retain full access (backward compatible). - DB: v26 migration adds scopes TEXT[] column to api_tokens - Types: add scopes field to ApiToken and ApiTokenInfo - Operations: createApiToken accepts/validates/persists scopes, embeds in JWT via extra.scopes - Enforcement: withSession checks scopes against method; tx handler additionally requires delete:* for TxRemoveDoc - Client: createApiToken signature accepts optional scopes param - UI: scope preset dropdown in create popup (default: Read Only), permissions column in token list with i18n labels - Also fixes 3 pre-existing TS2322/TS2345 errors in operations.ts Signed-off-by: Don Kendall <kendall@donkendall.com> * test: add unit tests for API token scope enforcement - scopes.test.ts: 8 tests for hasScope() and getRequiredScope() logic - apiTokenScopes.test.ts: 7 tests for createApiToken scope validation (valid scopes, multiple scopes, no scopes backward compat, invalid format rejection, empty array rejection, domain-scope rejection) and listApiTokens scopes inclusion - Export hasScope/getRequiredScope from rpc.ts for testability Signed-off-by: Don Kendall <kendall@donkendall.com> * fix: address review feedback — role restriction, locale parity, formatting - Restrict API token creation/revocation to AccountRole.User or higher (guests cannot use API tokens), per reviewer suggestion - Add 5 missing translation keys (ApiTokenPermissions, ApiTokenScopePreset, ApiTokenScopeReadOnly, ApiTokenScopeReadWrite, ApiTokenScopeFullAccess) to all non-en locale files to fix locale parity CI test - Fix prettier formatting in apiTokenScopes.test.ts - Rename local `extra` to `tokenExtra` in createApiToken to avoid shadowing the decoded token's `extra` field Signed-off-by: Don Kendall <kendall@donkendall.com> * fix: address aonnikov architectural review feedback - rpc.ts: use system service token for checkApiTokenRevoked so the revocation check is not coupled to the user's potentially-revoked bearer token; systemAccountUuid + service:'server' ensures account service always accepts the call - ApiDocsSection.svelte: derive transactor base URL from login.metadata.LoginEndpoint (set on auth) instead of window.location.origin, which is not necessarily the transactor host - ApiTokenCreatePopup.svelte: replace manual translate() calls and themeStore language watch with DropdownLabelsIntl + DropdownIntlItem[], which handle i18n automatically; error state is now IntlString - General.svelte: remove legacy GenerateApiToken button, handler, and ApiTokenPopup import in favour of the new ApiTokens settings panel Signed-off-by: Don Kendall <kendall@donkendall.com> * fix: formatting in ApiTokenPopup, apiTokenScopes test, and operations Signed-off-by: Don Kendall <kendall@donkendall.com> * fix: apply rushx fmt to pass CI formatting check Signed-off-by: Don Kendall <dkendall@ledoweb.com> * fix: restore (s as any) cast in server_http.ts removed by ESLint autofix Signed-off-by: Don Kendall <dkendall@ledoweb.com> * refactor(token): centralize API token revocation/expiry in verifyToken Address @aonnikov's review: the bespoke checkApiTokenRevoked RPC and the ad-hoc revocation cache in the transactor are replaced by a reusable verifyToken in server-token that checks signature, expiry, and (for revokable API tokens) revocation via a pluggable checker. - server-token: add verifyToken + isTokenExpired + setApiTokenRevocationChecker (the 'method to verify' metadata the plugin needs, without depending on the account client). Revocation cache (60s TTL) now lives here, reusable by any service (transactor, blob access, etc.). - account: the account is now authoritative — wrap() rejects revoked/expired API tokens, so any account method (selectWorkspace/getWorkspaceInfo/...) naturally 401s. Removed the redundant checkApiTokenRevoked method. - account-client: drop checkApiTokenRevoked. - transactor: withSession uses verifyToken; the registered checker reuses the existing getLoginInfoByToken instead of a dedicated boolean RPC. Scopes are parsed once and threaded through (no re-decode in the tx handler). - tests: verifyToken/isTokenExpired unit coverage. Signed-off-by: Don Kendall <dkendall@ledoweb.com> * fix(setting): derive REST API base from account-provided transactor endpoint Address @aonnikov: the REST API host must come from the transactor endpoint returned by the account service (the login endpoint, a ws(s):// URL), not be constructed from window.location. Convert ws->http and append /api/v1, matching the existing ServerManagerGeneral pattern. Signed-off-by: Don Kendall <dkendall@ledoweb.com> * i18n(setting): translate API token strings across all locales Address @ArtyomSavchenko: the new API token UI strings were left in English in non-en locales. Provide translations for ru/de/es/fr/it/pt/pt-br/zh/ja/cs/tr. The en/ru locale-parity test passes (the prior failure was an en/ru key mismatch, resolved by the develop merge). Signed-off-by: Don Kendall <dkendall@ledoweb.com> * style: wrap long lines to satisfy prettier (account utils import, ApiDocsSection) Signed-off-by: Don Kendall <dkendall@ledoweb.com> * fix(api-token): drop unenforceable scopes, harden the token lifecycle The scopes were only ever consulted in the transactor's REST handler, so they promised a boundary the platform did not keep: - the WebSocket transport decodes the token and never looks at scopes, so a read-only token could open a socket and issue any transaction; - even on the REST path, delete:* only matched a top-level TxRemoveDoc and was bypassed by nesting the removal in a TxApplyIf; - nothing stopped a scoped token from calling createApiToken and minting an unscoped one. Narrowing a token's rights has to happen in the pipeline, where it covers every transport, and that is a larger design than this feature. Until then a token carries its account's rights and says so, rather than displaying a restriction that does not hold. Scopes are removed end to end. What is kept is made to work: - API tokens can no longer create, list or revoke API tokens. Otherwise a leaked token renews itself and revokes the tokens meant to stop it. - Revocation fails closed. The account is the only authority on it, so an unreachable account now rejects the token instead of admitting a revoked one to whoever can keep the account busy. Verdicts stay trusted for the cache TTL so brief outages do not cut off healthy tokens. - The revocation cache is bounded and re-checks negative verdicts. - Revoking your own token no longer requires a role in its workspace, so leaving a workspace cannot strand a credential you can never revoke. - The per-account limit counts only usable tokens; revoked and expired ones are kept for the audit trail and used to lock out anyone rotating. - Rejected REST tokens are logged with a reason, since expired, revoked and unverifiable are one opaque 401 from outside. The unused listWorkspaceApiTokens/revokeWorkspaceApiToken pair is removed; it had no caller and no test. Tests cover the role restriction, the API-token guard, ownership on revoke, the limit accounting and fail-closed revocation. Removing any of those checks fails them. Claude-Session: https://claude.ai/code/session_01ANdoXbdn5k2hZy734EwKe7 Signed-off-by: Don Kendall <dkendall@ledoweb.com> * fix(setting): correct the API token settings page - Moves the page from workspace settings to account settings. Tokens belong to the account: the page already lists them across every workspace, and creating one only needs the User role the account service checks, not Owner as the category required. - Surfaces failures. A failed revoke was logged to the console and the row re-rendered unchanged; loading workspaces could reject unhandled and leave an empty dropdown with no explanation. - Outside a secure context there is no clipboard API, so the OK button did nothing and the dialog had no way out but Cancel. It now closes, leaving the token selectable. - Replaces hardcoded English labels, adds aria-expanded on the docs disclosure and labels on the copy targets. - Fills in the Korean and Polish translations, which were the only two locales missing these keys, and drops the API access strings orphaned when this PR replaced the old Generate API token button. Claude-Session: https://claude.ai/code/session_01ANdoXbdn5k2hZy734EwKe7 Signed-off-by: Don Kendall <dkendall@ledoweb.com> * chore: drop docs/openapi.yaml from the API token PR Unrelated to this feature and wrong for this repo: it documents a /_tokens minting service and a tools/mint-token CLI that do not exist here, uses reverse-proxy prefixes from a self-hosted deployment rather than the transactor's /api/v1 routes, and states that revocation is a future enhancement, which is what this PR implements. Nothing references it. REST API docs belong in their own change, generated against the routes that exist. Claude-Session: https://claude.ai/code/session_01ANdoXbdn5k2hZy734EwKe7 Signed-off-by: Don Kendall <dkendall@ledoweb.com> --------- Signed-off-by: Don Kendall <kendall@donkendall.com> Signed-off-by: Don Kendall <dkendall@ledoweb.com>
287 lines
17 KiB
JSON
287 lines
17 KiB
JSON
{
|
|
"string": {
|
|
"Setting": "Configuración",
|
|
"Spaces": "Espacios",
|
|
"Integrations": "Integraciones",
|
|
"Support": "Soporte",
|
|
"Privacy": "Privacidad",
|
|
"Terms": "Términos",
|
|
"AccountSettings": "Ajustes de cuenta",
|
|
"Categories": "Categorías",
|
|
"Delete": "Eliminar",
|
|
"ChangePassword": "Cambiar contraseña",
|
|
"Disconnect": "Desconectar",
|
|
"DisconnectAll": "Desconectar todos",
|
|
"Saving": "Guardando...",
|
|
"Saved": "Guardado",
|
|
"Add": "Añadir",
|
|
"AddNew": "Añadir {type}",
|
|
"Proceed": "Continuar",
|
|
"NewEmail": "Nuevo correo electrónico",
|
|
"SendConfirmation": "Enviar código de confirmación",
|
|
"CodeSent": "El código ha sido enviado. Por favor, introdúcelo en el campo de abajo.",
|
|
"SendAgain": "Enviar de nuevo",
|
|
"SendAgainIn": "Se puede enviar de nuevo en",
|
|
"Value": "Valor",
|
|
"Signout": "Cerrar sesión",
|
|
"Settings": "Ajustes",
|
|
"SelectWorkspace": "Seleccionar espacio de trabajo",
|
|
"InviteWorkspace": "Invitar a espacio de trabajo",
|
|
"DeleteStatus": "Eliminar estado",
|
|
"DeleteStatusConfirm": "¿Quieres eliminar este estado?",
|
|
"Reconnect": "Reconectar",
|
|
"IntegrationDisabled": "ha sido deshabilitada",
|
|
"IntegrationDisabledSetting": "La integración se ha deshabilitado",
|
|
"IntegrationDisabledDescr": "Integración deshabilitada",
|
|
"IntegrationWith": "Integración con ",
|
|
"ClassSetting": "Configuración de clase",
|
|
"ClassSettingHint": "Un grupo o categoría de cosas que tienen alguna propiedad o atributo en común con otras por tipo, clase o calidad.",
|
|
"ClassProperties": "Propiedades de la clase",
|
|
"Classes": "Clases",
|
|
"Attributes": "Atributos",
|
|
"DeleteAttribute": "Eliminar atributo",
|
|
"DeleteAttributeConfirm": "¿Quieres eliminar este atributo?",
|
|
"DeleteAttributeExistConfirm": "¿Quieres eliminar este atributo? Se perderán los datos",
|
|
"DeleteMixin": "Eliminar Mixin",
|
|
"DeleteMixinConfirm": "¿Quieres eliminar este Mixin?",
|
|
"DeleteMixinExistConfirm": "¿Quieres eliminar este Mixin? Los datos no estarán disponibles",
|
|
"Attribute": "Atributo",
|
|
"Custom": "Personalizado",
|
|
"Type": "Tipo",
|
|
"WithTime": "Con hora",
|
|
"DateMode": "Modo de fecha",
|
|
"CreatingAttribute": "Creando un atributo",
|
|
"EditAttribute": "Editar atributo",
|
|
"CreateEnum": "Crear enumeración",
|
|
"EditEnum": "Editar enumeración",
|
|
"Enums": "Enumeraciones",
|
|
"EnumsSettingHint": "Un grupo o categoría de cosas que tienen alguna propiedad o atributo en común con otras por tipo, clase o calidad.",
|
|
"EnumTitle": "Título de la enumeración",
|
|
"EnumsCount": "{count, plural, =1 {# opción} other {# opciones}}",
|
|
"ProjectTypesCount": "{count, plural, =0 {No hay tipos de proyecto} =1 {# tipo de proyecto} other {# tipos de proyecto}}",
|
|
"Options": "Opciones",
|
|
"EnterOptionTitle": "Introduce el título de la opción",
|
|
"NewEnumDialogClose": "¿Quieres cerrar este diálogo?",
|
|
"NewEnumDialogCloseNote": "Se perderán todos los cambios",
|
|
"NewValue": "Nuevo valor",
|
|
"Leave": "Abandonar espacio de trabajo",
|
|
"LeaveDescr": "¿Estás seguro de que quieres abandonar el espacio de trabajo? Esta acción es irreversible.",
|
|
"Members": "Miembros",
|
|
"WorkspaceSettings": "Ajustes del espacio de trabajo",
|
|
"Select": "Seleccionar",
|
|
"AddOwner": "Añadir propietario",
|
|
"ReadonlyGuest": "Solo lectura",
|
|
"Guest": "Invitado",
|
|
"User": "Usuario",
|
|
"Maintainer": "Mantenedor",
|
|
"Owner": "Propietario",
|
|
"OwnerFirstName": "Nombre del propietario",
|
|
"OwnerLastName": "Apellidos del propietario",
|
|
"Role": "Rol",
|
|
"FailedToSave": "Error al actualizar la contraseña",
|
|
"ImportEnum": "Importar valores de enumeración",
|
|
"ImportEnumCopy": "Copiar valores de enumeración del portapapeles",
|
|
"CreateMixin": "Crear Mixin",
|
|
"OldNames": "Valores anteriores",
|
|
"NewClassName": "Introduce un nuevo nombre para la clase o selecciona uno de los valores anteriores...",
|
|
"ShowAttribute": "Mostrar atributo",
|
|
"HideAttribute": "Ocultar atributo",
|
|
"Visibility": "Visibilidad",
|
|
"Hidden": "Oculto",
|
|
"Configure": "Configurar",
|
|
"InviteSettings": "Ajustes de invitación",
|
|
"RoleCapabilitySettings": "Permisos de rol",
|
|
"DefaultInviteRoleForJoin": "Rol predeterminado asignado al unirse mediante enlace de invitación:",
|
|
"InviteLinkGeneratorRoles": "Selecciona los roles de usuario que pueden generar enlaces de invitación:",
|
|
"DefaultValue": "Valor predeterminado",
|
|
"SelectAValue": "Seleccionar un valor",
|
|
"DateOnly": "Solo fecha",
|
|
"OnlyTime": "Solo hora",
|
|
"DateAndTime": "Fecha y hora",
|
|
"Configuration": "Configuración",
|
|
"ConfigurationEnabled": "Habilitado",
|
|
"ConfigurationDisabled": "Deshabilitado",
|
|
"ConfigDisable": "Deshabilitar",
|
|
"ConfigEnable": "Habilitar",
|
|
"ConfigBeta": "Versión beta",
|
|
"Properties": "Propiedades",
|
|
"TaskTypes": "Tipos de tarea",
|
|
"Automations": "Automatizaciones",
|
|
"Collections": "Colecciones",
|
|
"ClassColon": "Clase:",
|
|
"Assignees": "Atribuídos",
|
|
"DeleteRole": "Eliminar función",
|
|
"DeleteRoleConfirmation": "¿Está seguro de que desea eliminar esta función? Todos los usuarios con este rol perderán sus permisos",
|
|
"DeleteWorkspace": "Eliminar espacio de trabajo",
|
|
"DeleteWorkspaceConfirm": "¿Estás seguro de que quieres eliminar este espacio de trabajo? Tú y todos los demás miembros perderán el acceso a este espacio de trabajo. Toda la información del espacio de trabajo se perderá. Esta acción no se puede deshacer. ¿Quieres continuar?",
|
|
"DeleteSpaceType": "Eliminar tipo de espacio",
|
|
"DeleteSpaceTypeConfirm": "¿Estás seguro de que quieres eliminar este tipo de espacio?",
|
|
"WorkspaceName": "Nombre del espacio de trabajo",
|
|
"Workspace": "Espacio de trabajo",
|
|
"OwnerOrMaintainerRequired": "Necesitas ser Propietario o Mantenedor del espacio de trabajo",
|
|
"LastOwnerLeaveTitle": "No puedes abandonar el espacio de trabajo",
|
|
"LastOwnerLeaveMessage": "Eres el único propietario de este espacio de trabajo. Para salir, primero asigna permisos de propietario a otro miembro. Si nadie más necesita este espacio de trabajo, considera eliminarlo.",
|
|
"Backup": "Copia de seguridad",
|
|
"BackupLast": "Última copia de seguridad",
|
|
"BackupTotalSnapshots": "Total instantáneas",
|
|
"BackupTotalFiles": "Archivos",
|
|
"BackupSize": "Tamaño de la copia de seguridad",
|
|
"BackupLinkInfo": "La URL de un directorio de copia de seguridad que se puede descargar de forma recursiva usando herramientas como wget o curl.",
|
|
"BackupBearerTokenInfo": "Se requiere un token de portador para acceder a la copia de seguridad.",
|
|
"BackupSnapshots": "Instantáneas de copia de seguridad",
|
|
"BackupFileDownload": "Descargar archivo",
|
|
"BackupFiles": "Archivos de copia de seguridad",
|
|
"BackupNoBackup": "No hay copias de seguridad disponibles actualmente.",
|
|
"BackupDownloadAll": "Descargar copia de seguridad completa",
|
|
"BackupPreparingDownload": "Preparando la copia de seguridad…",
|
|
"BackupDownloadAllInfo": "Descarga todos los archivos de la copia de seguridad en un único archivo .zip que puedes guardar en tu ordenador.",
|
|
"BackupCopyScript": "Copiar script de descarga",
|
|
"BackupCopyToken": "Copiar token",
|
|
"BackupScriptInfo": "Un script de shell que descarga todos los archivos de la copia de seguridad con curl. Guárdalo y ejecútalo en una terminal; te pedirá tu token de copia de seguridad, por lo que no se almacenan secretos en el script.",
|
|
"BackupRestoreGuide": "Guía de copia de seguridad y restauración",
|
|
"BackupRestoreGuideInfo": "Instrucciones paso a paso para descargar esta copia de seguridad y restaurarla en otra instancia de Huly.",
|
|
"NonBackupedBlobs": "Blobs no respaldados",
|
|
"Calendar": "Calendario",
|
|
"StartOfTheWeek": "Inicio de la semana",
|
|
"SystemSetupString": "Configuración del sistema ({day})",
|
|
"DefaultString": "Predeterminado ({day})",
|
|
"AddAttribute": "Añadir atributo",
|
|
"WorkspaceNamePattern": "El nombre debe tener 40 caracteres o menos, no esté vacío y no puede contener caracteres especiales (<, >, /)",
|
|
"Mailboxes": "Buzones",
|
|
"CreateMailbox": "Crear buzón",
|
|
"CreateMailboxPlaceholder": "mi-nombre-genial",
|
|
"MailboxNoDomains": "Los dominios de correo electrónico no están configurados",
|
|
"MailboxLimitReached": "Límite de buzones alcanzado",
|
|
"MailboxErrorInvalidName": "El nombre del buzón no es válido",
|
|
"MailboxErrorDomainNotFound": "Dominio no encontrado",
|
|
"MailboxErrorNameRulesViolated": "El nombre del buzón debe tener entre {minLen} y {maxLen} caracteres",
|
|
"MailboxErrorMailboxExists": "Este buzón ya está ocupado",
|
|
"MailboxErrorMailboxCountLimit": "Se ha alcanzado el límite de buzones de su cuenta",
|
|
"DeleteMailbox": "Eliminar buzón",
|
|
"MailboxDeleteConfirmation": "¿Está seguro de que desea eliminar este buzón?",
|
|
"DisablePermissions": "Desactivar el control de acceso basado en roles",
|
|
"EnablePermissions": "Activar el control de acceso basado en roles",
|
|
"DisablePermissionsConfirmation": "¿Está seguro de que desea desactivar el control de acceso basado en roles? Todos los roles y permisos serán desactivados.",
|
|
"EnablePermissionsConfirmation": "¿Está seguro de que desea activar el control de acceso basado en roles? Todos los roles y permisos serán activados.",
|
|
"BetaWarning": "Los módulos etiquetados como beta están disponibles con fines experimentales y pueden no ser completamente funcionales. No recomendamos confiar en las funciones beta para trabajos críticos en este momento.",
|
|
"IntegrationFailed": "Error al crear la integración",
|
|
"IntegrationError": "Por favor, inténtelo de nuevo o contacte con soporte si el problema persiste",
|
|
"EmailIsUsed": "El correo electrónico ya está en uso",
|
|
"Customize": "Personalizar",
|
|
"GuestAccess": "Invitados anónimos",
|
|
"GuestAccessDescription": "Permite a usuarios anónimos visitar el espacio de trabajo en modo de solo lectura",
|
|
"GuestSignUpDescription": "Permite a usuarios anónimos unirse a su espacio de trabajo como invitados con derechos de edición limitados",
|
|
"GuestChannelsDescription": "Canales donde los invitados pueden escribir mensajes después de unirse",
|
|
"GuestChannelsArrayLabel": "Seleccionar canales",
|
|
"GuestSelectSpaces": "Seleccionar espacios",
|
|
"GuestAutoJoinAvailableSpaces": "Unión automática a espacios",
|
|
"GuestAutoJoinAvailableSpacesHint": "Cada tarjeta de aplicación tiene su propia fila « Unión automática a espacios »: elija dónde se añaden los invitados al activarse. Los cambios son inmediatos.",
|
|
"GuestAnonymousVisibleSpaces": "Espacios visibles de forma anónima",
|
|
"GuestAnonymousVisibleSpacesHint": "Cada tarjeta de aplicación tiene su propia fila: elija espacios donde se añade la cuenta anónima de solo lectura como miembro para que los visitantes sin cuenta puedan abrirlos. Los cambios son inmediatos.",
|
|
"ManageIdentities": "Gestionar identidades",
|
|
"Release": "Liberar",
|
|
"ReleaseSocialId": "Liberar ID social",
|
|
"ReleaseSocialIdConfirm": "¿Estás seguro de que quieres liberar este ID social: {socialId}? Esto lo eliminará de tu cuenta y ya no podrás usarlo para iniciar sesión. Además, todas las integraciones asociadas serán eliminadas.",
|
|
"ReleasePrimarySocialId": "Liberar ID social primario",
|
|
"ReleasePrimarySocialIdConfirm": "Liberar tu ID social primario actual requerirá que se recargue la página. ¿Estás seguro de que quieres continuar?",
|
|
"Login": "Iniciar sesión",
|
|
"Primary": "Primario",
|
|
"MyIntegrations": "Mis integraciones",
|
|
"AllIntegrations": "Todas",
|
|
"ConnectedIntegrations": "Conectadas",
|
|
"AvailableIntegrations": "Disponibles",
|
|
"Connect": "Conectar",
|
|
"Integrate": "Integrar",
|
|
"FailedToLoadIntegrations": "Error al cargar las integraciones",
|
|
"FailedToDisconnect": "Error al desconectar la integración",
|
|
"ServiceIsUnavailable": "El servicio no está disponible",
|
|
"Integrated": "Integrado",
|
|
"Connected": "Conectado",
|
|
"Disconnected": "Desconectado",
|
|
"Available": "Disponible",
|
|
"NotConnectedIntegration": "La cuenta {account} no está integrada con el espacio de trabajo",
|
|
"IntegrationIsUnstable": "El servicio de integración está experimentando problemas. Es posible que algunas funciones no funcionen correctamente.",
|
|
"MinValue": "Valor mínimo",
|
|
"Restricted": "Restringido",
|
|
"RestrictedAttributeWarning": "¿Está seguro de que desea restringir la modificación de este atributo? Esta acción creará permisos para este atributo y no se puede deshacer.",
|
|
"MaxValue": "Valor máximo",
|
|
"IntegerOnly": "Solo números enteros",
|
|
"AccessControl": "Control de acceso",
|
|
"DangerZone": "Zona de peligro",
|
|
"IdentifierExists": "El identificador ya existe",
|
|
"PasswordAgingRule": "Regla de envejecimiento de contraseñas",
|
|
"PasswordAgingRuleDescription": "Número de días después de los cuales se requerirá a los usuarios que cambien su contraseña.",
|
|
"OfficeSettings": "Configuración de oficina",
|
|
"OfficeDefaultSettings": "Configuración predeterminada para salas de reuniones",
|
|
"DefaultStartWithTranscription": "Habilitar transcripción en nuevas oficinas",
|
|
"DefaultStartWithRecording": "Habilitar grabación en nuevas oficinas",
|
|
"GuestPermissionsSettings": "Invitados",
|
|
"GuestPermissionsApplicationPermissions": "Permisos de aplicaciones",
|
|
"GuestPermissionsApplicationPermissionsHint": "Elija qué aplicaciones pueden usar los invitados y luego ajuste los permisos de cada aplicación a continuación.",
|
|
"GuestPermissionsTabGuest": "Invitado",
|
|
"GuestPermissionsTabAnonymousGuest": "Invitado anónimo",
|
|
"GuestPermissionsAnonymousApplicationHint": "Acceso a aplicaciones para invitados anónimos (solo lectura). Las aplicaciones que ven también pueden depender de la configuración de despliegue.",
|
|
"ImportDocumentPermission": "Importar documentos",
|
|
"ImportDocumentDescription": "Otorga a los usuarios la capacidad de importar documentos al espacio de trabajo",
|
|
"SelectUsers": "Seleccionar usuarios",
|
|
"ShowInTitle": "Mostrar en el título",
|
|
"SpaceMembersOnly": "Solo miembros del espacio",
|
|
"Reset": "Reiniciar",
|
|
"Security": "Seguridad",
|
|
"TwoFactorAuth": "Autenticación de dos factores",
|
|
"TwoFactorAuthDescription": "La autenticación de dos factores añade una capa adicional de seguridad a tu cuenta",
|
|
"EnableTwoFactorAuth": "Habilitar autenticación de dos factores",
|
|
"DisableTwoFactorAuth": "Deshabilitar autenticación de dos factores",
|
|
"TwoFactorAuthEnabled": "La autenticación de dos factores está habilitada",
|
|
"TwoFactorAuthDisabled": "La autenticación de dos factores está deshabilitada",
|
|
"ShowQRCode": "Mostrar código QR",
|
|
"EnterVerificationCode": "Introducir código de verificación",
|
|
"OverrideAttribute": "Sobreescribir atributo",
|
|
"Required": "Requerido",
|
|
"ApiBaseUrl": "URL base",
|
|
"ApiEndpointAccount": "Obtener información de la cuenta",
|
|
"ApiEndpointFindAll": "Consultar documentos por clase",
|
|
"ApiEndpointFindAllPost": "Consulta con filtros (cuerpo JSON)",
|
|
"ApiEndpointLoadModel": "Cargar el modelo de datos",
|
|
"ApiEndpointPing": "Comprobación de estado",
|
|
"ApiEndpointTx": "Crear o actualizar documentos",
|
|
"ApiTokenCopyWarning": "Copia este token ahora. No podrás volver a verlo.",
|
|
"ApiTokenCreated": "Token creado",
|
|
"ApiTokenExpiry": "Expiración",
|
|
"ApiTokenName": "Nombre del token",
|
|
"ApiTokenNoTokens": "Aún no hay tokens de API",
|
|
"ApiTokenRevoke": "Revocar token",
|
|
"ApiTokenRevokeConfirm": "¿Seguro que quieres revocar este token? Ya no se podrá usar para el acceso a la API.",
|
|
"ApiTokenWorkspace": "Espacio de trabajo",
|
|
"ApiTokens": "Tokens de API",
|
|
"ApiUsageDescription": "Usa tu token de API con la API REST integrada para consultar y modificar los datos del espacio de trabajo. Pasa el token como token Bearer en el encabezado Authorization.",
|
|
"ApiUsageTitle": "Uso de la API REST",
|
|
"ApiWorkspaceId": "El ID de tu espacio de trabajo (UUID) está incluido en el token. Pásalo como :workspaceId en la URL.",
|
|
"CountSpaces": "{count, plural, =0 {No spaces} =1 {# space} other {# spaces}}",
|
|
"CreateApiToken": "Crear token",
|
|
"Created": "Creado",
|
|
"Description": "Description",
|
|
"Expires": "Expira",
|
|
"General": "General",
|
|
"NewSpaceType": "New space type",
|
|
"Permissions": "Permissions",
|
|
"RoleName": "Role name",
|
|
"Roles": "Roles",
|
|
"SpaceTypeTitle": "Space type title",
|
|
"SpaceTypes": "Space types",
|
|
"TokenStatus": "Estado",
|
|
"ApiTokenStatusActive": "Activo",
|
|
"ApiTokenStatusExpiring": "Por expirar",
|
|
"ApiTokenStatusRevoked": "Revocado",
|
|
"ApiTokenStatusExpired": "Expirado",
|
|
"ApiTokenExpiry7Days": "7 días",
|
|
"ApiTokenExpiry30Days": "30 días",
|
|
"ApiTokenExpiry90Days": "90 días",
|
|
"ApiTokenExpiry180Days": "180 días",
|
|
"ApiTokenExpiry365Days": "365 días",
|
|
"ApiTokenLoadError": "No se pudieron cargar los tokens de API",
|
|
"ApiTokenCreateError": "No se pudo crear el token. Inténtalo de nuevo.",
|
|
"ApiTokenRevokeError": "No se pudo revocar el token. Inténtalo de nuevo."
|
|
}
|
|
}
|