Просмотр исходного кода

feat(i18n): add br locale support (#10086)

Ygor Simões 1 месяц назад
Родитель
Сommit
32f72f49a8

+ 8 - 2
packages/app/src/context/language.tsx

@@ -16,6 +16,7 @@ import { dict as pl } from "@/i18n/pl"
 import { dict as ru } from "@/i18n/ru"
 import { dict as ru } from "@/i18n/ru"
 import { dict as ar } from "@/i18n/ar"
 import { dict as ar } from "@/i18n/ar"
 import { dict as no } from "@/i18n/no"
 import { dict as no } from "@/i18n/no"
+import { dict as br } from "@/i18n/br"
 import { dict as uiEn } from "@opencode-ai/ui/i18n/en"
 import { dict as uiEn } from "@opencode-ai/ui/i18n/en"
 import { dict as uiZh } from "@opencode-ai/ui/i18n/zh"
 import { dict as uiZh } from "@opencode-ai/ui/i18n/zh"
 import { dict as uiZht } from "@opencode-ai/ui/i18n/zht"
 import { dict as uiZht } from "@opencode-ai/ui/i18n/zht"
@@ -29,13 +30,14 @@ import { dict as uiPl } from "@opencode-ai/ui/i18n/pl"
 import { dict as uiRu } from "@opencode-ai/ui/i18n/ru"
 import { dict as uiRu } from "@opencode-ai/ui/i18n/ru"
 import { dict as uiAr } from "@opencode-ai/ui/i18n/ar"
 import { dict as uiAr } from "@opencode-ai/ui/i18n/ar"
 import { dict as uiNo } from "@opencode-ai/ui/i18n/no"
 import { dict as uiNo } from "@opencode-ai/ui/i18n/no"
+import { dict as uiBr } from "@opencode-ai/ui/i18n/br"
 
 
-export type Locale = "en" | "zh" | "zht" | "ko" | "de" | "es" | "fr" | "da" | "ja" | "pl" | "ru" | "ar" | "no"
+export type Locale = "en" | "zh" | "zht" | "ko" | "de" | "es" | "fr" | "da" | "ja" | "pl" | "ru" | "ar" | "no" | "br"
 
 
 type RawDictionary = typeof en & typeof uiEn
 type RawDictionary = typeof en & typeof uiEn
 type Dictionary = i18n.Flatten<RawDictionary>
 type Dictionary = i18n.Flatten<RawDictionary>
 
 
-const LOCALES: readonly Locale[] = ["en", "zh", "zht", "ko", "de", "es", "fr", "da", "ja", "pl", "ru", "ar", "no"]
+const LOCALES: readonly Locale[] = ["en", "zh", "zht", "ko", "de", "es", "fr", "da", "ja", "pl", "ru", "ar", "no", "br"]
 
 
 function detectLocale(): Locale {
 function detectLocale(): Locale {
   if (typeof navigator !== "object") return "en"
   if (typeof navigator !== "object") return "en"
@@ -62,6 +64,7 @@ function detectLocale(): Locale {
       language.toLowerCase().startsWith("nn")
       language.toLowerCase().startsWith("nn")
     )
     )
       return "no"
       return "no"
+    if (language.toLowerCase().startsWith("pt")) return "br"
   }
   }
 
 
   return "en"
   return "en"
@@ -90,6 +93,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
       if (store.locale === "ru") return "ru"
       if (store.locale === "ru") return "ru"
       if (store.locale === "ar") return "ar"
       if (store.locale === "ar") return "ar"
       if (store.locale === "no") return "no"
       if (store.locale === "no") return "no"
+      if (store.locale === "br") return "br"
       return "en"
       return "en"
     })
     })
 
 
@@ -113,6 +117,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
       if (locale() === "ru") return { ...base, ...i18n.flatten({ ...ru, ...uiRu }) }
       if (locale() === "ru") return { ...base, ...i18n.flatten({ ...ru, ...uiRu }) }
       if (locale() === "ar") return { ...base, ...i18n.flatten({ ...ar, ...uiAr }) }
       if (locale() === "ar") return { ...base, ...i18n.flatten({ ...ar, ...uiAr }) }
       if (locale() === "no") return { ...base, ...i18n.flatten({ ...no, ...uiNo }) }
       if (locale() === "no") return { ...base, ...i18n.flatten({ ...no, ...uiNo }) }
+      if (locale() === "br") return { ...base, ...i18n.flatten({ ...br, ...uiBr }) }
       return { ...base, ...i18n.flatten({ ...ko, ...uiKo }) }
       return { ...base, ...i18n.flatten({ ...ko, ...uiKo }) }
     })
     })
 
 
@@ -132,6 +137,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
       ru: "language.ru",
       ru: "language.ru",
       ar: "language.ar",
       ar: "language.ar",
       no: "language.no",
       no: "language.no",
+      br: "language.br",
     }
     }
 
 
     const label = (value: Locale) => t(labelKey[value])
     const label = (value: Locale) => t(labelKey[value])

+ 1 - 0
packages/app/src/i18n/ar.ts

@@ -305,6 +305,7 @@ export const dict = {
   "language.pl": "البولندية",
   "language.pl": "البولندية",
   "language.ar": "العربية",
   "language.ar": "العربية",
   "language.no": "النرويجية",
   "language.no": "النرويجية",
+  "language.br": "البرتغالية (البرازيل)",
 
 
   "toast.language.title": "لغة",
   "toast.language.title": "لغة",
   "toast.language.description": "تم التبديل إلى {{language}}",
   "toast.language.description": "تم التبديل إلى {{language}}",

+ 665 - 0
packages/app/src/i18n/br.ts

@@ -0,0 +1,665 @@
+export const dict = {
+  "command.category.suggested": "Sugerido",
+  "command.category.view": "Visualizar",
+  "command.category.project": "Projeto",
+  "command.category.provider": "Provedor",
+  "command.category.server": "Servidor",
+  "command.category.session": "Sessão",
+  "command.category.theme": "Tema",
+  "command.category.language": "Idioma",
+  "command.category.file": "Arquivo",
+  "command.category.terminal": "Terminal",
+  "command.category.model": "Modelo",
+  "command.category.mcp": "MCP",
+  "command.category.agent": "Agente",
+  "command.category.permissions": "Permissões",
+  "command.category.workspace": "Espaço de trabalho",
+  "command.category.settings": "Configurações",
+
+  "theme.scheme.system": "Sistema",
+  "theme.scheme.light": "Claro",
+  "theme.scheme.dark": "Escuro",
+
+  "command.sidebar.toggle": "Alternar barra lateral",
+  "command.project.open": "Abrir projeto",
+  "command.provider.connect": "Conectar provedor",
+  "command.server.switch": "Trocar servidor",
+  "command.settings.open": "Abrir configurações",
+  "command.session.previous": "Sessão anterior",
+  "command.session.next": "Próxima sessão",
+  "command.session.archive": "Arquivar sessão",
+
+  "command.palette": "Paleta de comandos",
+
+  "command.theme.cycle": "Alternar tema",
+  "command.theme.set": "Usar tema: {{theme}}",
+  "command.theme.scheme.cycle": "Alternar esquema de cores",
+  "command.theme.scheme.set": "Usar esquema de cores: {{scheme}}",
+
+  "command.language.cycle": "Alternar idioma",
+  "command.language.set": "Usar idioma: {{language}}",
+
+  "command.session.new": "Nova sessão",
+  "command.file.open": "Abrir arquivo",
+  "command.file.open.description": "Buscar arquivos e comandos",
+  "command.terminal.toggle": "Alternar terminal",
+  "command.review.toggle": "Alternar revisão",
+  "command.terminal.new": "Novo terminal",
+  "command.terminal.new.description": "Criar uma nova aba de terminal",
+  "command.steps.toggle": "Alternar passos",
+  "command.steps.toggle.description": "Mostrar ou ocultar passos da mensagem atual",
+  "command.message.previous": "Mensagem anterior",
+  "command.message.previous.description": "Ir para a mensagem de usuário anterior",
+  "command.message.next": "Próxima mensagem",
+  "command.message.next.description": "Ir para a próxima mensagem de usuário",
+  "command.model.choose": "Escolher modelo",
+  "command.model.choose.description": "Selecionar um modelo diferente",
+  "command.mcp.toggle": "Alternar MCPs",
+  "command.mcp.toggle.description": "Alternar MCPs",
+  "command.agent.cycle": "Alternar agente",
+  "command.agent.cycle.description": "Mudar para o próximo agente",
+  "command.agent.cycle.reverse": "Alternar agente (reverso)",
+  "command.agent.cycle.reverse.description": "Mudar para o agente anterior",
+  "command.model.variant.cycle": "Alternar nível de raciocínio",
+  "command.model.variant.cycle.description": "Mudar para o próximo nível de esforço",
+  "command.permissions.autoaccept.enable": "Aceitar edições automaticamente",
+  "command.permissions.autoaccept.disable": "Parar de aceitar edições automaticamente",
+  "command.session.undo": "Desfazer",
+  "command.session.undo.description": "Desfazer a última mensagem",
+  "command.session.redo": "Refazer",
+  "command.session.redo.description": "Refazer a última mensagem desfeita",
+  "command.session.compact": "Compactar sessão",
+  "command.session.compact.description": "Resumir a sessão para reduzir o tamanho do contexto",
+  "command.session.fork": "Bifurcar da mensagem",
+  "command.session.fork.description": "Criar uma nova sessão a partir de uma mensagem anterior",
+  "command.session.share": "Compartilhar sessão",
+  "command.session.share.description": "Compartilhar esta sessão e copiar a URL para a área de transferência",
+  "command.session.unshare": "Parar de compartilhar sessão",
+  "command.session.unshare.description": "Parar de compartilhar esta sessão",
+
+  "palette.search.placeholder": "Buscar arquivos e comandos",
+  "palette.empty": "Nenhum resultado encontrado",
+  "palette.group.commands": "Comandos",
+  "palette.group.files": "Arquivos",
+
+  "dialog.provider.search.placeholder": "Buscar provedores",
+  "dialog.provider.empty": "Nenhum provedor encontrado",
+  "dialog.provider.group.popular": "Popular",
+  "dialog.provider.group.other": "Outro",
+  "dialog.provider.tag.recommended": "Recomendado",
+  "dialog.provider.anthropic.note": "Conectar com Claude Pro/Max ou chave de API",
+
+  "dialog.model.select.title": "Selecionar modelo",
+  "dialog.model.search.placeholder": "Buscar modelos",
+  "dialog.model.empty": "Nenhum resultado de modelo",
+  "dialog.model.manage": "Gerenciar modelos",
+  "dialog.model.manage.description": "Personalizar quais modelos aparecem no seletor de modelos.",
+
+  "dialog.model.unpaid.freeModels.title": "Modelos gratuitos fornecidos pelo OpenCode",
+  "dialog.model.unpaid.addMore.title": "Adicionar mais modelos de provedores populares",
+
+  "dialog.provider.viewAll": "Ver todos os provedores",
+
+  "provider.connect.title": "Conectar {{provider}}",
+  "provider.connect.title.anthropicProMax": "Entrar com Claude Pro/Max",
+  "provider.connect.selectMethod": "Selecionar método de login para {{provider}}.",
+  "provider.connect.method.apiKey": "Chave de API",
+  "provider.connect.status.inProgress": "Autorização em andamento...",
+  "provider.connect.status.waiting": "Aguardando autorização...",
+  "provider.connect.status.failed": "Autorização falhou: {{error}}",
+  "provider.connect.apiKey.description":
+    "Digite sua chave de API do {{provider}} para conectar sua conta e usar modelos do {{provider}} no OpenCode.",
+  "provider.connect.apiKey.label": "Chave de API do {{provider}}",
+  "provider.connect.apiKey.placeholder": "Chave de API",
+  "provider.connect.apiKey.required": "A chave de API é obrigatória",
+  "provider.connect.opencodeZen.line1":
+    "OpenCode Zen oferece acesso a um conjunto selecionado de modelos confiáveis otimizados para agentes de código.",
+  "provider.connect.opencodeZen.line2":
+    "Com uma única chave de API você terá acesso a modelos como Claude, GPT, Gemini, GLM e mais.",
+  "provider.connect.opencodeZen.visit.prefix": "Visite ",
+  "provider.connect.opencodeZen.visit.link": "opencode.ai/zen",
+  "provider.connect.opencodeZen.visit.suffix": " para obter sua chave de API.",
+  "provider.connect.oauth.code.visit.prefix": "Visite ",
+  "provider.connect.oauth.code.visit.link": "este link",
+  "provider.connect.oauth.code.visit.suffix":
+    " para obter seu código de autorização e conectar sua conta para usar modelos do {{provider}} no OpenCode.",
+  "provider.connect.oauth.code.label": "Código de autorização {{method}}",
+  "provider.connect.oauth.code.placeholder": "Código de autorização",
+  "provider.connect.oauth.code.required": "O código de autorização é obrigatório",
+  "provider.connect.oauth.code.invalid": "Código de autorização inválido",
+  "provider.connect.oauth.auto.visit.prefix": "Visite ",
+  "provider.connect.oauth.auto.visit.link": "este link",
+  "provider.connect.oauth.auto.visit.suffix":
+    " e digite o código abaixo para conectar sua conta e usar modelos do {{provider}} no OpenCode.",
+  "provider.connect.oauth.auto.confirmationCode": "Código de confirmação",
+  "provider.connect.toast.connected.title": "{{provider}} conectado",
+  "provider.connect.toast.connected.description": "Modelos do {{provider}} agora estão disponíveis para uso.",
+
+  "model.tag.free": "Grátis",
+  "model.tag.latest": "Mais recente",
+  "model.provider.anthropic": "Anthropic",
+  "model.provider.openai": "OpenAI",
+  "model.provider.google": "Google",
+  "model.provider.xai": "xAI",
+  "model.provider.meta": "Meta",
+  "model.input.text": "texto",
+  "model.input.image": "imagem",
+  "model.input.audio": "áudio",
+  "model.input.video": "vídeo",
+  "model.input.pdf": "pdf",
+  "model.tooltip.allows": "Permite: {{inputs}}",
+  "model.tooltip.reasoning.allowed": "Permite raciocínio",
+  "model.tooltip.reasoning.none": "Sem raciocínio",
+  "model.tooltip.context": "Limite de contexto {{limit}}",
+
+  "common.search.placeholder": "Buscar",
+  "common.goBack": "Voltar",
+  "common.loading": "Carregando",
+  "common.loading.ellipsis": "...",
+  "common.cancel": "Cancelar",
+  "common.submit": "Enviar",
+  "common.save": "Salvar",
+  "common.saving": "Salvando...",
+  "common.default": "Padrão",
+  "common.attachment": "anexo",
+
+  "prompt.placeholder.shell": "Digite comando do shell...",
+  "prompt.placeholder.normal": 'Pergunte qualquer coisa... "{{example}}"',
+  "prompt.mode.shell": "Shell",
+  "prompt.mode.shell.exit": "esc para sair",
+
+  "prompt.example.1": "Corrigir um TODO no código",
+  "prompt.example.2": "Qual é a stack tecnológica deste projeto?",
+  "prompt.example.3": "Corrigir testes quebrados",
+  "prompt.example.4": "Explicar como funciona a autenticação",
+  "prompt.example.5": "Encontrar e corrigir vulnerabilidades de segurança",
+  "prompt.example.6": "Adicionar testes unitários para o serviço de usuário",
+  "prompt.example.7": "Refatorar esta função para melhor legibilidade",
+  "prompt.example.8": "O que significa este erro?",
+  "prompt.example.9": "Me ajude a depurar este problema",
+  "prompt.example.10": "Gerar documentação da API",
+  "prompt.example.11": "Otimizar consultas ao banco de dados",
+  "prompt.example.12": "Adicionar validação de entrada",
+  "prompt.example.13": "Criar um novo componente para...",
+  "prompt.example.14": "Como faço o deploy deste projeto?",
+  "prompt.example.15": "Revisar meu código para boas práticas",
+  "prompt.example.16": "Adicionar tratamento de erros a esta função",
+  "prompt.example.17": "Explicar este padrão regex",
+  "prompt.example.18": "Converter isto para TypeScript",
+  "prompt.example.19": "Adicionar logging em todo o código",
+  "prompt.example.20": "Quais dependências estão desatualizadas?",
+  "prompt.example.21": "Me ajude a escrever um script de migração",
+  "prompt.example.22": "Implementar cache para este endpoint",
+  "prompt.example.23": "Adicionar paginação a esta lista",
+  "prompt.example.24": "Criar um comando CLI para...",
+  "prompt.example.25": "Como funcionam as variáveis de ambiente aqui?",
+
+  "prompt.popover.emptyResults": "Nenhum resultado correspondente",
+  "prompt.popover.emptyCommands": "Nenhum comando correspondente",
+  "prompt.dropzone.label": "Solte imagens ou PDFs aqui",
+  "prompt.slash.badge.custom": "personalizado",
+  "prompt.context.active": "ativo",
+  "prompt.context.includeActiveFile": "Incluir arquivo ativo",
+  "prompt.context.removeActiveFile": "Remover arquivo ativo do contexto",
+  "prompt.context.removeFile": "Remover arquivo do contexto",
+  "prompt.action.attachFile": "Anexar arquivo",
+  "prompt.attachment.remove": "Remover anexo",
+  "prompt.action.send": "Enviar",
+  "prompt.action.stop": "Parar",
+
+  "prompt.toast.pasteUnsupported.title": "Colagem não suportada",
+  "prompt.toast.pasteUnsupported.description": "Somente imagens ou PDFs podem ser colados aqui.",
+  "prompt.toast.modelAgentRequired.title": "Selecione um agente e modelo",
+  "prompt.toast.modelAgentRequired.description": "Escolha um agente e modelo antes de enviar um prompt.",
+  "prompt.toast.worktreeCreateFailed.title": "Falha ao criar worktree",
+  "prompt.toast.sessionCreateFailed.title": "Falha ao criar sessão",
+  "prompt.toast.shellSendFailed.title": "Falha ao enviar comando shell",
+  "prompt.toast.commandSendFailed.title": "Falha ao enviar comando",
+  "prompt.toast.promptSendFailed.title": "Falha ao enviar prompt",
+
+  "dialog.mcp.title": "MCPs",
+  "dialog.mcp.description": "{{enabled}} de {{total}} habilitados",
+  "dialog.mcp.empty": "Nenhum MCP configurado",
+
+  "mcp.status.connected": "conectado",
+  "mcp.status.failed": "falhou",
+  "mcp.status.needs_auth": "precisa de autenticação",
+  "mcp.status.disabled": "desabilitado",
+
+  "dialog.fork.empty": "Nenhuma mensagem para bifurcar",
+
+  "dialog.directory.search.placeholder": "Buscar pastas",
+  "dialog.directory.empty": "Nenhuma pasta encontrada",
+
+  "dialog.server.title": "Servidores",
+  "dialog.server.description": "Trocar para qual servidor OpenCode este aplicativo se conecta.",
+  "dialog.server.search.placeholder": "Buscar servidores",
+  "dialog.server.empty": "Nenhum servidor ainda",
+  "dialog.server.add.title": "Adicionar um servidor",
+  "dialog.server.add.url": "URL do servidor",
+  "dialog.server.add.placeholder": "http://localhost:4096",
+  "dialog.server.add.error": "Não foi possível conectar ao servidor",
+  "dialog.server.add.checking": "Verificando...",
+  "dialog.server.add.button": "Adicionar",
+  "dialog.server.default.title": "Servidor padrão",
+  "dialog.server.default.description":
+    "Conectar a este servidor na inicialização do aplicativo ao invés de iniciar um servidor local. Requer reinicialização.",
+  "dialog.server.default.none": "Nenhum servidor selecionado",
+  "dialog.server.default.set": "Definir servidor atual como padrão",
+  "dialog.server.default.clear": "Limpar",
+  "dialog.server.action.remove": "Remover servidor",
+
+  "dialog.project.edit.title": "Editar projeto",
+  "dialog.project.edit.name": "Nome",
+  "dialog.project.edit.icon": "Ícone",
+  "dialog.project.edit.icon.alt": "Ícone do projeto",
+  "dialog.project.edit.icon.hint": "Clique ou arraste uma imagem",
+  "dialog.project.edit.icon.recommended": "Recomendado: 128x128px",
+  "dialog.project.edit.color": "Cor",
+  "dialog.project.edit.color.select": "Selecionar cor {{color}}",
+  "dialog.project.edit.worktree.startup": "Script de inicialização do espaço de trabalho",
+  "dialog.project.edit.worktree.startup.description": "Executa após criar um novo espaço de trabalho (worktree).",
+  "dialog.project.edit.worktree.startup.placeholder": "ex: bun install",
+
+  "context.breakdown.title": "Detalhamento do Contexto",
+  "context.breakdown.note":
+    'Detalhamento aproximado dos tokens de entrada. "Outros" inclui definições de ferramentas e overhead.',
+  "context.breakdown.system": "Sistema",
+  "context.breakdown.user": "Usuário",
+  "context.breakdown.assistant": "Assistente",
+  "context.breakdown.tool": "Chamadas de Ferramentas",
+  "context.breakdown.other": "Outros",
+
+  "context.systemPrompt.title": "Prompt do Sistema",
+  "context.rawMessages.title": "Mensagens brutas",
+
+  "context.stats.session": "Sessão",
+  "context.stats.messages": "Mensagens",
+  "context.stats.provider": "Provedor",
+  "context.stats.model": "Modelo",
+  "context.stats.limit": "Limite de Contexto",
+  "context.stats.totalTokens": "Total de Tokens",
+  "context.stats.usage": "Uso",
+  "context.stats.inputTokens": "Tokens de Entrada",
+  "context.stats.outputTokens": "Tokens de Saída",
+  "context.stats.reasoningTokens": "Tokens de Raciocínio",
+  "context.stats.cacheTokens": "Tokens de Cache (leitura/escrita)",
+  "context.stats.userMessages": "Mensagens de Usuário",
+  "context.stats.assistantMessages": "Mensagens do Assistente",
+  "context.stats.totalCost": "Custo Total",
+  "context.stats.sessionCreated": "Sessão Criada",
+  "context.stats.lastActivity": "Última Atividade",
+
+  "context.usage.tokens": "Tokens",
+  "context.usage.usage": "Uso",
+  "context.usage.cost": "Custo",
+  "context.usage.clickToView": "Clique para ver o contexto",
+  "context.usage.view": "Ver uso do contexto",
+
+  "language.en": "Inglês",
+  "language.zh": "Chinês (Simplificado)",
+  "language.zht": "Chinês (Tradicional)",
+  "language.ko": "Coreano",
+  "language.de": "Alemão",
+  "language.es": "Espanhol",
+  "language.fr": "Francês",
+  "language.ja": "Japonês",
+  "language.da": "Dinamarquês",
+  "language.ru": "Russo",
+  "language.pl": "Polonês",
+  "language.ar": "Árabe",
+  "language.no": "Norueguês",
+  "language.br": "Português (Brasil)",
+
+  "toast.language.title": "Idioma",
+  "toast.language.description": "Alterado para {{language}}",
+
+  "toast.theme.title": "Tema alterado",
+  "toast.scheme.title": "Esquema de cores",
+
+  "toast.permissions.autoaccept.on.title": "Aceitando edições automaticamente",
+  "toast.permissions.autoaccept.on.description": "Permissões de edição e escrita serão aprovadas automaticamente",
+  "toast.permissions.autoaccept.off.title": "Parou de aceitar edições automaticamente",
+  "toast.permissions.autoaccept.off.description": "Permissões de edição e escrita exigirão aprovação",
+
+  "toast.model.none.title": "Nenhum modelo selecionado",
+  "toast.model.none.description": "Conecte um provedor para resumir esta sessão",
+
+  "toast.file.loadFailed.title": "Falha ao carregar arquivo",
+
+  "toast.session.share.copyFailed.title": "Falha ao copiar URL para a área de transferência",
+  "toast.session.share.success.title": "Sessão compartilhada",
+  "toast.session.share.success.description": "URL compartilhada copiada para a área de transferência!",
+  "toast.session.share.failed.title": "Falha ao compartilhar sessão",
+  "toast.session.share.failed.description": "Ocorreu um erro ao compartilhar a sessão",
+
+  "toast.session.unshare.success.title": "Sessão não compartilhada",
+  "toast.session.unshare.success.description": "Sessão deixou de ser compartilhada com sucesso!",
+  "toast.session.unshare.failed.title": "Falha ao parar de compartilhar sessão",
+  "toast.session.unshare.failed.description": "Ocorreu um erro ao parar de compartilhar a sessão",
+
+  "toast.session.listFailed.title": "Falha ao carregar sessões para {{project}}",
+
+  "toast.update.title": "Atualização disponível",
+  "toast.update.description": "Uma nova versão do OpenCode ({{version}}) está disponível para instalação.",
+  "toast.update.action.installRestart": "Instalar e reiniciar",
+  "toast.update.action.notYet": "Agora não",
+
+  "error.page.title": "Algo deu errado",
+  "error.page.description": "Ocorreu um erro ao carregar a aplicação.",
+  "error.page.details.label": "Detalhes do Erro",
+  "error.page.action.restart": "Reiniciar",
+  "error.page.action.checking": "Verificando...",
+  "error.page.action.checkUpdates": "Verificar atualizações",
+  "error.page.action.updateTo": "Atualizar para {{version}}",
+  "error.page.report.prefix": "Por favor, reporte este erro para a equipe do OpenCode",
+  "error.page.report.discord": "no Discord",
+  "error.page.version": "Versão: {{version}}",
+
+  "error.dev.rootNotFound":
+    "Elemento raiz não encontrado. Você esqueceu de adicioná-lo ao seu index.html? Ou talvez o atributo id foi escrito incorretamente?",
+
+  "error.globalSync.connectFailed": "Não foi possível conectar ao servidor. Há um servidor executando em `{{url}}`?",
+
+  "error.chain.unknown": "Erro desconhecido",
+  "error.chain.causedBy": "Causado por:",
+  "error.chain.apiError": "Erro de API",
+  "error.chain.status": "Status: {{status}}",
+  "error.chain.retryable": "Pode tentar novamente: {{retryable}}",
+  "error.chain.responseBody": "Corpo da resposta:\n{{body}}",
+  "error.chain.didYouMean": "Você quis dizer: {{suggestions}}",
+  "error.chain.modelNotFound": "Modelo não encontrado: {{provider}}/{{model}}",
+  "error.chain.checkConfig": "Verifique os nomes de provedor/modelo na sua configuração (opencode.json)",
+  "error.chain.mcpFailed": 'Servidor MCP "{{name}}" falhou. Nota: OpenCode ainda não suporta autenticação MCP.',
+  "error.chain.providerAuthFailed": "Autenticação do provedor falhou ({{provider}}): {{message}}",
+  "error.chain.providerInitFailed":
+    'Falha ao inicializar provedor "{{provider}}". Verifique credenciais e configuração.',
+  "error.chain.configJsonInvalid": "Arquivo de configuração em {{path}} não é um JSON(C) válido",
+  "error.chain.configJsonInvalidWithMessage":
+    "Arquivo de configuração em {{path}} não é um JSON(C) válido: {{message}}",
+  "error.chain.configDirectoryTypo":
+    'Diretório "{{dir}}" em {{path}} não é válido. Renomeie o diretório para "{{suggestion}}" ou remova-o. Este é um erro de digitação comum.',
+  "error.chain.configFrontmatterError": "Falha ao analisar frontmatter em {{path}}:\n{{message}}",
+  "error.chain.configInvalid": "Arquivo de configuração em {{path}} é inválido",
+  "error.chain.configInvalidWithMessage": "Arquivo de configuração em {{path}} é inválido: {{message}}",
+
+  "notification.permission.title": "Permissão necessária",
+  "notification.permission.description": "{{sessionTitle}} em {{projectName}} precisa de permissão",
+  "notification.question.title": "Pergunta",
+  "notification.question.description": "{{sessionTitle}} em {{projectName}} tem uma pergunta",
+  "notification.action.goToSession": "Ir para sessão",
+
+  "notification.session.responseReady.title": "Resposta pronta",
+  "notification.session.error.title": "Erro na sessão",
+  "notification.session.error.fallbackDescription": "Ocorreu um erro",
+
+  "home.recentProjects": "Projetos recentes",
+  "home.empty.title": "Nenhum projeto recente",
+  "home.empty.description": "Comece abrindo um projeto local",
+
+  "session.tab.session": "Sessão",
+  "session.tab.review": "Revisão",
+  "session.tab.context": "Contexto",
+  "session.panel.reviewAndFiles": "Revisão e arquivos",
+  "session.review.filesChanged": "{{count}} Arquivos Alterados",
+  "session.review.loadingChanges": "Carregando alterações...",
+  "session.review.empty": "Nenhuma alteração nesta sessão ainda",
+  "session.messages.renderEarlier": "Renderizar mensagens anteriores",
+  "session.messages.loadingEarlier": "Carregando mensagens anteriores...",
+  "session.messages.loadEarlier": "Carregar mensagens anteriores",
+  "session.messages.loading": "Carregando mensagens...",
+  "session.messages.jumpToLatest": "Ir para a mais recente",
+
+  "session.context.addToContext": "Adicionar {{selection}} ao contexto",
+
+  "session.new.worktree.main": "Branch principal",
+  "session.new.worktree.mainWithBranch": "Branch principal ({{branch}})",
+  "session.new.worktree.create": "Criar novo worktree",
+  "session.new.lastModified": "Última modificação",
+
+  "session.header.search.placeholder": "Buscar {{project}}",
+  "session.header.searchFiles": "Buscar arquivos",
+
+  "session.share.popover.title": "Publicar na web",
+  "session.share.popover.description.shared":
+    "Esta sessão é pública na web. Está acessível para qualquer pessoa com o link.",
+  "session.share.popover.description.unshared":
+    "Compartilhar sessão publicamente na web. Estará acessível para qualquer pessoa com o link.",
+  "session.share.action.share": "Compartilhar",
+  "session.share.action.publish": "Publicar",
+  "session.share.action.publishing": "Publicando...",
+  "session.share.action.unpublish": "Cancelar publicação",
+  "session.share.action.unpublishing": "Cancelando publicação...",
+  "session.share.action.view": "Ver",
+  "session.share.copy.copied": "Copiado",
+  "session.share.copy.copyLink": "Copiar link",
+
+  "lsp.tooltip.none": "Nenhum servidor LSP",
+  "lsp.label.connected": "{{count}} LSP",
+
+  "prompt.loading": "Carregando prompt...",
+  "terminal.loading": "Carregando terminal...",
+  "terminal.title": "Terminal",
+  "terminal.title.numbered": "Terminal {{number}}",
+  "terminal.close": "Fechar terminal",
+  "terminal.connectionLost.title": "Conexão Perdida",
+  "terminal.connectionLost.description":
+    "A conexão do terminal foi interrompida. Isso pode acontecer quando o servidor reinicia.",
+
+  "common.closeTab": "Fechar aba",
+  "common.dismiss": "Descartar",
+  "common.requestFailed": "Requisição falhou",
+  "common.moreOptions": "Mais opções",
+  "common.learnMore": "Saiba mais",
+  "common.rename": "Renomear",
+  "common.reset": "Redefinir",
+  "common.archive": "Arquivar",
+  "common.delete": "Excluir",
+  "common.close": "Fechar",
+  "common.edit": "Editar",
+  "common.loadMore": "Carregar mais",
+  "common.key.esc": "ESC",
+
+  "sidebar.menu.toggle": "Alternar menu",
+  "sidebar.nav.projectsAndSessions": "Projetos e sessões",
+  "sidebar.settings": "Configurações",
+  "sidebar.help": "Ajuda",
+  "sidebar.workspaces.enable": "Habilitar espaços de trabalho",
+  "sidebar.workspaces.disable": "Desabilitar espaços de trabalho",
+  "sidebar.gettingStarted.title": "Começando",
+  "sidebar.gettingStarted.line1": "OpenCode inclui modelos gratuitos para você começar imediatamente.",
+  "sidebar.gettingStarted.line2": "Conecte qualquer provedor para usar modelos, incluindo Claude, GPT, Gemini etc.",
+  "sidebar.project.recentSessions": "Sessões recentes",
+  "sidebar.project.viewAllSessions": "Ver todas as sessões",
+
+  "settings.section.desktop": "Desktop",
+  "settings.tab.general": "Geral",
+  "settings.tab.shortcuts": "Atalhos",
+
+  "settings.general.section.appearance": "Aparência",
+  "settings.general.section.notifications": "Notificações do sistema",
+  "settings.general.section.sounds": "Efeitos sonoros",
+
+  "settings.general.row.language.title": "Idioma",
+  "settings.general.row.language.description": "Alterar o idioma de exibição do OpenCode",
+  "settings.general.row.appearance.title": "Aparência",
+  "settings.general.row.appearance.description": "Personalize como o OpenCode aparece no seu dispositivo",
+  "settings.general.row.theme.title": "Tema",
+  "settings.general.row.theme.description": "Personalize como o OpenCode é tematizado.",
+  "settings.general.row.font.title": "Fonte",
+  "settings.general.row.font.description": "Personalize a fonte monoespaçada usada em blocos de código",
+  "font.option.ibmPlexMono": "IBM Plex Mono",
+  "font.option.cascadiaCode": "Cascadia Code",
+  "font.option.firaCode": "Fira Code",
+  "font.option.hack": "Hack",
+  "font.option.inconsolata": "Inconsolata",
+  "font.option.intelOneMono": "Intel One Mono",
+  "font.option.jetbrainsMono": "JetBrains Mono",
+  "font.option.mesloLgs": "Meslo LGS",
+  "font.option.robotoMono": "Roboto Mono",
+  "font.option.sourceCodePro": "Source Code Pro",
+  "font.option.ubuntuMono": "Ubuntu Mono",
+  "sound.option.alert01": "Alerta 01",
+  "sound.option.alert02": "Alerta 02",
+  "sound.option.alert03": "Alerta 03",
+  "sound.option.alert04": "Alerta 04",
+  "sound.option.alert05": "Alerta 05",
+  "sound.option.alert06": "Alerta 06",
+  "sound.option.alert07": "Alerta 07",
+  "sound.option.alert08": "Alerta 08",
+  "sound.option.alert09": "Alerta 09",
+  "sound.option.alert10": "Alerta 10",
+  "sound.option.bipbop01": "Bip-bop 01",
+  "sound.option.bipbop02": "Bip-bop 02",
+  "sound.option.bipbop03": "Bip-bop 03",
+  "sound.option.bipbop04": "Bip-bop 04",
+  "sound.option.bipbop05": "Bip-bop 05",
+  "sound.option.bipbop06": "Bip-bop 06",
+  "sound.option.bipbop07": "Bip-bop 07",
+  "sound.option.bipbop08": "Bip-bop 08",
+  "sound.option.bipbop09": "Bip-bop 09",
+  "sound.option.bipbop10": "Bip-bop 10",
+  "sound.option.staplebops01": "Staplebops 01",
+  "sound.option.staplebops02": "Staplebops 02",
+  "sound.option.staplebops03": "Staplebops 03",
+  "sound.option.staplebops04": "Staplebops 04",
+  "sound.option.staplebops05": "Staplebops 05",
+  "sound.option.staplebops06": "Staplebops 06",
+  "sound.option.staplebops07": "Staplebops 07",
+  "sound.option.nope01": "Não 01",
+  "sound.option.nope02": "Não 02",
+  "sound.option.nope03": "Não 03",
+  "sound.option.nope04": "Não 04",
+  "sound.option.nope05": "Não 05",
+  "sound.option.nope06": "Não 06",
+  "sound.option.nope07": "Não 07",
+  "sound.option.nope08": "Não 08",
+  "sound.option.nope09": "Não 09",
+  "sound.option.nope10": "Não 10",
+  "sound.option.nope11": "Não 11",
+  "sound.option.nope12": "Não 12",
+  "sound.option.yup01": "Sim 01",
+  "sound.option.yup02": "Sim 02",
+  "sound.option.yup03": "Sim 03",
+  "sound.option.yup04": "Sim 04",
+  "sound.option.yup05": "Sim 05",
+  "sound.option.yup06": "Sim 06",
+
+  "settings.general.notifications.agent.title": "Agente",
+  "settings.general.notifications.agent.description":
+    "Mostrar notificação do sistema quando o agente estiver completo ou precisar de atenção",
+  "settings.general.notifications.permissions.title": "Permissões",
+  "settings.general.notifications.permissions.description":
+    "Mostrar notificação do sistema quando uma permissão for necessária",
+  "settings.general.notifications.errors.title": "Erros",
+  "settings.general.notifications.errors.description": "Mostrar notificação do sistema quando ocorrer um erro",
+
+  "settings.general.sounds.agent.title": "Agente",
+  "settings.general.sounds.agent.description": "Reproduzir som quando o agente estiver completo ou precisar de atenção",
+  "settings.general.sounds.permissions.title": "Permissões",
+  "settings.general.sounds.permissions.description": "Reproduzir som quando uma permissão for necessária",
+  "settings.general.sounds.errors.title": "Erros",
+  "settings.general.sounds.errors.description": "Reproduzir som quando ocorrer um erro",
+
+  "settings.shortcuts.title": "Atalhos de teclado",
+  "settings.shortcuts.reset.button": "Redefinir para padrões",
+  "settings.shortcuts.reset.toast.title": "Atalhos redefinidos",
+  "settings.shortcuts.reset.toast.description": "Atalhos de teclado foram redefinidos para os padrões.",
+  "settings.shortcuts.conflict.title": "Atalho já em uso",
+  "settings.shortcuts.conflict.description": "{{keybind}} já está atribuído a {{titles}}.",
+  "settings.shortcuts.unassigned": "Não atribuído",
+  "settings.shortcuts.pressKeys": "Pressione teclas",
+  "settings.shortcuts.search.placeholder": "Buscar atalhos",
+  "settings.shortcuts.search.empty": "Nenhum atalho encontrado",
+
+  "settings.shortcuts.group.general": "Geral",
+  "settings.shortcuts.group.session": "Sessão",
+  "settings.shortcuts.group.navigation": "Navegação",
+  "settings.shortcuts.group.modelAndAgent": "Modelo e agente",
+  "settings.shortcuts.group.terminal": "Terminal",
+  "settings.shortcuts.group.prompt": "Prompt",
+
+  "settings.providers.title": "Provedores",
+  "settings.providers.description": "Configurações de provedores estarão disponíveis aqui.",
+  "settings.models.title": "Modelos",
+  "settings.models.description": "Configurações de modelos estarão disponíveis aqui.",
+  "settings.agents.title": "Agentes",
+  "settings.agents.description": "Configurações de agentes estarão disponíveis aqui.",
+  "settings.commands.title": "Comandos",
+  "settings.commands.description": "Configurações de comandos estarão disponíveis aqui.",
+  "settings.mcp.title": "MCP",
+  "settings.mcp.description": "Configurações de MCP estarão disponíveis aqui.",
+
+  "settings.permissions.title": "Permissões",
+  "settings.permissions.description": "Controle quais ferramentas o servidor pode usar por padrão.",
+  "settings.permissions.section.tools": "Ferramentas",
+  "settings.permissions.toast.updateFailed.title": "Falha ao atualizar permissões",
+
+  "settings.permissions.action.allow": "Permitir",
+  "settings.permissions.action.ask": "Perguntar",
+  "settings.permissions.action.deny": "Negar",
+
+  "settings.permissions.tool.read.title": "Ler",
+  "settings.permissions.tool.read.description": "Ler um arquivo (corresponde ao caminho do arquivo)",
+  "settings.permissions.tool.edit.title": "Editar",
+  "settings.permissions.tool.edit.description":
+    "Modificar arquivos, incluindo edições, escritas, patches e multi-edições",
+  "settings.permissions.tool.glob.title": "Glob",
+  "settings.permissions.tool.glob.description": "Corresponder arquivos usando padrões glob",
+  "settings.permissions.tool.grep.title": "Grep",
+  "settings.permissions.tool.grep.description": "Buscar conteúdo de arquivos usando expressões regulares",
+  "settings.permissions.tool.list.title": "Listar",
+  "settings.permissions.tool.list.description": "Listar arquivos dentro de um diretório",
+  "settings.permissions.tool.bash.title": "Bash",
+  "settings.permissions.tool.bash.description": "Executar comandos shell",
+  "settings.permissions.tool.task.title": "Tarefa",
+  "settings.permissions.tool.task.description": "Lançar sub-agentes",
+  "settings.permissions.tool.skill.title": "Habilidade",
+  "settings.permissions.tool.skill.description": "Carregar uma habilidade por nome",
+  "settings.permissions.tool.lsp.title": "LSP",
+  "settings.permissions.tool.lsp.description": "Executar consultas de servidor de linguagem",
+  "settings.permissions.tool.todoread.title": "Ler Tarefas",
+  "settings.permissions.tool.todoread.description": "Ler a lista de tarefas",
+  "settings.permissions.tool.todowrite.title": "Escrever Tarefas",
+  "settings.permissions.tool.todowrite.description": "Atualizar a lista de tarefas",
+  "settings.permissions.tool.webfetch.title": "Buscar Web",
+  "settings.permissions.tool.webfetch.description": "Buscar conteúdo de uma URL",
+  "settings.permissions.tool.websearch.title": "Pesquisa Web",
+  "settings.permissions.tool.websearch.description": "Pesquisar na web",
+  "settings.permissions.tool.codesearch.title": "Pesquisa de Código",
+  "settings.permissions.tool.codesearch.description": "Pesquisar código na web",
+  "settings.permissions.tool.external_directory.title": "Diretório Externo",
+  "settings.permissions.tool.external_directory.description": "Acessar arquivos fora do diretório do projeto",
+  "settings.permissions.tool.doom_loop.title": "Loop Infinito",
+  "settings.permissions.tool.doom_loop.description": "Detectar chamadas de ferramentas repetidas com entrada idêntica",
+
+  "session.delete.failed.title": "Falha ao excluir sessão",
+  "session.delete.title": "Excluir sessão",
+  "session.delete.confirm": 'Excluir sessão "{{name}}"?',
+  "session.delete.button": "Excluir sessão",
+
+  "workspace.new": "Novo espaço de trabalho",
+  "workspace.type.local": "local",
+  "workspace.type.sandbox": "sandbox",
+  "workspace.create.failed.title": "Falha ao criar espaço de trabalho",
+  "workspace.delete.failed.title": "Falha ao excluir espaço de trabalho",
+  "workspace.resetting.title": "Redefinindo espaço de trabalho",
+  "workspace.resetting.description": "Isso pode levar um minuto.",
+  "workspace.reset.failed.title": "Falha ao redefinir espaço de trabalho",
+  "workspace.reset.success.title": "Espaço de trabalho redefinido",
+  "workspace.reset.success.description": "Espaço de trabalho agora corresponde ao branch padrão.",
+  "workspace.status.checking": "Verificando alterações não mescladas...",
+  "workspace.status.error": "Não foi possível verificar o status do git.",
+  "workspace.status.clean": "Nenhuma alteração não mesclada detectada.",
+  "workspace.status.dirty": "Alterações não mescladas detectadas neste espaço de trabalho.",
+  "workspace.delete.title": "Excluir espaço de trabalho",
+  "workspace.delete.confirm": 'Excluir espaço de trabalho "{{name}}"?',
+  "workspace.delete.button": "Excluir espaço de trabalho",
+  "workspace.reset.title": "Redefinir espaço de trabalho",
+  "workspace.reset.confirm": 'Redefinir espaço de trabalho "{{name}}"?',
+  "workspace.reset.button": "Redefinir espaço de trabalho",
+  "workspace.reset.archived.none": "Nenhuma sessão ativa será arquivada.",
+  "workspace.reset.archived.one": "1 sessão será arquivada.",
+  "workspace.reset.archived.many": "{{count}} sessões serão arquivadas.",
+  "workspace.reset.note": "Isso redefinirá o espaço de trabalho para corresponder ao branch padrão.",
+}

+ 1 - 0
packages/app/src/i18n/da.ts

@@ -288,6 +288,7 @@ export const dict = {
   "language.pl": "Polsk",
   "language.pl": "Polsk",
   "language.ar": "Arabisk",
   "language.ar": "Arabisk",
   "language.no": "Norsk",
   "language.no": "Norsk",
+  "language.br": "Portugisisk (Brasilien)",
 
 
   "toast.language.title": "Sprog",
   "toast.language.title": "Sprog",
   "toast.language.description": "Skiftede til {{language}}",
   "toast.language.description": "Skiftede til {{language}}",

+ 1 - 0
packages/app/src/i18n/de.ts

@@ -293,6 +293,7 @@ export const dict = {
   "language.pl": "Polnisch",
   "language.pl": "Polnisch",
   "language.ar": "Arabisch",
   "language.ar": "Arabisch",
   "language.no": "Norwegisch",
   "language.no": "Norwegisch",
+  "language.br": "Portugiesisch (Brasilien)",
 
 
   "toast.language.title": "Sprache",
   "toast.language.title": "Sprache",
   "toast.language.description": "Zu {{language}} gewechselt",
   "toast.language.description": "Zu {{language}} gewechselt",

+ 1 - 0
packages/app/src/i18n/en.ts

@@ -308,6 +308,7 @@ export const dict = {
   "language.pl": "Polish",
   "language.pl": "Polish",
   "language.ar": "Arabic",
   "language.ar": "Arabic",
   "language.no": "Norwegian",
   "language.no": "Norwegian",
+  "language.br": "Portuguese (Brazil)",
 
 
   "toast.language.title": "Language",
   "toast.language.title": "Language",
   "toast.language.description": "Switched to {{language}}",
   "toast.language.description": "Switched to {{language}}",

+ 1 - 0
packages/app/src/i18n/es.ts

@@ -288,6 +288,7 @@ export const dict = {
   "language.pl": "Polaco",
   "language.pl": "Polaco",
   "language.ar": "Árabe",
   "language.ar": "Árabe",
   "language.no": "Noruego",
   "language.no": "Noruego",
+  "language.br": "Portugués (Brasil)",
 
 
   "toast.language.title": "Idioma",
   "toast.language.title": "Idioma",
   "toast.language.description": "Cambiado a {{language}}",
   "toast.language.description": "Cambiado a {{language}}",

+ 1 - 0
packages/app/src/i18n/fr.ts

@@ -288,6 +288,7 @@ export const dict = {
   "language.pl": "Polonais",
   "language.pl": "Polonais",
   "language.ar": "Arabe",
   "language.ar": "Arabe",
   "language.no": "Norvégien",
   "language.no": "Norvégien",
+  "language.br": "Portugais (Brésil)",
 
 
   "toast.language.title": "Langue",
   "toast.language.title": "Langue",
   "toast.language.description": "Passé à {{language}}",
   "toast.language.description": "Passé à {{language}}",

+ 1 - 0
packages/app/src/i18n/ja.ts

@@ -286,6 +286,7 @@ export const dict = {
   "language.pl": "ポーランド語",
   "language.pl": "ポーランド語",
   "language.ar": "アラビア語",
   "language.ar": "アラビア語",
   "language.no": "ノルウェー語",
   "language.no": "ノルウェー語",
+  "language.br": "ポルトガル語(ブラジル)",
 
 
   "toast.language.title": "言語",
   "toast.language.title": "言語",
   "toast.language.description": "{{language}}に切り替えました",
   "toast.language.description": "{{language}}に切り替えました",

+ 1 - 0
packages/app/src/i18n/ko.ts

@@ -290,6 +290,7 @@ export const dict = {
   "language.pl": "폴란드어",
   "language.pl": "폴란드어",
   "language.ar": "아랍어",
   "language.ar": "아랍어",
   "language.no": "노르웨이어",
   "language.no": "노르웨이어",
+  "language.br": "포르투갈어 (브라질)",
 
 
   "toast.language.title": "언어",
   "toast.language.title": "언어",
   "toast.language.description": "{{language}}(으)로 전환됨",
   "toast.language.description": "{{language}}(으)로 전환됨",

+ 1 - 0
packages/app/src/i18n/no.ts

@@ -308,6 +308,7 @@ export const dict = {
   "language.pl": "Polsk",
   "language.pl": "Polsk",
   "language.ar": "Arabisk",
   "language.ar": "Arabisk",
   "language.no": "Norsk",
   "language.no": "Norsk",
+  "language.br": "Portugisisk (Brasil)",
 
 
   "toast.language.title": "Språk",
   "toast.language.title": "Språk",
   "toast.language.description": "Byttet til {{language}}",
   "toast.language.description": "Byttet til {{language}}",

+ 1 - 0
packages/app/src/i18n/pl.ts

@@ -304,6 +304,7 @@ export const dict = {
   "language.ru": "Rosyjski",
   "language.ru": "Rosyjski",
   "language.ar": "Arabski",
   "language.ar": "Arabski",
   "language.no": "Norweski",
   "language.no": "Norweski",
+  "language.br": "Portugalski (Brazylia)",
 
 
   "toast.language.title": "Język",
   "toast.language.title": "Język",
   "toast.language.description": "Przełączono na {{language}}",
   "toast.language.description": "Przełączono na {{language}}",

+ 1 - 0
packages/app/src/i18n/ru.ts

@@ -304,6 +304,7 @@ export const dict = {
   "language.ru": "Русский",
   "language.ru": "Русский",
   "language.ar": "Арабский",
   "language.ar": "Арабский",
   "language.no": "Норвежский",
   "language.no": "Норвежский",
+  "language.br": "Португальский (Бразилия)",
 
 
   "toast.language.title": "Язык",
   "toast.language.title": "Язык",
   "toast.language.description": "Переключено на {{language}}",
   "toast.language.description": "Переключено на {{language}}",

+ 1 - 0
packages/app/src/i18n/zh.ts

@@ -286,6 +286,7 @@ export const dict = {
   "language.pl": "波兰语",
   "language.pl": "波兰语",
   "language.ar": "阿拉伯语",
   "language.ar": "阿拉伯语",
   "language.no": "挪威语",
   "language.no": "挪威语",
+  "language.br": "葡萄牙语(巴西)",
 
 
   "toast.language.title": "语言",
   "toast.language.title": "语言",
   "toast.language.description": "已切换到{{language}}",
   "toast.language.description": "已切换到{{language}}",

+ 1 - 0
packages/app/src/i18n/zht.ts

@@ -282,6 +282,7 @@ export const dict = {
   "language.ru": "俄語",
   "language.ru": "俄語",
   "language.ar": "阿拉伯語",
   "language.ar": "阿拉伯語",
   "language.no": "挪威語",
   "language.no": "挪威語",
+  "language.br": "葡萄牙語(巴西)",
 
 
   "toast.language.title": "語言",
   "toast.language.title": "語言",
   "toast.language.description": "已切換到 {{language}}",
   "toast.language.description": "已切換到 {{language}}",

+ 92 - 0
packages/ui/src/i18n/br.ts

@@ -0,0 +1,92 @@
+export const dict = {
+  "ui.sessionReview.title": "Alterações da sessão",
+  "ui.sessionReview.diffStyle.unified": "Unificado",
+  "ui.sessionReview.diffStyle.split": "Dividido",
+  "ui.sessionReview.expandAll": "Expandir tudo",
+  "ui.sessionReview.collapseAll": "Recolher tudo",
+
+  "ui.sessionTurn.steps.show": "Mostrar passos",
+  "ui.sessionTurn.steps.hide": "Ocultar passos",
+  "ui.sessionTurn.summary.response": "Resposta",
+  "ui.sessionTurn.diff.showMore": "Mostrar mais alterações ({{count}})",
+
+  "ui.sessionTurn.retry.retrying": "tentando novamente",
+  "ui.sessionTurn.retry.inSeconds": "em {{seconds}}s",
+
+  "ui.sessionTurn.status.delegating": "Delegando trabalho",
+  "ui.sessionTurn.status.planning": "Planejando próximos passos",
+  "ui.sessionTurn.status.gatheringContext": "Coletando contexto",
+  "ui.sessionTurn.status.searchingCodebase": "Pesquisando no código",
+  "ui.sessionTurn.status.searchingWeb": "Pesquisando na web",
+  "ui.sessionTurn.status.makingEdits": "Fazendo edições",
+  "ui.sessionTurn.status.runningCommands": "Executando comandos",
+  "ui.sessionTurn.status.thinking": "Pensando",
+  "ui.sessionTurn.status.thinkingWithTopic": "Pensando - {{topic}}",
+  "ui.sessionTurn.status.gatheringThoughts": "Organizando pensamentos",
+  "ui.sessionTurn.status.consideringNextSteps": "Considerando próximos passos",
+
+  "ui.messagePart.diagnostic.error": "Erro",
+  "ui.messagePart.title.edit": "Editar",
+  "ui.messagePart.title.write": "Escrever",
+  "ui.messagePart.option.typeOwnAnswer": "Digite sua própria resposta",
+  "ui.messagePart.review.title": "Revise suas respostas",
+
+  "ui.list.loading": "Carregando",
+  "ui.list.empty": "Nenhum resultado",
+  "ui.list.clearFilter": "Limpar filtro",
+  "ui.list.emptyWithFilter.prefix": "Nenhum resultado para",
+  "ui.list.emptyWithFilter.suffix": "",
+
+  "ui.messageNav.newMessage": "Nova mensagem",
+
+  "ui.textField.copyToClipboard": "Copiar para área de transferência",
+  "ui.textField.copied": "Copiado",
+
+  "ui.imagePreview.alt": "Visualização de imagem",
+
+  "ui.tool.read": "Ler",
+  "ui.tool.list": "Listar",
+  "ui.tool.glob": "Glob",
+  "ui.tool.grep": "Grep",
+  "ui.tool.webfetch": "Buscar Web",
+  "ui.tool.shell": "Shell",
+  "ui.tool.patch": "Patch",
+  "ui.tool.todos": "Tarefas",
+  "ui.tool.todos.read": "Ler tarefas",
+  "ui.tool.questions": "Perguntas",
+  "ui.tool.agent": "Agente {{type}}",
+
+  "ui.common.file.one": "arquivo",
+  "ui.common.file.other": "arquivos",
+  "ui.common.question.one": "pergunta",
+  "ui.common.question.other": "perguntas",
+
+  "ui.common.add": "Adicionar",
+  "ui.common.cancel": "Cancelar",
+  "ui.common.confirm": "Confirmar",
+  "ui.common.dismiss": "Descartar",
+  "ui.common.close": "Fechar",
+  "ui.common.next": "Próximo",
+  "ui.common.submit": "Enviar",
+
+  "ui.permission.deny": "Negar",
+  "ui.permission.allowAlways": "Permitir sempre",
+  "ui.permission.allowOnce": "Permitir uma vez",
+
+  "ui.message.expand": "Expandir mensagem",
+  "ui.message.collapse": "Recolher mensagem",
+  "ui.message.copy": "Copiar",
+  "ui.message.copied": "Copiado!",
+  "ui.message.attachment.alt": "anexo",
+
+  "ui.patch.action.deleted": "Excluído",
+  "ui.patch.action.created": "Criado",
+  "ui.patch.action.moved": "Movido",
+  "ui.patch.action.patched": "Aplicado patch",
+
+  "ui.question.subtitle.answered": "{{count}} respondidas",
+  "ui.question.answer.none": "(sem resposta)",
+  "ui.question.review.notAnswered": "(não respondida)",
+  "ui.question.multiHint": "(selecione todas que se aplicam)",
+  "ui.question.custom.placeholder": "Digite sua resposta...",
+}