diff --git a/web/frontend/src/components/app-header.tsx b/web/frontend/src/components/app-header.tsx
index 465d218be..700cc21e0 100644
--- a/web/frontend/src/components/app-header.tsx
+++ b/web/frontend/src/components/app-header.tsx
@@ -288,6 +288,9 @@ export function AppHeader() {
i18n.changeLanguage("en")}>
English
+ i18n.changeLanguage("pt-BR")}>
+ Português (Brasil)
+
i18n.changeLanguage("zh")}>
简体中文
diff --git a/web/frontend/src/i18n/index.ts b/web/frontend/src/i18n/index.ts
index bdc1fe917..4da7b3f0d 100644
--- a/web/frontend/src/i18n/index.ts
+++ b/web/frontend/src/i18n/index.ts
@@ -1,5 +1,6 @@
import dayjs from "dayjs"
import "dayjs/locale/en"
+import "dayjs/locale/pt-br"
import "dayjs/locale/zh-cn"
import localizedFormat from "dayjs/plugin/localizedFormat"
import relativeTime from "dayjs/plugin/relativeTime"
@@ -8,6 +9,7 @@ import LanguageDetector from "i18next-browser-languagedetector"
import { initReactI18next } from "react-i18next"
import en from "./locales/en.json"
+import ptBr from "./locales/pt-br.json"
import zh from "./locales/zh.json"
dayjs.extend(relativeTime)
@@ -26,6 +28,9 @@ i18n
en: {
translation: en,
},
+ "pt-BR": {
+ translation: ptBr,
+ },
zh: {
translation: zh,
},
@@ -41,6 +46,8 @@ i18n
i18n.on("languageChanged", (lng) => {
if (lng.startsWith("zh")) {
dayjs.locale("zh-cn")
+ } else if (lng.startsWith("pt")) {
+ dayjs.locale("pt-br")
} else {
dayjs.locale("en")
}
diff --git a/web/frontend/src/i18n/locales/pt-br.json b/web/frontend/src/i18n/locales/pt-br.json
new file mode 100644
index 000000000..eb9f5e155
--- /dev/null
+++ b/web/frontend/src/i18n/locales/pt-br.json
@@ -0,0 +1,534 @@
+{
+ "navigation": {
+ "chat": "Chat",
+ "model_group": "Modelos",
+ "models": "Modelos",
+ "credentials": "Credenciais",
+ "agent_group": "Agente",
+ "skills": "Skills",
+ "tools": "Ferramentas",
+ "services": "Serviços",
+ "channels_group": "Canais",
+ "show_more_channels": "Mais",
+ "show_less_channels": "Menos",
+ "config": "Configuração",
+ "logs": "Logs"
+ },
+ "chat": {
+ "welcome": "Como posso te ajudar hoje?",
+ "welcomeDesc": "Pergunte sobre clima, configurações ou qualquer outra tarefa. Estou aqui para ajudar.",
+ "placeholder": "Digite uma mensagem...\nEnter para enviar, Shift + Enter para nova linha",
+ "newChat": "Novo Chat",
+ "notConnected": "O Gateway não está rodando. Inicie-o para conversar.",
+ "thinking": {
+ "step1": "Pensando...",
+ "step2": "Analisando sua solicitação...",
+ "step3": "Preparando resposta...",
+ "step4": "Quase lá..."
+ },
+ "history": "Histórico",
+ "noHistory": "Nenhum histórico de chat ainda",
+ "historyLoadFailed": "Falha ao carregar histórico de chat",
+ "historyOpenFailed": "Falha ao abrir este histórico de chat",
+ "loadingMore": "Carregando mais...",
+ "deleteSession": "Excluir sessão",
+ "messagesCount": "{{count}} mensagens",
+ "noModel": "Selecionar modelo",
+ "empty": {
+ "noConfiguredModel": "Nenhum Modelo Configurado",
+ "noConfiguredModelDescription": "Você precisa configurar pelo menos um modelo de IA com uma API Key antes de iniciar o chat.",
+ "goToModels": "Ir para Modelos",
+ "noSelectedModel": "Nenhum Modelo Selecionado",
+ "noSelectedModelDescription": "Você tem modelos configurados, mas nenhum está definido como padrão. Selecione um modelo antes de iniciar o chat.",
+ "notRunning": "Gateway Não Está Rodando",
+ "notRunningDescription": "Inicie o serviço de gateway para começar a conversar. Use o botão Iniciar Gateway na barra superior."
+ },
+ "modelGroup": {
+ "apikey": "API Key",
+ "oauth": "OAuth",
+ "local": "Local"
+ }
+ },
+ "header": {
+ "gateway": {
+ "stopDialog": {
+ "title": "Parar o Serviço de Gateway?",
+ "description": "Tem certeza de que deseja parar o gateway? Isso desconectará suas sessões de chat ativas e interromperá a inferência.",
+ "confirm": "Parar Gateway"
+ },
+ "action": {
+ "start": "Iniciar Gateway",
+ "stop": "Parar Gateway",
+ "restart": "Reiniciar Gateway"
+ },
+ "status": {
+ "starting": "Iniciando Gateway...",
+ "restarting": "Reiniciando Gateway...",
+ "stopping": "Parando Gateway..."
+ },
+ "restartRequired": "Alterações no modelo requerem reiniciar o gateway para ter efeito."
+ }
+ },
+ "common": {
+ "cancel": "Cancelar",
+ "save": "Salvar",
+ "saving": "Salvando...",
+ "reset": "Redefinir",
+ "confirm": "Confirmar"
+ },
+ "labels": {
+ "loading": "Carregando..."
+ },
+ "credentials": {
+ "description": "Gerencie credenciais OAuth e baseadas em token para provedores compatíveis.",
+ "loading": "Carregando credenciais...",
+ "providers": {
+ "openai": {
+ "description": "Suporta OAuth pelo navegador, código de dispositivo e login por token."
+ },
+ "anthropic": {
+ "description": "Usa login por token para acesso ao Claude."
+ },
+ "antigravity": {
+ "description": "Usa OAuth pelo navegador para Google Cloud Code Assist."
+ }
+ },
+ "status": {
+ "connected": "Conectado",
+ "needsRefresh": "Precisa atualizar",
+ "expired": "Expirado",
+ "notLoggedIn": "Não conectado"
+ },
+ "actions": {
+ "browser": "OAuth pelo Navegador",
+ "deviceCode": "Código do Dispositivo",
+ "stopLoading": "Parar Carregamento",
+ "saveToken": "Salvar",
+ "logout": "Sair"
+ },
+ "logoutDialog": {
+ "title": "Sair do provedor?",
+ "description": "Isso removerá sua credencial salva para {{provider}}."
+ },
+ "fields": {
+ "openaiToken": "Token OpenAI",
+ "anthropicToken": "Token Anthropic"
+ },
+ "labels": {
+ "account": "Conta",
+ "email": "E-mail",
+ "project": "Projeto"
+ },
+ "errors": {
+ "loadFailed": "Falha ao carregar credenciais",
+ "flowFailed": "Falha ao verificar fluxo de autenticação",
+ "loginFailed": "Falha no login",
+ "logoutFailed": "Falha ao sair",
+ "invalidBrowserResponse": "Resposta inválida do login pelo navegador",
+ "invalidDeviceResponse": "Resposta inválida do código de dispositivo",
+ "popupBlocked": "Não foi possível abrir uma nova aba. Permita popups e tente novamente."
+ },
+ "flow": {
+ "current": "Status atual de autenticação",
+ "pending": "Aguardando autorização...",
+ "success": "Autenticação bem-sucedida",
+ "error": "Falha na autenticação",
+ "expired": "Sessão de autenticação expirada"
+ },
+ "device": {
+ "title": "Login por Dispositivo OpenAI",
+ "description": "Abra a página de verificação e insira o código abaixo. Esta página será atualizada automaticamente.",
+ "code": "Código do Usuário",
+ "url": "URL de Verificação",
+ "polling": "Verificando status de login...",
+ "open": "Abrir Página de Verificação"
+ }
+ },
+ "models": {
+ "description": "Configure API Keys para provedores de IA. Apenas modelos configurados estarão disponíveis para chat.",
+ "loadError": "Falha ao carregar modelos",
+ "noDefaultHintPrefix": "Nenhum modelo padrão definido. Clique em",
+ "noDefaultHintSuffix": "para definir um.",
+ "status": {
+ "configured": "Configurado",
+ "unconfigured": "Não configurado"
+ },
+ "badge": {
+ "default": "Padrão",
+ "virtual": "Virtual"
+ },
+ "action": {
+ "edit": "Editar API Key",
+ "setDefault": "Definir como padrão",
+ "delete": "Excluir modelo"
+ },
+ "defaultOnSave": {
+ "label": "Modelo Padrão",
+ "description": "Definir automaticamente este modelo como padrão após salvar."
+ },
+ "add": {
+ "button": "Adicionar Modelo",
+ "title": "Adicionar Modelo Personalizado",
+ "description": "Adicione um endpoint de modelo compatível com OpenAI ou nativo.",
+ "modelName": "Nome do Modelo",
+ "modelNamePlaceholder": "ex: meu-gpt4",
+ "modelNameHint": "Um nome curto usado para identificar este modelo nas conversas.",
+ "modelId": "Identificador do Modelo",
+ "modelIdPlaceholder": "ex: openai/gpt-4o",
+ "modelIdHint": "Formato: protocolo/id-modelo. Suportados: openai, anthropic, gemini, groq, …",
+ "errorRequired": "Este campo é obrigatório.",
+ "errorDuplicateModelName": "Este nome já existe. Use um nome diferente.",
+ "saveError": "Falha ao adicionar modelo",
+ "confirm": "Adicionar Modelo"
+ },
+ "delete": {
+ "title": "Excluir Modelo?",
+ "description": "\"{{name}}\" será removido permanentemente da sua lista de modelos. Isso não pode ser desfeito.",
+ "confirm": "Excluir"
+ },
+ "advanced": {
+ "toggle": "Opções avançadas"
+ },
+ "field": {
+ "apiBase": "URL Base da API",
+ "apiKey": "API Key",
+ "apiKeyPlaceholder": "Insira sua API Key",
+ "apiKeyPlaceholderSet": "Deixe em branco para manter a chave atual",
+ "proxy": "Proxy HTTP",
+ "proxyHint": "Opcional. ex: http://127.0.0.1:7890",
+ "authMethod": "Método de Autenticação",
+ "authMethodHint": "Método de autenticação: oauth, token. Deixe em branco para autenticação por API Key.",
+ "connectMode": "Modo de Conexão",
+ "connectModeHint": "Modo de conexão para provedores via CLI: stdio ou grpc.",
+ "workspace": "Diretório de Trabalho",
+ "workspaceHint": "Diretório de trabalho para provedores via CLI (ex: GitHub Copilot).",
+ "requestTimeout": "Timeout da Requisição (s)",
+ "requestTimeoutHint": "Máximo de segundos para aguardar uma resposta. 0 = usar padrão.",
+ "rpm": "Limite de Taxa (RPM)",
+ "rpmHint": "Máximo de requisições por minuto. 0 = sem limite.",
+ "thinkingLevel": "Nível de Raciocínio",
+ "thinkingLevelHint": "Orçamento de raciocínio estendido: off, low, medium, high, xhigh, adaptive.",
+ "maxTokensField": "Campo de Max Tokens",
+ "maxTokensFieldHint": "Sobrescrever o nome do campo de max tokens na requisição, ex: max_completion_tokens.",
+ "extraBody": "Corpo Extra",
+ "extraBodyHint": "Campos JSON adicionais para injetar no corpo da requisição, ex: {\"reasoning_split\": true}."
+ },
+ "edit": {
+ "title": "Configurar {{name}}",
+ "apiKeyHint": "Uma chave já está definida. Deixe em branco para mantê-la.",
+ "oauthNote": "Este provedor usa OAuth — não é necessária API Key.",
+ "saveError": "Falha ao salvar"
+ }
+ },
+ "channels": {
+ "loadError": "Falha ao carregar canais",
+ "edit": "Configurar {{name}}",
+ "status": {
+ "configured": "Configurado"
+ },
+ "name": {
+ "telegram": "Telegram",
+ "discord": "Discord",
+ "slack": "Slack",
+ "feishu": "Feishu",
+ "dingtalk": "DingTalk",
+ "line": "LINE",
+ "qq": "QQ",
+ "onebot": "OneBot",
+ "wecom": "WeCom",
+ "whatsapp": "WhatsApp",
+ "whatsapp_native": "WhatsApp Nativo",
+ "pico": "Web",
+ "maixcam": "MaixCam",
+ "matrix": "Matrix",
+ "irc": "IRC",
+ "weixin": "WeChat"
+ },
+ "weixin": {
+ "warningTitle": "Fase de testes, use com cautela",
+ "warningDesc": "O canal do WeChat ainda é experimental e pode ter risco de suspensão de conta. Use apenas se você entende e aceita o risco.",
+ "bindTitle": "Vinculação de Conta WeChat",
+ "bindDesc": "Escaneie o QR code com o WeChat para vincular sua conta pessoal.",
+ "bind": "Vincular WeChat",
+ "rebind": "Revincular",
+ "bound": "WeChat Vinculado",
+ "notBound": "Conta WeChat ainda não vinculada.",
+ "generating": "Gerando QR code...",
+ "scanHint": "Abra o WeChat e escaneie o QR code",
+ "scanned": "Escaneado — confirme no WeChat",
+ "expired": "QR code expirado",
+ "retry": "Tentar Novamente",
+ "refresh": "Atualizar QR",
+ "errorGeneric": "Ocorreu um erro. Tente novamente."
+ },
+ "wecom": {
+ "bindTitle": "Vinculação WeCom",
+ "bindDesc": "Escaneie o QR code com o WeCom para vincular seu AI Bot.",
+ "enableDesc": "Após vincular, você pode habilitar ou desabilitar o canal aqui.",
+ "enableBindFirst": "Vincule o bot primeiro, depois habilite o canal.",
+ "bind": "Vincular WeCom",
+ "rebind": "Revincular",
+ "bound": "WeCom Vinculado",
+ "notBound": "AI Bot do WeCom ainda não vinculado.",
+ "generating": "Gerando QR code...",
+ "scanHint": "Abra o WeCom e escaneie o QR code",
+ "scanned": "Escaneado, confirme no WeCom",
+ "expired": "QR code expirado",
+ "retry": "Tentar Novamente",
+ "refresh": "Atualizar QR",
+ "errorGeneric": "Ocorreu um erro. Tente novamente."
+ },
+ "field": {
+ "token": "Token do Bot",
+ "tokenPlaceholder": "Insira o token do bot",
+ "botToken": "Token do Bot",
+ "appToken": "Token do App",
+ "appId": "ID do App",
+ "appSecret": "Segredo do App",
+ "verificationToken": "Token de Verificação",
+ "encryptKey": "Chave de Criptografia",
+ "baseUrl": "URL Base da API",
+ "proxy": "Proxy HTTP",
+ "mentionOnly": "Apenas Menções",
+ "typingEnabled": "Indicador de Digitação",
+ "placeholderEnabled": "Mensagem Provisória",
+ "placeholderText": "Texto Provisório",
+ "groupTriggerMentionOnly": "Apenas Menções em Grupo",
+ "groupTriggerPrefixes": "Prefixos de Ativação em Grupo",
+ "isLark": "Lark (Internacional)",
+ "allowFrom": "Permitir De",
+ "allowFromPlaceholder": "ex: 123456, 789012",
+ "allowOrigins": "Origens Permitidas",
+ "allowOriginsPlaceholder": "ex: https://exemplo.com, http://localhost:5173",
+ "secretPlaceholder": "Insira o segredo",
+ "secretHintSet": "Um valor já está definido. Deixe em branco para mantê-lo."
+ },
+ "page": {
+ "notFound": "Canal \"{{name}}\" não é suportado.",
+ "saveSuccess": "Configuração do canal salva.",
+ "saveError": "Falha ao salvar configuração do canal",
+ "enabled": "habilitado",
+ "docLink": "Documentação",
+ "enableLabel": "Habilitar canal",
+ "restartRequiredTitle": "Reinicialização do gateway necessária",
+ "restartRequiredDesc": "A configuração mais recente de {{name}} foi salva. Reinicie o gateway para que ela entre em vigor."
+ },
+ "form": {
+ "desc": {
+ "token": "Token de acesso do bot usado para conectar à API da plataforma.",
+ "botToken": "Token do bot usado para enviar e receber mensagens.",
+ "appToken": "Token do app usado para conexões em Socket Mode.",
+ "appId": "ID único do aplicativo usado para autenticação.",
+ "appSecret": "Segredo do aplicativo usado para assinatura e autenticação.",
+ "verificationToken": "Token de verificação para callbacks de eventos.",
+ "encryptKey": "Chave de criptografia usada para descriptografar payloads de callback.",
+ "baseUrl": "URL base da API da plataforma. O endpoint oficial é usado por padrão.",
+ "proxy": "Endereço de proxy HTTP para acesso à rede externa.",
+ "mentionOnly": "Responder apenas quando o bot for explicitamente mencionado em chats de grupo.",
+ "typingEnabled": "Exibir status de digitação enquanto o assistente está gerando uma resposta.",
+ "placeholderEnabled": "Habilitar mensagens provisórias temporárias antes da resposta final ser enviada.",
+ "groupTriggerMentionOnly": "Em chats de grupo, responder apenas quando o bot for mencionado.",
+ "groupTriggerPrefixes": "Prefixos personalizados de ativação em grupo, separados por vírgulas.",
+ "isLark": "Usar domínio internacional Lark (open.larksuite.com) em vez do domínio Feishu (open.feishu.cn).",
+ "allowFrom": "IDs de usuários ou grupos permitidos, separados por vírgulas.",
+ "allowOrigins": "Domínios de origem permitidos, separados por vírgulas.",
+ "wsUrl": "URL do serviço WebSocket.",
+ "reconnectInterval": "Intervalo de reconexão após desconexão (segundos).",
+ "bridgeUrl": "URL do serviço de bridge.",
+ "sessionStorePath": "Caminho local para armazenamento de sessão.",
+ "useNative": "Usar modo de cliente nativo.",
+ "host": "Endereço do host do serviço.",
+ "port": "Porta do serviço.",
+ "homeserver": "URL do homeserver Matrix.",
+ "userId": "ID de usuário da conta.",
+ "deviceId": "ID do dispositivo.",
+ "joinOnInvite": "Entrar automaticamente em salas quando convidado.",
+ "clientId": "Client ID usado para autenticação na plataforma.",
+ "corpId": "Corp ID da empresa.",
+ "agentId": "Agent ID do aplicativo empresarial.",
+ "webhookUrl": "URL completa do webhook.",
+ "webhookHost": "Host de escuta do webhook.",
+ "webhookPort": "Porta de escuta do webhook.",
+ "webhookPath": "Caminho da rota do webhook.",
+ "replyTimeout": "Timeout de resposta em segundos.",
+ "maxSteps": "Número máximo de etapas de processamento.",
+ "welcomeMessage": "Conteúdo da mensagem de boas-vindas para novas sessões.",
+ "allowTokenQuery": "Permitir token em parâmetros de query da URL.",
+ "pingInterval": "Intervalo de heartbeat da conexão em segundos.",
+ "readTimeout": "Timeout de leitura em segundos.",
+ "writeTimeout": "Timeout de escrita em segundos.",
+ "maxConnections": "Número máximo de conexões simultâneas.",
+ "server": "Endereço do servidor IRC.",
+ "tls": "Habilitar TLS.",
+ "nick": "Apelido do bot.",
+ "user": "Nome de usuário IRC.",
+ "realName": "Nome real exibido.",
+ "channels": "Canais IRC para entrar.",
+ "requestCaps": "Lista de capabilities IRC solicitadas na conexão.",
+ "maxBase64FileSizeMiB": "Tamanho máximo em MiB para converter arquivos locais em base64 antes do upload. 0 significa ilimitado. Aplica-se apenas a arquivos locais, não uploads por URL.",
+ "genericField": "Usado para configurar {{field}}."
+ }
+ },
+ "validation": {
+ "requiredField": "Este campo é obrigatório."
+ }
+ },
+ "pages": {
+ "agent": {
+ "load_error": "Falha ao carregar informações de suporte do agente.",
+ "skills": {
+ "description": "Skills são carregadas do workspace, diretório home global do PicoClaw e diretórios internos.",
+ "empty": "Nenhuma skill disponível no momento.",
+ "import": "Importar Skill",
+ "import_success": "Skill importada.",
+ "import_error": "Falha ao importar skill.",
+ "view": "Visualizar",
+ "delete": "Excluir",
+ "delete_title": "Excluir Skill?",
+ "delete_description": "\"{{name}}\" será removida das skills do workspace.",
+ "delete_confirm": "Excluir",
+ "delete_success": "Skill excluída.",
+ "delete_error": "Falha ao excluir skill.",
+ "viewer_title": "Conteúdo da Skill",
+ "viewer_description": "Leia o conteúdo atual efetivo do SKILL.md aqui.",
+ "loading_detail": "Carregando conteúdo da skill...",
+ "load_detail_error": "Falha ao carregar conteúdo da skill.",
+ "path": "Caminho da Skill",
+ "no_description": "Sem descrição fornecida."
+ },
+ "tools": {
+ "description": "Esta visualização mostra se cada ferramenta do agente está habilitada, desabilitada ou bloqueada por um pré-requisito ausente.",
+ "empty": "Nenhuma ferramenta disponível.",
+ "enable": "Habilitar",
+ "disable": "Desabilitar",
+ "enable_success": "Ferramenta habilitada.",
+ "disable_success": "Ferramenta desabilitada.",
+ "toggle_error": "Falha ao atualizar estado da ferramenta.",
+ "config_key": "Controlado por tools.{{key}}",
+ "status": {
+ "enabled": "Habilitado",
+ "disabled": "Desabilitado",
+ "blocked": "Bloqueado"
+ },
+ "categories": {
+ "automation": "Automação",
+ "filesystem": "Sistema de Arquivos",
+ "web": "Web",
+ "communication": "Comunicação",
+ "skills": "Skills",
+ "agents": "Agentes",
+ "hardware": "Hardware",
+ "discovery": "Descoberta"
+ },
+ "reasons": {
+ "requires_linux": "Esta ferramenta funciona apenas em hosts Linux com os arquivos de dispositivo necessários expostos.",
+ "requires_skills": "Habilite `tools.skills` antes que esta ferramenta de registro de skills possa ser usada.",
+ "requires_subagent": "Habilite `tools.subagent` antes que a ferramenta spawn possa delegar trabalho.",
+ "requires_mcp_discovery": "Habilite `tools.mcp.discovery` antes que as ferramentas de descoberta MCP fiquem disponíveis."
+ }
+ }
+ },
+ "config": {
+ "load_error": "Falha ao carregar configuração. Atualize a página e tente novamente.",
+ "workspace": "Diretório de Trabalho",
+ "workspace_hint": "Diretório base para operações de arquivo do agente.",
+ "restrict_workspace": "Restringir ao Workspace",
+ "restrict_workspace_hint": "Permitir apenas operações de arquivo dentro do workspace.",
+ "split_on_marker": "Modo Conversacional",
+ "split_on_marker_hint": "Dividir mensagens longas em curtas como uma conversa humana real.",
+ "tool_feedback_enabled": "Feedback de Ferramentas",
+ "tool_feedback_enabled_hint": "Enviar uma prévia curta da chamada de ferramenta no chat atual antes de cada execução.",
+ "tool_feedback_max_args_length": "Tamanho da Prévia de Argumentos",
+ "tool_feedback_max_args_length_hint": "Número máximo de caracteres de argumentos mostrados em cada mensagem de feedback. 0 para usar o padrão.",
+ "exec_enabled": "Permitir Comandos",
+ "exec_enabled_hint": "Habilitar ou desabilitar execução de comandos. Quando desabilitado, nenhuma solicitação de comando será executada.",
+ "allow_remote": "Permitir Comandos Remotos",
+ "allow_remote_hint": "Quando habilitado, sessões remotas também podem executar comandos. Quando desabilitado, a execução fica limitada a contextos locais seguros.",
+ "enable_deny_patterns": "Habilitar Lista Negra",
+ "enable_deny_patterns_hint": "Quando habilitado, bloqueia comandos que correspondam aos padrões perigosos internos e à lista negra personalizada abaixo.",
+ "exec_timeout_seconds": "Timeout de Comando (segundos)",
+ "exec_timeout_seconds_hint": "Tempo máximo de execução para comandos. 0 para usar o timeout padrão.",
+ "custom_deny_patterns": "Lista Negra de Comandos",
+ "custom_deny_patterns_hint": "Adicione regras extras de bloqueio de comandos, uma expressão regular por linha.",
+ "custom_allow_patterns": "Lista Branca de Comandos",
+ "custom_allow_patterns_hint": "Adicione regras extras de permissão de comandos, uma expressão regular por linha. Comandos correspondentes pulam a lista negra, mas outros limites de segurança ainda se aplicam.",
+ "custom_patterns_placeholder": "^rm\\s+-rf\\b\n^git\\s+push\\b",
+ "pattern_detector_title": "Ferramenta de Detecção de Padrões",
+ "pattern_detector_hint": "Insira um comando para testar se ele corresponde a algum padrão da lista negra ou branca.",
+ "pattern_detector_input_placeholder": "Insira um comando para testar, ex: rm -rf /tmp",
+ "pattern_detector_test_button": "Testar",
+ "pattern_detector_result_allowed": "Permitido (corresponde à lista branca)",
+ "pattern_detector_result_blocked": "Bloqueado (corresponde à lista negra)",
+ "pattern_detector_result_no_match": "Sem correspondência (usará regras padrão)",
+ "allow_shell_execution": "Permitir Comandos Agendados",
+ "allow_shell_execution_hint": "Permitir que tarefas agendadas executem comandos por padrão. Quando desabilitado, é necessário passar command_confirm=true para agendar uma tarefa de comando.",
+ "cron_exec_timeout": "Timeout de Comando Agendado (minutos)",
+ "cron_exec_timeout_hint": "Tempo máximo de execução para comandos agendados. 0 para desabilitar o timeout.",
+ "max_tokens": "Máximo de Tokens",
+ "max_tokens_hint": "Limite superior de tokens por resposta do modelo.",
+ "context_window": "Janela de Contexto",
+ "context_window_hint": "Capacidade de contexto de entrada do modelo em tokens. Deixe vazio para usar o padrão (4x max tokens).",
+ "max_tool_iterations": "Máximo de Iterações de Ferramentas",
+ "max_tool_iterations_hint": "Máximo de loops de chamadas de ferramentas em uma única tarefa.",
+ "summarize_threshold": "Limite para Resumo de Mensagens",
+ "summarize_threshold_hint": "Iniciar resumo após esta quantidade de mensagens.",
+ "summarize_token_percent": "Percentual de Tokens para Resumo",
+ "summarize_token_percent_hint": "Usado quando o resumo da conversa é acionado.",
+ "session_scope": "Escopo da Sessão",
+ "session_scope_hint": "Como o contexto do chat é isolado entre pares/canais.",
+ "session_scope_per_channel_peer": "Por Canal + Usuário",
+ "session_scope_per_channel_peer_desc": "Contexto separado para cada usuário em cada canal.",
+ "session_scope_per_channel": "Por Canal",
+ "session_scope_per_channel_desc": "Um contexto compartilhado por canal.",
+ "session_scope_per_peer": "Por Usuário",
+ "session_scope_per_peer_desc": "Um contexto por usuário em todos os canais.",
+ "session_scope_global": "Global",
+ "session_scope_global_desc": "Todas as mensagens compartilham um único contexto global.",
+ "heartbeat_enabled": "Heartbeat",
+ "heartbeat_enabled_hint": "Enviar mensagens periódicas de heartbeat.",
+ "heartbeat_interval": "Intervalo de Heartbeat (minutos)",
+ "heartbeat_interval_hint": "Intervalo em minutos entre sinais de heartbeat.",
+ "devices_enabled": "Habilitar Dispositivos",
+ "devices_enabled_hint": "Habilitar integrações com dispositivos de hardware.",
+ "monitor_usb": "Monitorar USB",
+ "monitor_usb_hint": "Observar eventos de conexão/desconexão USB quando dispositivos estão habilitados.",
+ "autostart_label": "Iniciar no Login",
+ "autostart_hint": "Iniciar o PicoClaw Web automaticamente ao fazer login.",
+ "autostart_unsupported": "Iniciar no login não é suportado nesta plataforma.",
+ "autostart_load_error": "Falha ao carregar status de inicialização automática.",
+ "server_port": "Porta do Serviço",
+ "server_port_hint": "Porta HTTP usada pelo PicoClaw Web.",
+ "lan_access": "Habilitar Acesso LAN",
+ "lan_access_hint": "Permitir acesso de outros dispositivos na sua rede local.",
+ "allowed_cidrs": "CIDRs de Rede Permitidos",
+ "allowed_cidrs_hint": "Apenas clientes destes intervalos CIDR podem acessar o serviço. Um por linha ou separados por vírgula. Deixe vazio para permitir todos.",
+ "allowed_cidrs_placeholder": "192.168.1.0/24\n10.0.0.0/8",
+ "sections": {
+ "agent": "Agente",
+ "runtime": "Execução",
+ "exec": "Executar Comandos",
+ "cron": "Tarefas Cron",
+ "launcher": "Serviço",
+ "devices": "Dispositivos"
+ },
+ "open_raw": "Config Bruta",
+ "back_to_visual": "Config Visual",
+ "raw_json_title": "Configuração JSON Bruta",
+ "json_placeholder": "Insira configuração JSON válida...",
+ "save_success": "Configuração salva com sucesso.",
+ "save_error": "Falha ao salvar configuração.",
+ "reset_confirm_title": "Redefinir Alterações",
+ "reset_confirm_desc": "Tem certeza de que deseja redefinir suas alterações não salvas para o último estado salvo?",
+ "reset_success": "Alterações redefinidas para o último estado salvo.",
+ "invalid_json": "Formato JSON inválido.",
+ "format_success": "JSON formatado com sucesso.",
+ "format_error": "Formato JSON inválido.",
+ "format": "Formatar",
+ "unsaved_changes": "Você tem alterações não salvas."
+ },
+ "logs": {
+ "clear": "Limpar logs",
+ "empty": "Aguardando logs..."
+ }
+ }
+}