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": "Adicionar apelido",
|
|
"aliasTarget": "Endereço de destino",
|
|
"aliasesTitle": "Apelidos",
|
|
"auditLog": "Trilha de auditoria",
|
|
"backToWebmail": "Voltar ao webmail",
|
|
"cancelJob": "Cancelar",
|
|
"certificateState": "Certificado",
|
|
"checksPassed": "{passed} de {total} aprovadas",
|
|
"createAccount": "Criar conta",
|
|
"createAlias": "Criar um apelido de roteamento",
|
|
"csvImportFailed": "A importação do CSV falhou",
|
|
"csvImported": "{count} caixas importadas.",
|
|
"csvIntro": "Cole o CSV para criar várias contas com as pastas da RFC 6154. Colunas: email, papel, cota_mb.",
|
|
"csvPreview": "Pré-visualizar",
|
|
"csvRun": "Executar importação",
|
|
"csvTitle": "Importar caixas em massa (CSV)",
|
|
"dashboardSubtitle": "Números ao vivo lidos do banco de dados.",
|
|
"dashboardTitle": "Visão geral",
|
|
"dkimAlgorithm": "Tipo de chave",
|
|
"dkimOverlap": "As duas chaves assinam as mensagens enviadas por {days} dias, para nada falhar enquanto o DNS propaga.",
|
|
"dkimPublishRecord": "Publique este registro no DNS:",
|
|
"dkimRotate": "Gerar uma nova chave",
|
|
"dkimSelector": "Seletor",
|
|
"dkimTitle": "Rotação de chave DKIM",
|
|
"dmarcSubtitle": "Detalhamento dos relatórios XML agregados que foram processados.",
|
|
"dmarcTitle": "Relatórios DMARC",
|
|
"dnsRecordsFor": "Registros DNS de {domain}",
|
|
"dnsStatusDrift": "Divergente",
|
|
"dnsStatusPartial": "Parcial",
|
|
"dnsStatusVerified": "Verificado",
|
|
"domainName": "Nome do domínio",
|
|
"domainsTitle": "Domínios",
|
|
"expiresInDays": "Expira em {days} dias",
|
|
"freezeDomain": "Congelar domínio",
|
|
"greylistScore": "Pontuação de greylist",
|
|
"headerScore": "Pontuação de marcação de cabeçalho",
|
|
"jobCancelled": "O trabalho {id} foi cancelado.",
|
|
"jobRetried": "O trabalho {id} foi recolocado na fila para nova tentativa.",
|
|
"lastChecked": "Última verificação: {when}",
|
|
"lastReload": "Última recarga",
|
|
"lockAccount": "Bloquear",
|
|
"mailHost": "Host de e-mail",
|
|
"mailboxCount": "{count} caixas de e-mail",
|
|
"mailboxesSubtitle": "Contas, apelidos, importação CSV e a política de segundo fator.",
|
|
"mailboxesTitle": "Caixas de e-mail",
|
|
"mfaAdmins": "Obrigatório para administradores",
|
|
"mfaEveryone": "Obrigatório para todos",
|
|
"mfaOptional": "Opcional",
|
|
"mfaPolicyIntro": "Escolha com que rigor este domínio exige um segundo fator.",
|
|
"mfaPolicyTitle": "Exigência de segundo fator",
|
|
"noCertificate": "Nenhum certificado carregado para este host.",
|
|
"noChecks": "Nenhuma verificação relatada.",
|
|
"noDomains": "Nenhum domínio foi cadastrado ainda.",
|
|
"notPublished": "Não publicado",
|
|
"onboardIntro": "Cria o domínio e os apelidos padrão da RFC 2142, apontados para o seu endereço.",
|
|
"onboardTitle": "Adicionar um domínio",
|
|
"openAdmin": "Console de administração",
|
|
"preflightTitle": "Verificações de prontidão",
|
|
"presentProxied": "Presente (com proxy)",
|
|
"queueEmpty": "A fila de saída está vazia.",
|
|
"queueSubtitle": "Inspecione a fila de saída, tente reenviar um trabalho ou cancele um.",
|
|
"queueTitle": "Fila de saída",
|
|
"quotaMb": "Cota (MB)",
|
|
"readinessIntro": "Verificações que o servidor relata sobre si mesmo antes de transportar mensagens em produção.",
|
|
"reconcileDns": "Reconciliar DNS",
|
|
"reconcileNotImplemented": "A verificação de registros DNS individuais ainda não foi implementada: isto registra a solicitação e relê o status armazenado, não consulta um resolvedor.",
|
|
"rejectScore": "Pontuação de rejeição",
|
|
"retryJob": "Tentar novamente",
|
|
"rspamdIntro": "Pontuações que acionam greylisting, marcação de cabeçalho e rejeição.",
|
|
"rspamdSaved": "Limites salvos.",
|
|
"saveThresholds": "Salvar limites",
|
|
"securitySubtitle": "Verificações de prontidão, estado do TLS, limites de spam e a trilha de auditoria.",
|
|
"securityTitle": "Segurança",
|
|
"tabAccounts": "Contas",
|
|
"tabAliases": "Apelidos",
|
|
"tabAudit": "Trilha de auditoria",
|
|
"tabCsv": "Importação em massa",
|
|
"tabReadiness": "Prontidão",
|
|
"tabRspamd": "Limites de spam",
|
|
"tabTls": "TLS",
|
|
"tlsMode": "Modo TLS",
|
|
"tlsTitle": "Certificado e transporte",
|
|
"traceNoResults": "Nenhum rastro encontrado para esse ID de fila.",
|
|
"tracePlaceholder": "ID da fila",
|
|
"traceResultFor": "Rastreamento de {id}",
|
|
"traceStep": "Etapa {n}",
|
|
"traceTitle": "Rastrear uma mensagem",
|
|
"unknownSni": "Requisições SNI desconhecidas",
|
|
"unlockAccount": "Desbloquear",
|
|
"verifyIntro": "Resolve cada registro esperado em servidores DNS públicos e relata um a um.",
|
|
"watcherHealthy": "Monitor de certificado"
|
|
},
|
|
"auth": {
|
|
"adminLoginTitle": "Console de administração",
|
|
"adminStepUpNote": "O console de administração pede o segundo fator novamente, mesmo você já estando conectado ao webmail.",
|
|
"authFailed": "Falha na autenticação",
|
|
"cantScanQr": "Não consegue escanear? Digite esta chave manualmente:",
|
|
"emailLabel": "Endereço de e-mail",
|
|
"enrolmentFailed": "Não foi possível iniciar a configuração do segundo fator",
|
|
"enrolmentIntro": "O console de administração exige um segundo fator. Configure um agora para continuar.",
|
|
"genericError": "Algo deu errado",
|
|
"invalidCredentials": "E-mail ou senha inválidos",
|
|
"mfaRequired": "Digite o código de seis dígitos do seu aplicativo autenticador.",
|
|
"orRecoveryCode": "Perdeu o celular? Um código de recuperação também funciona aqui.",
|
|
"passwordLabel": "Senha",
|
|
"qrCodeAlt": "Código QR para configurar a verificação em duas etapas",
|
|
"scanQr": "Escaneie este código com o Google Authenticator, Aegis, Authy ou 1Password.",
|
|
"signInButton": "Entrar",
|
|
"signOutOfAdmin": "Sair da administração",
|
|
"stepUpIntro": "Você já está autenticado, então basta o segundo fator. A senha não é pedida de novo.",
|
|
"stepUpSignedInAs": "Autenticado como {email}",
|
|
"stepUpTitle": "Abrir o console administrativo",
|
|
"totpCodeLabel": "Código de autenticação",
|
|
"userLoginTitle": "Entre na sua caixa de e-mail",
|
|
"verificationFailed": "Falha na verificação",
|
|
"verifyCodeButton": "Verificar código"
|
|
},
|
|
"common": {
|
|
"actions": "Ações",
|
|
"add": "Adicionar",
|
|
"adminPortal": "Administração",
|
|
"appName": "LambdaMail",
|
|
"back": "Voltar",
|
|
"cancel": "Cancelar",
|
|
"confirm": "Confirmar",
|
|
"continue": "Continuar",
|
|
"copied": "Copiado",
|
|
"copy": "Copiar",
|
|
"delete": "Excluir",
|
|
"loading": "Carregando...",
|
|
"logout": "Sair",
|
|
"never": "Nunca",
|
|
"none": "Nenhum",
|
|
"refresh": "Atualizar",
|
|
"retry": "Tentar novamente",
|
|
"save": "Salvar",
|
|
"search": "Buscar",
|
|
"status": "Status",
|
|
"unavailable": "Indisponível",
|
|
"userPortal": "Webmail"
|
|
},
|
|
"errors": {
|
|
"forbidden": "Você não tem acesso a isto",
|
|
"loadFailed": "Não foi possível carregar os dados",
|
|
"serverError": "Algo deu errado no servidor",
|
|
"unauthorized": "Entre novamente"
|
|
},
|
|
"mail": {
|
|
"addFiles": "Adicionar arquivos...",
|
|
"allMessages": "Todas",
|
|
"archive": "Arquivo",
|
|
"attachments": "Anexos ({count})",
|
|
"attachmentsFilter": "Com anexos",
|
|
"attachmentsUnsupported": "Anexos são listados apenas pelo nome; o envio de arquivos ainda não está implementado.",
|
|
"backToList": "Voltar para a lista de mensagens",
|
|
"bold": "Negrito",
|
|
"bulletList": "Lista com marcadores",
|
|
"compose": "Escrever",
|
|
"discard": "Descartar",
|
|
"draftSaveFailed": "Não foi possível salvar o rascunho",
|
|
"draftSaved": "Rascunho salvo automaticamente",
|
|
"draftSaving": "Salvando rascunho...",
|
|
"drafts": "Rascunhos",
|
|
"emptyBody": "Esta mensagem não tem corpo de texto.",
|
|
"forward": "Encaminhar",
|
|
"imagesEnabled": "Imagens carregadas",
|
|
"hideCcBcc": "- Ocultar Cc/Cco",
|
|
"inbox": "Caixa de entrada",
|
|
"insertLink": "Inserir link",
|
|
"insertUrl": "Digite a URL:",
|
|
"italic": "Itálico",
|
|
"junk": "Spam",
|
|
"loadImages": "Carregar imagens",
|
|
"markRead": "Marcar como lida",
|
|
"markUnread": "Marcar como não lida",
|
|
"messagesInFolder": "{count} mensagens",
|
|
"noMatches": "Nada corresponde a essa busca",
|
|
"noMessages": "Nenhuma mensagem",
|
|
"noSubject": "(Sem assunto)",
|
|
"numberedList": "Lista numerada",
|
|
"remoteContentBlocked": "As imagens remotas foram bloqueadas para que esta mensagem não possa rastrear você.",
|
|
"reply": "Responder",
|
|
"searchMatches": "{count} encontradas",
|
|
"searchPlaceholder": "Buscar (from:, subject:)...",
|
|
"selectAMessage": "Selecione uma mensagem para ler",
|
|
"sendMessage": "Enviar mensagem",
|
|
"sending": "Enviando...",
|
|
"sent": "Enviados",
|
|
"showCcBcc": "+ Adicionar Cc/Cco",
|
|
"strikethrough": "Tachado",
|
|
"trash": "Lixeira",
|
|
"underline": "Sublinhado",
|
|
"undoSend": "Enviando em {seconds}s",
|
|
"undoSendAction": "Desfazer",
|
|
"unreadCount": "{count} não lidas",
|
|
"unreadFilter": "Não lidas"
|
|
},
|
|
"settings": {
|
|
"actionDiscard": "Descartar",
|
|
"actionFlag": "Marcar mensagem",
|
|
"actionMove": "Mover para o Arquivo",
|
|
"addRule": "Adicionar regra",
|
|
"appPasswordPlaceholder": "Thunderbird / Outlook Mobile",
|
|
"appPasswords": "Senhas de aplicativo",
|
|
"autoReplySaveFailed": "Não foi possível salvar a resposta automática",
|
|
"enableMfa": "Ativar verificação em duas etapas",
|
|
"fieldFrom": "De",
|
|
"fieldHeader": "Cabeçalho",
|
|
"fieldSubject": "Assunto",
|
|
"generateAppPassword": "Gerar",
|
|
"langEn": "English",
|
|
"langEs": "Español",
|
|
"langPtBR": "Português (Brasil)",
|
|
"language": "Idioma",
|
|
"matchContains": "contém",
|
|
"matchEquals": "é exatamente",
|
|
"matchRegex": "corresponde à regex",
|
|
"mfaDisabled": "Desativada",
|
|
"mfaEnabled": "Ativada",
|
|
"mfaStatus": "Status da verificação em duas etapas",
|
|
"recoveryCodesTitle": "Códigos de recuperação",
|
|
"ruleIf": "SE",
|
|
"ruleThen": "ENTÃO",
|
|
"saveAutoReply": "Salvar resposta automática",
|
|
"saveRecoveryCodes": "Guarde-os em local seguro. Cada um funciona uma única vez e eles só aparecem agora.",
|
|
"security": "Segurança",
|
|
"sessions": "Sessões",
|
|
"settingsSaved": "Configurações salvas.",
|
|
"sieveIntro": "Regras que organizam as mensagens recebidas automaticamente.",
|
|
"sieveTitle": "Filtros (Sieve)",
|
|
"signOut": "Sair",
|
|
"signatureIntro": "Anexada automaticamente às mensagens que você escreve.",
|
|
"signaturePlaceholder": "Atenciosamente,\nSeu nome\nSeu cargo",
|
|
"signatureSaveFailed": "Não foi possível salvar a assinatura",
|
|
"signatureSaved": "Assinatura salva.",
|
|
"signatureTitle": "Assinatura de e-mail",
|
|
"sixDigitCode": "Código de seis dígitos",
|
|
"startOverMfa": "Perdeu o registro? Recomece com uma nova chave",
|
|
"subtitle": "Verificação em duas etapas, filtros, resposta automática e sua assinatura.",
|
|
"title": "Configurações",
|
|
"twoFactorIntro": "Proteja sua conta com o Google Authenticator, Aegis, Authy ou 1Password.",
|
|
"vacationBodyLabel": "Mensagem da resposta",
|
|
"vacationDefaultBody": "Obrigado pela sua mensagem. Estou ausente no momento e responderei assim que retornar.",
|
|
"vacationDefaultSubject": "Fora do escritório",
|
|
"vacationIntro": "Responde automaticamente às mensagens recebidas enquanto você estiver ausente.",
|
|
"vacationSubjectLabel": "Assunto da resposta",
|
|
"vacationTitle": "Resposta automática de ausência",
|
|
"valuePlaceholder": "Valor a corresponder..."
|
|
},
|
|
"ui": {
|
|
"accountLocked": "Bloqueada",
|
|
"accountStatus": "Status da conta",
|
|
"actions": "Ações",
|
|
"active": "Ativo",
|
|
"activeSessions": "Sessões ativas",
|
|
"actor": "Autor",
|
|
"actualRecord": "Valor atual",
|
|
"allChecksPassed": "Todas as verificações passaram",
|
|
"appPasswordGenerated": "Senha de aplicativo gerada",
|
|
"appPasswordsSection": "Senhas de aplicativo",
|
|
"attempts": "Tentativas",
|
|
"bounceRate": "Taxa de devolução",
|
|
"ccRecipients": "Cc",
|
|
"changePassword": "Alterar senha",
|
|
"clientIp": "IP do cliente",
|
|
"copyPasswordNow": "Copie agora. Ela não será exibida novamente.",
|
|
"coreInfra": "Serviços principais",
|
|
"currentPassword": "Senha atual",
|
|
"currentSession": "Este dispositivo",
|
|
"daneVerified": "DANE verificado",
|
|
"destination": "Destino",
|
|
"diskUsed": "Armazenamento usado",
|
|
"dkimAlignment": "Alinhamento DKIM",
|
|
"dkimResult": "DKIM",
|
|
"dmarcEnforcement": "Política DMARC",
|
|
"domainVerification": "Verificação de domínio",
|
|
"domainsVerified": "Domínios verificados",
|
|
"emailAddress": "Endereço de e-mail",
|
|
"eventAction": "Ação",
|
|
"expectedValue": "Valor esperado",
|
|
"healthy": "Saudável",
|
|
"imapEngine": "Serviço IMAP",
|
|
"inboundVolume": "Recebidas (24h)",
|
|
"jobId": "Trabalho",
|
|
"lastError": "Último erro",
|
|
"liveMetrics": "Métricas ao vivo",
|
|
"localDisk": "Disco local",
|
|
"mailboxesActive": "Caixas ativas",
|
|
"messageBody": "Mensagem",
|
|
"messageVolume": "Mensagens",
|
|
"mfaActive": "TOTP ativo",
|
|
"mfaNone": "Sem segundo fator",
|
|
"newPassword": "Nova senha",
|
|
"noAppPasswords": "Nenhuma senha de aplicativo ainda.",
|
|
"noData": "Ainda sem dados",
|
|
"online": "Online",
|
|
"outboundDelivered": "Enviadas (24h)",
|
|
"passwordChanged": "Senha alterada.",
|
|
"postgresRunner": "Fila baseada em Postgres",
|
|
"preflightTitle": "Prontidão",
|
|
"provisionMailbox": "Criar caixa de e-mail",
|
|
"queueDepth": "Tamanho da fila",
|
|
"recipient": "Destinatário",
|
|
"recordName": "Registro",
|
|
"reportingOrg": "Organização que reportou",
|
|
"role": "Papel",
|
|
"scanners": "Análise de spam e vírus",
|
|
"sender": "Remetente",
|
|
"signOutOthers": "Sair dos outros dispositivos",
|
|
"smtpListener": "Serviço SMTP",
|
|
"sourceIp": "IP de origem",
|
|
"spfRatio": "Taxa de aprovação SPF",
|
|
"spfResult": "SPF",
|
|
"storageQuota": "Cota de armazenamento",
|
|
"subject": "Assunto",
|
|
"targetObject": "Alvo",
|
|
"timestamp": "Horário",
|
|
"toRecipients": "Para",
|
|
"toggleMenu": "Alternar menu",
|
|
"totalEvaluated": "Mensagens avaliadas",
|
|
"twoFactorSection": "Verificação em duas etapas",
|
|
"watching": "Monitorando"
|
|
}
|
|
}
|