The webmail was indigo over glass and the console was green over glass, so the
two halves of one product did not look related, and neither followed a system
anything could be checked against. This replaces the interface with the
Nocturne design system from Claude Design: a near-neutral blue-grey ground,
Inter at weight 500, solid surfaces with a 1px inset edge instead of blur, and
a single blurple accent used as a line, a mark and a glow rather than a flood.
The palette is remapped at the source rather than renamed at every call site.
tailwind.config.js points slate, indigo, emerald, teal and the rest at the
Nocturne ramps, and globals.css carries the same values as variables, so a
utility class and a token cannot drift apart and no colour can enter the
interface from outside the system. The console's green is gone because it
resolves to the one accent; that was the point.
Structurally, both surfaces now share one rail - the same brand mark, the same
3px accent mark on the active item, the same account tile - with a segmented
control for crossing between them. Crossing into the console still goes to the
step-up rather than the admin sign-in, and leaving it is still a plain link.
Settings moves from eight stacked panels to a tab strip, so enabling a second
factor and writing a filter are no longer separated by everything else.
Nothing is sized by the length of its text any more. Labels wrap, tab strips
wrap instead of scrolling, subjects and queue diagnostics wrap instead of
truncating, and the message list's snippet is clamped to two lines rather than
one. That is what broke when the interface was read in Portuguese or Spanish.
Defects found while doing it:
- The queue and DMARC screens styled their status pills with "badge-danger",
"badge-warning" and "badge-verified" - three class names no stylesheet in
this project defines - so every verdict rendered as identical unstyled
text. They are Badge variants now, which exist.
- The DMARC screen printed the literal string "quarantine" as the
enforcement level whatever the domains publish. The report endpoint returns
no policy at all, so it was asserting a configuration nobody had made. It
shows the DMARC pass ratio it genuinely has.
- Half the mailboxes screen and two lines of the audit trace were hardcoded
strings, some Portuguese and some English, so they stayed in one language
whatever the interface was set to. They come from the bundle now, with the
new keys added to all three locales.
- Avatars printed email[0], so every account at one domain collapsed onto the
same letter. initialsFor takes two letters from the local part's own word
boundaries, behind tests.
Trivy reported one HIGH: nanoid 3.3.16, pulled in transitively by postcss,
vulnerable to a denial of service via an infinite loop in ID generation
(CVE-2026-67213). Pinned to ^3.3.18 through the overrides block the package
already uses for sharp and postcss.
Verified: 98 webmail tests green, tsc clean, production build clean, and the
compiled stylesheet serves the Nocturne values with no stock Tailwind indigo,
emerald or slate hex left in it. Trivy fs with the CI scanners, severities and
skip-dirs exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
327 lines
14 KiB
JSON
327 lines
14 KiB
JSON
{
|
|
"admin": {
|
|
"addAlias": "Añadir apelido",
|
|
"aliasTarget": "Dirección de destino",
|
|
"aliasesTitle": "Alias",
|
|
"auditLog": "Registro de auditoría",
|
|
"backToWebmail": "Volver al webmail",
|
|
"cancelJob": "Cancelar",
|
|
"certificateState": "Certificado",
|
|
"checksPassed": "{passed} de {total} aprobadas",
|
|
"createAccount": "Crear cuenta",
|
|
"createAlias": "Crear un alias de enrutamiento",
|
|
"csvImportFailed": "La importación del CSV falló",
|
|
"csvImported": "{count} buzones importados.",
|
|
"csvIntro": "Pega el CSV para crear varias cuentas con sus carpetas de la RFC 6154. Columnas: email, rol, cuota_mb.",
|
|
"csvPreview": "Vista previa",
|
|
"csvRun": "Ejecutar la importación",
|
|
"csvTitle": "Importar buzones en masa (CSV)",
|
|
"dashboardSubtitle": "Cifras en vivo leídas de la base de datos.",
|
|
"dashboardTitle": "Resumen",
|
|
"dkimAlgorithm": "Tipo de clave",
|
|
"dkimOverlap": "Ambas claves firman el correo saliente durante {days} días para que nada falle mientras el DNS se propaga.",
|
|
"dkimPublishRecord": "Publique este registro en DNS:",
|
|
"dkimRotate": "Generar una nueva clave",
|
|
"dkimSelector": "Selector",
|
|
"dkimTitle": "Rotación de clave DKIM",
|
|
"dmarcSubtitle": "Desglose de los informes XML agregados procesados.",
|
|
"dmarcTitle": "Informes DMARC",
|
|
"dnsRecordsFor": "Registros DNS de {domain}",
|
|
"dnsStatusDrift": "Divergente",
|
|
"dnsStatusPartial": "Parcial",
|
|
"dnsStatusVerified": "Verificado",
|
|
"domainName": "Nombre del dominio",
|
|
"domainsTitle": "Dominios",
|
|
"expiresInDays": "Caduca en {days} días",
|
|
"freezeDomain": "Congelar dominio",
|
|
"greylistScore": "Puntuación de greylist",
|
|
"headerScore": "Puntuación de etiquetado de cabecera",
|
|
"jobCancelled": "El trabajo {id} fue cancelado.",
|
|
"jobRetried": "El trabajo {id} se volvió a poner en cola para otro intento.",
|
|
"lastChecked": "Última comprobación: {when}",
|
|
"lastReload": "Última recarga",
|
|
"lockAccount": "Bloquear",
|
|
"mailHost": "Host de correo",
|
|
"mailboxCount": "{count} buzones",
|
|
"mailboxesSubtitle": "Cuentas, alias, importación CSV y la política de segundo factor.",
|
|
"mailboxesTitle": "Buzones",
|
|
"mfaAdmins": "Obligatorio para administradores",
|
|
"mfaEveryone": "Obligatorio para todos",
|
|
"mfaOptional": "Opcional",
|
|
"mfaPolicyIntro": "Elija con qué rigor este dominio exige un segundo factor.",
|
|
"mfaPolicyTitle": "Requisito de segundo factor",
|
|
"noCertificate": "No hay certificado cargado para este host.",
|
|
"noChecks": "No se informaron verificaciones.",
|
|
"noDomains": "Aún no se ha dado de alta ningún dominio.",
|
|
"notPublished": "No publicado",
|
|
"onboardIntro": "Crea el dominio y sus alias estándar RFC 2142, apuntados a su dirección.",
|
|
"onboardTitle": "Añadir un dominio",
|
|
"openAdmin": "Consola de administración",
|
|
"preflightTitle": "Verificaciones de preparación",
|
|
"presentProxied": "Presente (con proxy)",
|
|
"queueEmpty": "La cola de salida está vacía.",
|
|
"queueSubtitle": "Inspeccione la cola de salida, reintente un trabajo o cancele uno.",
|
|
"queueTitle": "Cola de salida",
|
|
"quotaMb": "Cuota (MB)",
|
|
"readinessIntro": "Verificaciones que el servidor informa sobre sí mismo antes de transportar correo en producción.",
|
|
"reconcileDns": "Reconciliar DNS",
|
|
"reconcileNotImplemented": "La verificación de registros DNS individuales aún no está implementada: esto registra la solicitud y relee el estado almacenado, no consulta un resolutor.",
|
|
"rejectScore": "Puntuación de rechazo",
|
|
"retryJob": "Reintentar",
|
|
"rspamdIntro": "Puntuaciones que activan greylisting, etiquetado de cabecera y rechazo.",
|
|
"rspamdSaved": "Umbrales guardados.",
|
|
"saveThresholds": "Guardar umbrales",
|
|
"securitySubtitle": "Verificaciones de preparación, estado TLS, umbrales de spam y el registro de auditoría.",
|
|
"securityTitle": "Seguridad",
|
|
"tabAccounts": "Cuentas",
|
|
"tabAliases": "Alias",
|
|
"tabAudit": "Registro de auditoría",
|
|
"tabCsv": "Importación masiva",
|
|
"tabReadiness": "Preparación",
|
|
"tabRspamd": "Umbrales de spam",
|
|
"tabTls": "TLS",
|
|
"tlsMode": "Modo TLS",
|
|
"tlsTitle": "Certificado y transporte",
|
|
"traceNoResults": "No se encontró rastro para ese ID de cola.",
|
|
"tracePlaceholder": "ID de la cola",
|
|
"traceResultFor": "Rastreo de {id}",
|
|
"traceStep": "Paso {n}",
|
|
"traceTitle": "Rastrear un mensaje",
|
|
"unknownSni": "Solicitudes SNI desconocidas",
|
|
"unlockAccount": "Desbloquear",
|
|
"verifyIntro": "Resuelve cada registro esperado en resolutores públicos e informa uno por uno.",
|
|
"watcherHealthy": "Monitor de certificado"
|
|
},
|
|
"auth": {
|
|
"adminLoginTitle": "Consola de administración",
|
|
"adminStepUpNote": "La consola de administración vuelve a pedir su segundo factor, aunque ya haya iniciado sesión en el webmail.",
|
|
"authFailed": "Fallo en la autenticación",
|
|
"cantScanQr": "¿No puede escanear? Introduzca esta clave manualmente:",
|
|
"emailLabel": "Dirección de correo",
|
|
"enrolmentFailed": "No se pudo iniciar la configuración del segundo factor",
|
|
"enrolmentIntro": "La consola de administración requiere un segundo factor. Configure uno ahora para continuar.",
|
|
"genericError": "Algo salió mal",
|
|
"invalidCredentials": "Correo o contraseña inválidos",
|
|
"mfaRequired": "Introduzca el código de seis dígitos de su aplicación de autenticación.",
|
|
"orRecoveryCode": "¿Perdiste el teléfono? Aquí también sirve un código de recuperación.",
|
|
"passwordLabel": "Contraseña",
|
|
"qrCodeAlt": "Código QR para configurar la verificación en dos pasos",
|
|
"scanQr": "Escanee este código con Google Authenticator, Aegis, Authy o 1Password.",
|
|
"signInButton": "Iniciar sesión",
|
|
"signOutOfAdmin": "Salir de administración",
|
|
"stepUpIntro": "Ya has iniciado sesión, así que solo hace falta tu segundo factor. No se te pide la contraseña otra vez.",
|
|
"stepUpSignedInAs": "Sesión iniciada como {email}",
|
|
"stepUpTitle": "Abrir la consola de administración",
|
|
"totpCodeLabel": "Código de autenticación",
|
|
"userLoginTitle": "Acceda a su buzón",
|
|
"verificationFailed": "Fallo en la verificación",
|
|
"verifyCodeButton": "Verificar código"
|
|
},
|
|
"common": {
|
|
"actions": "Acciones",
|
|
"add": "Añadir",
|
|
"adminPortal": "Administración",
|
|
"appName": "LambdaMail",
|
|
"back": "Volver",
|
|
"cancel": "Cancelar",
|
|
"confirm": "Confirmar",
|
|
"continue": "Continuar",
|
|
"copied": "Copiado",
|
|
"copy": "Copiar",
|
|
"delete": "Eliminar",
|
|
"loading": "Cargando...",
|
|
"logout": "Cerrar sesión",
|
|
"never": "Nunca",
|
|
"none": "Ninguno",
|
|
"refresh": "Actualizar",
|
|
"retry": "Reintentar",
|
|
"save": "Guardar",
|
|
"search": "Buscar",
|
|
"status": "Estado",
|
|
"unavailable": "No disponible",
|
|
"userPortal": "Webmail"
|
|
},
|
|
"errors": {
|
|
"forbidden": "No tiene acceso a esto",
|
|
"loadFailed": "No se pudieron cargar los datos",
|
|
"serverError": "Algo salió mal en el servidor",
|
|
"unauthorized": "Inicie sesión de nuevo"
|
|
},
|
|
"mail": {
|
|
"addFiles": "Añadir archivos...",
|
|
"allMessages": "Todas",
|
|
"archive": "Archivo",
|
|
"attachments": "Adjuntos ({count})",
|
|
"attachmentsFilter": "Con adjuntos",
|
|
"attachmentsUnsupported": "Los adjuntos se listan solo por nombre; la subida de archivos aún no está implementada.",
|
|
"backToList": "Volver a la lista de mensajes",
|
|
"bold": "Negrita",
|
|
"bulletList": "Lista con viñetas",
|
|
"compose": "Redactar",
|
|
"discard": "Descartar",
|
|
"draftSaveFailed": "No se pudo guardar el borrador",
|
|
"draftSaved": "Borrador guardado automáticamente",
|
|
"draftSaving": "Guardando borrador...",
|
|
"drafts": "Borradores",
|
|
"emptyBody": "Este mensaje no tiene cuerpo de texto.",
|
|
"forward": "Reenviar",
|
|
"imagesEnabled": "Imágenes cargadas",
|
|
"hideCcBcc": "- Ocultar Cc/Cco",
|
|
"inbox": "Bandeja de entrada",
|
|
"insertLink": "Insertar enlace",
|
|
"insertUrl": "Introduzca la URL:",
|
|
"italic": "Cursiva",
|
|
"junk": "Spam",
|
|
"loadImages": "Cargar imágenes",
|
|
"markRead": "Marcar como leído",
|
|
"markUnread": "Marcar como no leído",
|
|
"messagesInFolder": "{count} mensajes",
|
|
"noMatches": "Nada coincide con esa búsqueda",
|
|
"noMessages": "Sin mensajes",
|
|
"noSubject": "(Sin asunto)",
|
|
"numberedList": "Lista numerada",
|
|
"remoteContentBlocked": "Se bloquearon las imágenes remotas para que este mensaje no pueda rastrearte.",
|
|
"reply": "Responder",
|
|
"searchMatches": "{count} encontrados",
|
|
"searchPlaceholder": "Buscar (from:, subject:)...",
|
|
"selectAMessage": "Selecciona un mensaje para leerlo",
|
|
"sendMessage": "Enviar mensaje",
|
|
"sending": "Enviando...",
|
|
"sent": "Enviados",
|
|
"showCcBcc": "+ Añadir Cc/Cco",
|
|
"strikethrough": "Tachado",
|
|
"trash": "Papelera",
|
|
"underline": "Subrayado",
|
|
"undoSend": "Enviando en {seconds}s",
|
|
"undoSendAction": "Deshacer",
|
|
"unreadCount": "{count} sin leer",
|
|
"unreadFilter": "Sin leer"
|
|
},
|
|
"settings": {
|
|
"actionDiscard": "Descartar",
|
|
"actionFlag": "Marcar mensaje",
|
|
"actionMove": "Mover al Archivo",
|
|
"addRule": "Añadir regla",
|
|
"appPasswordPlaceholder": "Thunderbird / Outlook Mobile",
|
|
"appPasswords": "Contraseñas de aplicación",
|
|
"autoReplySaveFailed": "No se pudo guardar la respuesta automática",
|
|
"enableMfa": "Activar verificación en dos pasos",
|
|
"fieldFrom": "De",
|
|
"fieldHeader": "Cabecera",
|
|
"fieldSubject": "Asunto",
|
|
"generateAppPassword": "Generar",
|
|
"langEn": "English",
|
|
"langEs": "Español",
|
|
"langPtBR": "Português (Brasil)",
|
|
"language": "Idioma",
|
|
"matchContains": "contiene",
|
|
"matchEquals": "es exactamente",
|
|
"matchRegex": "coincide con regex",
|
|
"mfaDisabled": "Desactivada",
|
|
"mfaEnabled": "Activada",
|
|
"mfaStatus": "Estado de la verificación en dos pasos",
|
|
"recoveryCodesTitle": "Códigos de recuperación",
|
|
"ruleIf": "SI",
|
|
"ruleThen": "ENTONCES",
|
|
"saveAutoReply": "Guardar respuesta automática",
|
|
"saveRecoveryCodes": "Guárdelos en un lugar seguro. Cada uno funciona una sola vez y solo se muestran ahora.",
|
|
"security": "Seguridad",
|
|
"sessions": "Sesiones",
|
|
"settingsSaved": "Configuración guardada.",
|
|
"sieveIntro": "Reglas que organizan el correo entrante automáticamente.",
|
|
"sieveTitle": "Filtros (Sieve)",
|
|
"signOut": "Cerrar sesión",
|
|
"signatureIntro": "Se añade automáticamente a los mensajes que redacta.",
|
|
"signaturePlaceholder": "Saludos cordiales,\nSu nombre\nSu cargo",
|
|
"signatureSaveFailed": "No se pudo guardar la firma",
|
|
"signatureSaved": "Firma guardada.",
|
|
"signatureTitle": "Firma de correo",
|
|
"sixDigitCode": "Código de seis dígitos",
|
|
"startOverMfa": "¿Perdió el registro? Empiece de nuevo con una clave nueva",
|
|
"subtitle": "Verificación en dos pasos, filtros, respuesta automática y su firma.",
|
|
"title": "Configuración",
|
|
"twoFactorIntro": "Proteja su cuenta con Google Authenticator, Aegis, Authy o 1Password.",
|
|
"vacationBodyLabel": "Mensaje de la respuesta",
|
|
"vacationDefaultBody": "Gracias por su mensaje. Estoy ausente en este momento y responderé a mi regreso.",
|
|
"vacationDefaultSubject": "Fuera de la oficina",
|
|
"vacationIntro": "Responde automáticamente al correo entrante mientras esté ausente.",
|
|
"vacationSubjectLabel": "Asunto de la respuesta",
|
|
"vacationTitle": "Respuesta automática de ausencia",
|
|
"valuePlaceholder": "Valor a coincidir..."
|
|
},
|
|
"ui": {
|
|
"accountLocked": "Bloqueada",
|
|
"accountStatus": "Estado de la cuenta",
|
|
"actions": "Acciones",
|
|
"active": "Activo",
|
|
"activeSessions": "Sesiones activas",
|
|
"actor": "Autor",
|
|
"actualRecord": "Valor actual",
|
|
"allChecksPassed": "Todas las verificaciones pasaron",
|
|
"appPasswordGenerated": "Contraseña de aplicación generada",
|
|
"appPasswordsSection": "Contraseñas de aplicación",
|
|
"attempts": "Intentos",
|
|
"bounceRate": "Tasa de rebote",
|
|
"ccRecipients": "Cc",
|
|
"changePassword": "Cambiar contraseña",
|
|
"clientIp": "IP del cliente",
|
|
"copyPasswordNow": "Cópiela ahora. No se mostrará de nuevo.",
|
|
"coreInfra": "Servicios principales",
|
|
"currentPassword": "Contraseña actual",
|
|
"currentSession": "Este dispositivo",
|
|
"daneVerified": "DANE verificado",
|
|
"destination": "Destino",
|
|
"diskUsed": "Almacenamiento usado",
|
|
"dkimAlignment": "Alineación DKIM",
|
|
"dkimResult": "DKIM",
|
|
"dmarcEnforcement": "Política DMARC",
|
|
"domainVerification": "Verificación de dominio",
|
|
"domainsVerified": "Dominios verificados",
|
|
"emailAddress": "Dirección de correo",
|
|
"eventAction": "Acción",
|
|
"expectedValue": "Valor esperado",
|
|
"healthy": "Correcto",
|
|
"imapEngine": "Servicio IMAP",
|
|
"inboundVolume": "Recibidas (24h)",
|
|
"jobId": "Trabajo",
|
|
"lastError": "Último error",
|
|
"liveMetrics": "Métricas en vivo",
|
|
"localDisk": "Disco local",
|
|
"mailboxesActive": "Buzones activos",
|
|
"messageBody": "Mensaje",
|
|
"messageVolume": "Mensajes",
|
|
"mfaActive": "TOTP activo",
|
|
"mfaNone": "Sin segundo factor",
|
|
"newPassword": "Nueva contraseña",
|
|
"noAppPasswords": "Aún no hay contraseñas de aplicación.",
|
|
"noData": "Aún sin datos",
|
|
"online": "En línea",
|
|
"outboundDelivered": "Enviadas (24h)",
|
|
"passwordChanged": "Contraseña cambiada.",
|
|
"postgresRunner": "Cola basada en Postgres",
|
|
"preflightTitle": "Preparación",
|
|
"provisionMailbox": "Crear buzón",
|
|
"queueDepth": "Tamaño de la cola",
|
|
"recipient": "Destinatario",
|
|
"recordName": "Registro",
|
|
"reportingOrg": "Organización informante",
|
|
"role": "Rol",
|
|
"scanners": "Análisis de spam y virus",
|
|
"sender": "Remitente",
|
|
"signOutOthers": "Cerrar sesión en otros dispositivos",
|
|
"smtpListener": "Servicio SMTP",
|
|
"sourceIp": "IP de origen",
|
|
"spfRatio": "Tasa de aprobación SPF",
|
|
"spfResult": "SPF",
|
|
"storageQuota": "Cuota de almacenamiento",
|
|
"subject": "Asunto",
|
|
"targetObject": "Objetivo",
|
|
"timestamp": "Hora",
|
|
"toRecipients": "Para",
|
|
"toggleMenu": "Alternar menú",
|
|
"totalEvaluated": "Mensajes evaluados",
|
|
"twoFactorSection": "Verificación en dos pasos",
|
|
"watching": "Vigilando"
|
|
}
|
|
}
|