feat(i18n): add pt-BR locale to PR #3202 structure

This commit is contained in:
Lekler 2026-01-28 05:02:16 -03:00
parent ae17ea9c1b
commit 770cc9a9cb
3 changed files with 271 additions and 1 deletions

View File

@ -1,14 +1,16 @@
export type Locale = "en" | "zh-CN";
export type Locale = "en" | "zh-CN" | "pt-BR";
export type MessageParams = Record<string, string | number | boolean | null | undefined>;
export type Messages = Record<string, string>;
import { en } from "./locales/en";
import { zhCN } from "./locales/zh-CN";
import { ptBR } from "./locales/pt-BR";
const BUNDLES: Record<Locale, Messages> = {
en,
"zh-CN": zhCN,
"pt-BR": ptBR,
};
let currentLocale: Locale = "en";
@ -20,6 +22,7 @@ export function normalizeLocale(input: string | null | undefined): Locale | null
if (!raw) return null;
const lower = raw.toLowerCase();
if (lower === "zh" || lower === "zh-cn" || lower.startsWith("zh-")) return "zh-CN";
if (lower === "pt" || lower === "pt-br" || lower.startsWith("pt-")) return "pt-BR";
if (lower === "en" || lower === "en-us" || lower.startsWith("en-")) return "en";
return null;
}

View File

@ -155,6 +155,8 @@ export const en: Messages = {
"settings.lang.en": "English",
"settings.lang.zhShort": "中",
"settings.lang.enShort": "EN",
"settings.lang.ptBR": "Português (Brasil)",
"settings.lang.ptShort": "PT",
"overview.gatewayAccess.title": "Gateway Access",
"overview.gatewayAccess.subtitle": "Where the dashboard connects and how it authenticates.",

265
ui/src/ui/locales/pt-BR.ts Normal file
View File

@ -0,0 +1,265 @@
import type { Messages } from "../i18n";
export const ptBR: Messages = {
"common.na": "n/a",
"common.loading": "Carregando…",
"common.refresh": "Atualizar",
"common.save": "Salvar",
"common.apply": "Aplicar",
"common.cancel": "Cancelar",
"common.close": "Fechar",
"common.search": "Buscar",
"common.filter": "Filtrar",
"common.export": "Exportar",
"common.copy": "Copiar",
"common.openInNewTab": "Abrir em nova aba",
"common.enabled": "Habilitado",
"common.disabled": "Desabilitado",
"common.on": "Ligado",
"common.off": "Desligado",
"common.start": "Iniciar",
"common.stop": "Parar",
"common.add": "Adicionar",
"common.remove": "Remover",
"common.delete": "Excluir",
"common.edit": "Editar",
"common.view": "Visualizar",
"common.useDefault": "Usar padrão",
"common.useDefaultWith": "Usar padrão (${value})",
"common.ok": "OK",
"common.yes": "Sim",
"common.no": "Não",
"common.agent": "Agente",
"common.inherit": "herdar",
"common.file": "Arquivo",
"common.none": "nenhum",
"common.never": "nunca",
"common.unknown": "desconhecido",
"common.enable": "Habilitar",
"common.disable": "Desabilitar",
"common.run": "Executar",
"common.export.visible": "visível",
"common.export.filtered": "filtrado",
"nav.chat": "Chat",
"nav.control": "Controle",
"nav.agent": "Agente",
"nav.settings": "Configurações",
"nav.resources": "Recursos",
"nav.docs": "Documentação",
"tab.overview.title": "Visão Geral",
"tab.channels.title": "Canais",
"tab.instances.title": "Instâncias",
"tab.sessions.title": "Sessões",
"tab.cron.title": "Tarefas Cron",
"tab.skills.title": "Skills",
"tab.nodes.title": "Nós",
"tab.chat.title": "Chat",
"tab.config.title": "Configuração",
"tab.debug.title": "Depuração",
"tab.logs.title": "Logs",
"tab.control.title": "Controle",
"tab.overview.subtitle": "Status do gateway e leitura rápida de saúde.",
"tab.channels.subtitle": "Gerenciar canais e configurações.",
"tab.instances.subtitle": "Beacons de presença de clientes e nós conectados.",
"tab.sessions.subtitle": "Inspecionar sessões ativas e ajustar padrões.",
"tab.cron.subtitle": "Agendar despertares e execuções recorrentes de agentes.",
"tab.skills.subtitle": "Gerenciar disponibilidade de skills e chaves de API.",
"tab.nodes.subtitle": "Dispositivos pareados, capacidades e exposição de comandos.",
"tab.chat.subtitle": "Sessão de chat direta com o gateway para intervenções rápidas.",
"tab.config.subtitle": "Editar ~/.clawdbot/clawdbot.json com segurança.",
"tab.debug.subtitle": "Snapshots do gateway, eventos e chamadas RPC manuais.",
"tab.logs.subtitle": "Acompanhamento em tempo real dos logs do gateway.",
"topbar.expandSidebar": "Expandir barra lateral",
"topbar.collapseSidebar": "Recolher barra lateral",
"topbar.gatewayDashboard": "Painel do Gateway",
"topbar.health": "Saúde",
"topbar.healthOk": "OK",
"topbar.healthOffline": "Offline",
"gateway.disconnected": "desconectado (${code}): ${reason}",
"gateway.noReason": "sem motivo",
"gateway.eventGap": "lacuna de eventos detectada (esperado seq ${expected}, recebido ${received}); atualização recomendada",
"gateway.reason.tokenMissing": "não autorizado: token do gateway faltando (abra uma URL de painel tokenizada ou cole o token nas configurações)",
"gateway.reason.tokenMismatch": "não autorizado: incompatibilidade de token do gateway (atualize o token nas configurações para corresponder ao gateway)",
"gateway.reason.tokenNotConfigured": "não autorizado: token do gateway não configurado no gateway (defina gateway.auth.token)",
"gateway.reason.passwordMissing": "não autorizado: senha do gateway faltando (cole a senha nas configurações ou use token)",
"gateway.reason.passwordMismatch": "não autorizado: senha incorreta (verifique a senha nas configurações)",
"gateway.reason.passwordNotConfigured": "não autorizado: senha do gateway não configurada no gateway (defina gateway.auth.password)",
"gateway.reason.tailscaleIdentityMissing": "não autorizado: identidade tailscale faltando (use autenticação Tailscale Serve ou token/senha)",
"gateway.reason.tailscaleProxyHeadersMissing": "não autorizado: cabeçalhos de proxy tailscale faltando (use Tailscale Serve ou token/senha)",
"gateway.reason.tailscaleIdentityCheckFailed": "não autorizado: verificação de identidade tailscale falhou (use autenticação Tailscale Serve ou token/senha)",
"gateway.reason.tailscaleIdentityMismatch": "não autorizado: incompatibilidade de identidade tailscale (use autenticação Tailscale Serve ou token/senha)",
"gateway.reason.unauthorized": "não autorizado",
"format.ago.justNow": "agora mesmo",
"format.ago.seconds": "${seconds}s atrás",
"format.ago.minutes": "${minutes}m atrás",
"format.ago.hours": "${hours}h atrás",
"format.ago.days": "${days}d atrás",
"format.duration.seconds": "${seconds}s",
"format.duration.minutes": "${minutes}m",
"format.duration.hours": "${hours}h",
"format.duration.days": "${days}d",
"chat.loading": "Carregando chat…",
"chat.disconnectedReason": "Desconectado do gateway.",
"chat.compacting": "Compactando contexto...",
"chat.compacted": "Contexto compactado",
"chat.attachmentPreview": "Prévia do anexo",
"chat.attachedImage": "Imagem anexada",
"chat.removeAttachment": "Remover anexo",
"chat.exitFocusMode": "Sair do modo foco",
"chat.queued": "Na fila (${count})",
"chat.removeQueuedMessage": "Remover mensagem da fila",
"chat.imageCount": "Imagem (${count})",
"chat.messageLabel": "Mensagem",
"chat.placeholder.connected": "Mensagem (↩ para enviar, Shift+↩ para quebra de linha, colar imagens)",
"chat.placeholder.connectedWithAttachments": "Adicione uma mensagem ou cole mais imagens...",
"chat.placeholder.disconnected": "Conecte-se ao gateway para iniciar o chat…",
"chat.stop": "Parar",
"chat.newSession": "Nova sessão",
"chat.queue": "Fila",
"chat.send": "Enviar",
"chat.showingLast": "Mostrando últimas ${limit} mensagens (${hidden} ocultas).",
"chat.tool.commandLabel": "Comando:",
"chat.tool.noOutput": "Sem saída — ferramenta concluída com sucesso.",
"chat.tool.completed": "Concluído",
"chat.role.you": "Você",
"chat.role.assistant": "Assistente",
"chat.role.user": "Usuário",
"chat.role.system": "Sistema",
"chat.role.tool": "Ferramenta",
"sidebar.toolOutput": "Saída da Ferramenta",
"sidebar.viewRawText": "Ver Texto Puro",
"sidebar.noContent": "Nenhum conteúdo disponível",
"execApproval.title": "Aprovação de execução necessária",
"execApproval.expiresIn": "expira em ${remaining}",
"execApproval.expired": "expirado",
"execApproval.pendingCount": "${count} pendentes",
"execApproval.meta.host": "Host",
"execApproval.meta.agent": "Agente",
"execApproval.meta.session": "Sessão",
"execApproval.meta.cwd": "CWD",
"execApproval.meta.resolved": "Resolvido",
"execApproval.meta.security": "Segurança",
"execApproval.meta.ask": "Perguntar",
"execApproval.allowOnce": "Permitir uma vez",
"execApproval.allowAlways": "Permitir sempre",
"execApproval.deny": "Negar",
"settings.language": "Idioma",
"settings.lang.zhCN": "中文",
"settings.lang.en": "English",
"settings.lang.zhShort": "中",
"settings.lang.enShort": "EN",
"settings.lang.ptBR": "Português (Brasil)",
"settings.lang.ptShort": "PT",
"overview.gatewayAccess.title": "Acesso ao Gateway",
"overview.gatewayAccess.subtitle": "Onde o painel se conecta e como se autentica.",
"overview.websocketUrl": "URL do WebSocket",
"overview.gatewayToken": "Token do Gateway",
"overview.passwordNotStored": "Senha (não armazenada)",
"overview.passwordPlaceholder": "senha do sistema ou compartilhada",
"overview.defaultSessionKey": "Chave de Sessão Padrão",
"overview.connect": "Conectar",
"overview.refresh": "Atualizar",
"overview.connectHint": "Clique em Conectar para aplicar as alterações.",
"overview.snapshot.title": "Snapshot",
"overview.snapshot.subtitle": "Informações mais recentes do handshake do gateway.",
"overview.status": "Status",
"overview.connected": "Conectado",
"overview.disconnected": "Desconectado",
"overview.uptime": "Tempo de Atividade",
"overview.tickInterval": "Intervalo de Tick",
"overview.lastChannelsRefresh": "Última Atualização de Canais",
"overview.channelsHint": "Use Canais para vincular WhatsApp, Telegram, Discord, Signal ou iMessage.",
"overview.instances": "Instâncias",
"overview.instancesHint": "Beacons de presença nos últimos 5 minutos.",
"overview.sessions": "Sessões",
"overview.sessionsHint": "Chaves de sessão recentes rastreadas pelo gateway.",
"overview.cron": "Cron",
"overview.enabled": "Habilitado",
"overview.disabled": "Desabilitado",
"overview.nextWake": "Próximo despertar ${when}",
"overview.notes.title": "Notas",
"overview.notes.subtitle": "Lembretes rápidos para configurações de controle remoto.",
"overview.notes.tailscaleServe.title": "Tailscale Serve",
"overview.notes.tailscaleServe.body": "Prefira o modo serve para manter o gateway em loopback com autenticação tailnet.",
"overview.notes.sessionHygiene.title": "Higiene de sessão",
"overview.notes.sessionHygiene.body": "Use /new ou sessions.patch para redefinir o contexto.",
"overview.notes.cronReminders.title": "Lembretes do Cron",
"overview.notes.cronReminders.body": "Use sessões isoladas para execuções recorrentes.",
"overview.auth.required": "Este gateway requer autenticação. Adicione um token ou senha e clique em Conectar.",
"overview.auth.tokenizedUrl": "URL tokenizada",
"overview.auth.setToken": "definir token",
"overview.auth.docsTitle": "Docs de auth da UI de Controle (abre nova aba)",
"overview.auth.docsLabel": "Docs: Auth UI de Controle",
"overview.auth.failed": "Falha na autenticação. Copie novamente uma URL tokenizada com ",
"overview.auth.failedAfterCommand": ", ou atualize o token, depois clique em Conectar.",
"overview.insecureHttp": "Esta página é HTTP, então o navegador bloqueia a identidade do dispositivo. Use HTTPS (Tailscale Serve) ou abra ",
"overview.insecureHttpAfterUrl": " no host do gateway.",
"overview.insecureHttpOption": "Se você precisa ficar em HTTP, defina ",
"overview.insecureHttpOptionAfter": " (apenas token).",
"overview.docs.opensNewTab": "Documentação (abre nova aba)",
"overview.docs.tailscaleServe": "Docs: Tailscale Serve",
"overview.docs.insecureHttp": "Docs: Insecure HTTP",
"chatControls.refreshHistory": "Atualizar histórico do chat",
"chatControls.disabledOnboarding": "Desabilitado durante onboarding",
"chatControls.toggleThinking": "Alternar saída de pensamento/trabalho do assistente",
"chatControls.toggleFocus": "Alternar modo foco (ocultar barra lateral + cabeçalho)",
"theme.label": "Tema",
"theme.system": "Sistema",
"theme.light": "Claro",
"theme.dark": "Escuro",
"logs.subtitle": "Logs de arquivo do gateway (JSONL).",
"logs.searchPlaceholder": "Buscar logs",
"logs.autoFollow": "Seguir automaticamente",
"logs.truncated": "Saída de log truncada; mostrando trecho mais recente.",
"logs.empty": "Nenhuma entrada de log.",
"sessions.subtitle": "Chaves de sessão ativas e substituições por sessão.",
"sessions.filters.activeWithin": "Ativo em (minutos)",
"sessions.filters.limit": "Limite",
"sessions.filters.includeGlobal": "Incluir global",
"sessions.filters.includeUnknown": "Incluir desconhecido",
"sessions.store": "Armazenamento: ${path}",
"sessions.table.key": "Chave",
"sessions.table.label": "Rótulo",
"sessions.table.kind": "Tipo",
"sessions.table.updated": "Atualizado",
"sessions.table.tokens": "Tokens",
"sessions.table.thinking": "Pensando",
"sessions.table.verbose": "Verbo",
"sessions.table.reasoning": "Raciocínio",
"sessions.table.actions": "Ações",
"sessions.empty": "Nenhuma sessão encontrada.",
"sessions.optional": "(opcional)",
"sessions.deleteConfirm": "Apagar sessão \"${key}\"?\n\nApaga a entrada da sessão e arquiva sua transcrição.",
"sessions.verbose.offExplicit": "desligado (explícito)",
"sessions.verbose.on": "ligado",
"sessions.level.off": "desligado",
"sessions.level.minimal": "mínimo",
"sessions.level.low": "baixo",
"sessions.level.medium": "médio",
"sessions.level.high": "alto",
"sessions.level.on": "ligado",
"sessions.level.stream": "stream",
"sessions.kind.global": "global",
"sessions.kind.agent": "agente",
"sessions.kind.isolated": "isolado",
};