The mail list rendered two hardcoded messages and the reader showed their canned HTML; compose ran a countdown and then navigated away without ever submitting anything. Both now use the API, including search, the unread badges in the sidebar (which were the literals "3" and "1", so an empty inbox still advertised unread mail), and marking a message read on open. The undo window now means what it says: the message is held in the browser and only submitted when the countdown elapses, so cancelling it means nothing was ever queued rather than trying to recall it afterwards. Message bodies render in an iframe with an empty sandbox - no scripts, no same-origin - and remote references are stripped until the reader asks for images, so a tracking pixel cannot fire on open. The previous sandbox allowed popups. The admin page titles and the language switcher labels now come from the bundles. The labels live there rather than in the source because PLAN.md R9 keeps non-ASCII out of code, and each language should be named the way that language names it. ADR-001 assigned the mail API to the TypeScript storage service; the reasoning for putting it in Go instead is recorded in PLAN.md, which .gitignore deliberately keeps out of the repository, so that revision lives only in the working copy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
84 lines
3.0 KiB
JSON
84 lines
3.0 KiB
JSON
{
|
|
"common": {
|
|
"appName": "LambdaMail",
|
|
"userPortal": "Webmail",
|
|
"adminPortal": "Consola de Gestión",
|
|
"loading": "Cargando...",
|
|
"save": "Guardar Cambios",
|
|
"cancel": "Cancelar",
|
|
"delete": "Eliminar",
|
|
"confirm": "Confirmar",
|
|
"search": "Buscar",
|
|
"status": "Estado",
|
|
"actions": "Acciones",
|
|
"refresh": "Actualizar",
|
|
"logout": "Cerrar Sesión"
|
|
},
|
|
"auth": {
|
|
"userLoginTitle": "Iniciar Sesión en Webmail",
|
|
"adminLoginTitle": "Iniciar Sesión en Consola Admin",
|
|
"emailLabel": "Dirección de Correo",
|
|
"passwordLabel": "Contraseña",
|
|
"signInButton": "Iniciar Sesión",
|
|
"totpCodeLabel": "Código del Autenticador (6 dígitos)",
|
|
"verifyCodeButton": "Verificar Código",
|
|
"invalidCredentials": "Correo o contraseña no válidos",
|
|
"mfaRequired": "Código de autenticación de dos factores requerido"
|
|
},
|
|
"mail": {
|
|
"inbox": "Bandeja de Entrada",
|
|
"sent": "Enviados",
|
|
"drafts": "Borradores",
|
|
"trash": "Papelera",
|
|
"junk": "Spam",
|
|
"archive": "Archivo",
|
|
"compose": "Redactar Correo",
|
|
"noMessages": "No hay mensajes en esta carpeta",
|
|
"unreadCount": "{count, plural, =0 {Sin mensajes no leídos} one {# mensaje no leído} other {# mensajes no leídos}}",
|
|
"loadImages": "Cargar Imágenes Remotas",
|
|
"reply": "Responder",
|
|
"forward": "Reenviar",
|
|
"undoSend": "Deshacer Envío ({seconds}s restantes)"
|
|
},
|
|
"settings": {
|
|
"title": "Configuración de la Cuenta",
|
|
"security": "Seguridad y 2FA",
|
|
"appPasswords": "Contraseñas de Aplicación",
|
|
"sessions": "Sesiones Activas",
|
|
"mfaStatus": "Estado de Autenticación de Dos Factores",
|
|
"mfaEnabled": "2FA está Activo",
|
|
"mfaDisabled": "2FA está Desactivado",
|
|
"enableMfa": "Activar 2FA",
|
|
"generateAppPassword": "Generar Contraseña de Aplicación",
|
|
"recoveryCodesTitle": "Códigos de Recuperación",
|
|
"saveRecoveryCodes": "Guarde estos códigos de recuperación en un lugar seguro. No se volverán a mostrar.",
|
|
"language": "Idioma",
|
|
"signOut": "Cerrar sesión",
|
|
"langEn": "Inglés",
|
|
"langPtBR": "Portugués (Brasil)",
|
|
"langEs": "Español"
|
|
},
|
|
"admin": {
|
|
"dashboardTitle": "Panel del Sistema",
|
|
"domainsTitle": "Dominios y DNS (13 Registros)",
|
|
"mailboxesTitle": "Buzones y Cuentas",
|
|
"aliasesTitle": "Alias y Enrutamiento",
|
|
"queueTitle": "Cola de Entrega de Salida",
|
|
"dmarcTitle": "Análisis DMARC",
|
|
"securityTitle": "Seguridad y Registro de Auditoría",
|
|
"preflightTitle": "Diagnóstico Preflight",
|
|
"reconcileDns": "Reconciliar Registros DNS",
|
|
"dnsStatusVerified": "VERIFICADO",
|
|
"dnsStatusDrift": "DESVÍO DETECTADO",
|
|
"dnsStatusPartial": "PARCIAL",
|
|
"retryJob": "Reintentar Entrega",
|
|
"cancelJob": "Cancelar Trabajo",
|
|
"freezeDomain": "Congelar Destino"
|
|
},
|
|
"errors": {
|
|
"unauthorized": "Sesión expirada o no autorizada",
|
|
"forbidden": "Acceso prohibido para esta superficie de cuenta",
|
|
"serverError": "Ocurrió un error interno en el servidor"
|
|
}
|
|
}
|