feat(i18n): add Português (Brasil) (pt-BR) locale (#3347)

## Summary

Adds **Português (Brasil)** (`pt-BR`) as a supported locale:

- Selectable as **Translation target language** (project settings) and
as the dashboard / terminal UI language.
- Full machine-drafted catalogs (`app`, `cli`, `common`), disclosed in
`packages/i18n/locales/TRANSLATION_STATUS.md` following the pattern
#1352 established — reviewed for glossary/register consistency (0.18%
untranslated, matching only keys that are empty in `en`), but
native-speaker corrections are welcome.
- Brazilian Portuguese content-language detection (accent-stripped
stopword list — the scorer strips diacritics before matching, so
accented entries never match; `com`/`mais` deliberately omitted to avoid
bare-domain `.com` and French collisions, with regression tests for both
directions).
- `pt`/`pt-PT` browser and environment locales resolve to `pt-BR` on all
three detection paths (`FALLBACK_LNG` routing plus a `pt` branch in
`normalizeToSupportedLocale`, mirroring the existing `zh` handling).
- `README.pt-BR.md` + switcher links in all READMEs, docs updates
(`settings-reference`, `cli-reference`, `i18n-contributing`, `--lang`
help text), changeset (`minor`).

Drive-by fixes bundled: `TRANSLATION_STATUS.md` was missing the `ko`
row; the LanguageSelector endonym test was missing `한국어`;
`docs/i18n-contributing.md` now names the two compile-enforced display
maps (`LOCALE_LABELS`, `localeDisplayName`) a new locale must update;
the `--lang` CLI help text no longer drifts from its validator.

## Test plan

- `pnpm i18n:status` (key parity gate) green; catalogs are
`i18n:sync`-idempotent.
- Updated/extended suites: core `locale-settings`, i18n
`config`/`parity`/`db-banner-catalog`/`i18n-gate-coverage`, dashboard
`useLanguage`/`LanguageSelector`/`GeneralSection.importTranslate`/`detectContentLanguage`
(incl. new pt-BR detection + bare-domain regression tests), CLI
`settings`.
- `pnpm verify:fast` (typecheck, build, boot smoke), `pnpm lint`, `pnpm
check:changesets`, and the bounded `pnpm test` lane all green locally
(the three `test:pg-gate` files fail locally only for lack of a Postgres
instance; they fail identically on clean `main`).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added Brazilian Portuguese (Português (Brasil)) across the dashboard,
terminal interface, settings, and translation tools.
  * Added Portuguese translations for common interface and CLI content.
* Added automatic Portuguese language detection, locale normalization,
and fallback support.
* Added a Portuguese (Brazil) README with product, setup, and usage
documentation.

* **Documentation**
* Updated language selectors, CLI references, settings documentation,
and translation guidance.
  * Added Portuguese README links to translated documentation.
  * Added French to the documented dashboard language options.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
This commit is contained in:
Victor Canô
2026-08-09 20:33:16 -03:00
committed by GitHub
parent 7775000bfd
commit a09e0cb87f
34 changed files with 10574 additions and 28 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": minor
---
summary: Add Português (Brasil) (pt-BR) as a dashboard, terminal UI, and translation target language.
category: feature
dev: Adds `pt-BR` to `SUPPORTED_LOCALES` with machine-drafted catalogs (flagged in packages/i18n/locales/TRANSLATION_STATUS.md) and Portuguese content-language detection stopwords.

View File

@@ -10,7 +10,7 @@ Describe lo que quieres — un equipo de agentes de IA lo **planifica, construye
[**runfusion.ai →**](https://runfusion.ai) · [Docs](./docs/README.md) · [GitHub](https://github.com/Runfusion/Fusion) · [npm](https://www.npmjs.com/package/@runfusion/fusion) · [Discord](https://discord.gg/ksrfuy7WYR)
[English](./README.md) · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · **Español** · [한국어](./README.ko.md)
[English](./README.md) · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · **Español** · [한국어](./README.ko.md) · [Português (Brasil)](./README.pt-BR.md)
*Esta es una traducción automática; el README en inglés es el documento canónico.*

View File

@@ -10,7 +10,7 @@ Décrivez ce que vous voulez — une équipe d'agents IA le **planifie, le const
[**runfusion.ai →**](https://runfusion.ai) · [Docs](./docs/README.md) · [GitHub](https://github.com/Runfusion/Fusion) · [npm](https://www.npmjs.com/package/@runfusion/fusion) · [Discord](https://discord.gg/ksrfuy7WYR)
[English](./README.md) · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · **Français** · [Español](./README.es.md) · [한국어](./README.ko.md)
[English](./README.md) · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · **Français** · [Español](./README.es.md) · [한국어](./README.ko.md) · [Português (Brasil)](./README.pt-BR.md)
*Traduction automatique — le README anglais fait foi.*

View File

@@ -10,7 +10,7 @@
[**runfusion.ai →**](https://runfusion.ai) · [문서](./docs/README.md) · [GitHub](https://github.com/Runfusion/Fusion) · [npm](https://www.npmjs.com/package/@runfusion/fusion) · [Discord](https://discord.gg/ksrfuy7WYR)
[English](./README.md) · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · [Español](./README.es.md) · **한국어**
[English](./README.md) · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · [Español](./README.es.md) · **한국어** · [Português (Brasil)](./README.pt-BR.md)
*이 문서는 기계 번역본입니다. 공식 원본은 [영문 README](./README.md)를 참조하세요.*

View File

@@ -10,7 +10,7 @@ Describe what you want — a team of AI agents **plans, builds, reviews, and shi
[**runfusion.ai →**](https://runfusion.ai) · [Docs](./docs/README.md) · [GitHub](https://github.com/Runfusion/Fusion) · [npm](https://www.npmjs.com/package/@runfusion/fusion) · [Discord](https://discord.gg/ksrfuy7WYR)
**English** · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · [Español](./README.es.md) · [한국어](./README.ko.md)
**English** · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · [Español](./README.es.md) · [한국어](./README.ko.md) · [Português (Brasil)](./README.pt-BR.md)
[![License: MIT](https://img.shields.io/badge/license-MIT-3fb950.svg)](./LICENSE)
[![npm](https://img.shields.io/npm/v/@runfusion/fusion.svg?color=58a6ff)](https://www.npmjs.com/package/@runfusion/fusion)

697
README.pt-BR.md Normal file
View File

@@ -0,0 +1,697 @@
<div align="center">
# <img src="./demo/assets/fusion-logo-orange.svg" alt="" width="34" align="center" /> Fusion
### De ideia bruta a código em produção — automaticamente.
### 🏭 Uma fábrica de software, operada por um orquestrador multiagente.
Descreva o que você quer — uma equipe de agentes de IA **planeja, constrói, revisa e entrega** para você. O Fusion é a sua fábrica de software: uma linha de montagem para código que opera entre tarefas, agentes, missões, git, arquivos e worktrees, com qualquer modelo, local ou na nuvem.
[**runfusion.ai →**](https://runfusion.ai) · [Docs](./docs/README.md) · [GitHub](https://github.com/Runfusion/Fusion) · [npm](https://www.npmjs.com/package/@runfusion/fusion) · [Discord](https://discord.gg/ksrfuy7WYR)
[English](./README.md) · [简体中文](./README.zh-CN.md) · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · [Español](./README.es.md) · [한국어](./README.ko.md) · **Português (Brasil)**
*Esta é uma tradução automática; o README em inglês é o documento canônico.*
[![License: MIT](https://img.shields.io/badge/license-MIT-3fb950.svg)](./LICENSE)
[![npm](https://img.shields.io/npm/v/@runfusion/fusion.svg?color=58a6ff)](https://www.npmjs.com/package/@runfusion/fusion)
[![Discord](https://img.shields.io/badge/Discord-join-5865F2?logo=discord&logoColor=white)](https://discord.gg/ksrfuy7WYR)
![Status](https://img.shields.io/badge/status-early%20preview-d29922.svg)
![Shipping](https://img.shields.io/badge/shipping-weekly-bc8cff.svg)
<br />
<img src="./demo/assets/fusion-reel.gif" alt="Demonstração do Fusion: de ideia bruta a código em produção" width="900" />
<br />
<br />
<a href="https://runfusion.ai">
<img src="https://runfusion.ai/fusion-dashboard.png" alt="Painel do Fusion: colunas kanban Planejamento, A Fazer, Em Andamento, Em Revisão e Concluído com cartões de tarefas ativas" width="900" />
</a>
</div>
---
## Todo o seu ambiente de desenvolvimento. Em uma única tela.
Descreva uma tarefa em linguagem natural. Um agente de planejamento lê seu projeto, entende o contexto e escreve um plano completo em `PROMPT.md` — etapas, escopo de arquivos, critérios de aceitação. Depois o Fusion planeja, revisa, executa e revisa novamente, em um worktree de git isolado, com um gate de aprovação humana onde você quiser.
Um quadro. Controlado de qualquer lugar. Laptop, Mac mini, servidor Linux, VM na nuvem, celular — tudo conectado.
> Como o Trello, mas suas tarefas são especificadas, executadas e entregues por IA. Construído sobre o excelente trabalho de [dustinbyrne/kb](https://github.com/dustinbyrne/kb).
---
## Início rápido
**Zero instalação, direto do npm:**
```bash
npx runfusion.ai
```
Isso abre o painel. Os subcomandos são encaminhados diretamente: `npx runfusion.ai task create "fix X"`, `npx runfusion.ai --help`, etc. (Ou de forma explícita: `npx @runfusion/fusion dashboard`.)
**Instalador em uma linha** (macOS e Linux — escolhe o Homebrew automaticamente, com fallback para npm):
```bash
curl -fsSL https://runfusion.ai/install.sh | sh
fusion dashboard
```
**Homebrew** (macOS e Linux):
```bash
brew install runfusion/fusion/fusion
fusion dashboard # ou: fn dashboard
```
A instalação totalmente qualificada faz auto-tap e, no Homebrew 6.0+, confia somente na fórmula do Fusion. Se você já executou `brew tap runfusion/fusion` e a instalação pelo nome curto falhar com "untrusted tap", execute `brew trust --formula runfusion/fusion/fusion` e depois `brew install fusion`.
**npm global**:
```bash
npm install -g @runfusion/fusion
fn dashboard # ou: fusion dashboard
```
**A partir de um clone** (para desenvolvimento):
```bash
pnpm dev dashboard
```
Depois, clique na URL `Open:` impressa no terminal. Ela embute um token de
portador (`http://localhost:4040/?token=fn_...`) que o navegador captura no
`localStorage` na primeira visita e reutiliza automaticamente depois disso.
No lado do servidor, o Fusion agora persiste o token do painel/daemon em
`~/.fusion/settings.json` na primeira execução autenticada e o reutiliza nas
próximas inicializações, a menos que você o substitua (`--token`,
`FUSION_DASHBOARD_TOKEN`, `FUSION_DAEMON_TOKEN`) ou desabilite a autenticação
com `--no-auth`. Veja
[Referência da CLI → fn dashboard → Autenticação](./docs/cli-reference.md#fn-dashboard)
para a precedência completa e as opções de redefinição/revogação.
### Configuração inicial
No primeiro lançamento, o Fusion abre o **assistente de onboarding** com três etapas guiadas:
1. **Configuração de IA** — Use uma lista simplificada de provedores para início rápido (provedores recomendados mais quaisquer provedores já conectados), depois expanda **Configurações avançadas de provedor** somente se precisar de provedores adicionais ou detalhes de configuração. Você só precisa de um provedor para começar. As entradas de provedor obsoletas Google Gemini CLI / Antigravity ficam intencionalmente ocultas; os caminhos de chave de API do Google/Gemini, Google Generative AI, Vertex e Cloud Code continuam suportados.
2. **GitHub (Opcional)** — Conecte o GitHub para importar issues e gerenciar PRs
3. **Primeira Tarefa** — Crie sua primeira tarefa ou importe do GitHub (se nenhum projeto estiver ativo, o onboarding primeiro pede que você registre/selecione um diretório de projeto)
O assistente pode ser **dispensado e não é bloqueante** — clique em **Pular por agora** para usar o painel imediatamente. Ative-o novamente depois em **Configurações → Autenticação → Reabrir guia de onboarding**.
### Mobile
Para o fluxo de trabalho com Capacitor + PWA, veja [MOBILE.md](./MOBILE.md).
---
## O fluxo
```
① Describe ② Planning ③ The board ④ Isolated worktree
───────────── ───────────── ───────────── ─────────────────────
"Add dark mode → Agent writes → Plan → Review → → fusion/FN-123 branch
toggle to PROMPT.md Execute → Review concurrent, zero
settings panel" (steps, scope, (per step, until file conflicts
acceptance) done)
```
### Veja cada etapa, antes do merge
<div align="center">
<img src="https://runfusion.ai/screenshot-task-detail.png" alt="Detalhe de tarefa do Fusion: etapas do fluxo de trabalho visíveis em uma tarefa em andamento, com diffs e alterações de arquivos" width="820" />
</div>
Cada tarefa mostra seu plano, suas revisões, seus diffs e suas alterações de arquivo em tempo real. Entre em uma tarefa ativa e ajuste a direção, reforce as restrições, pause ou reformule o prompt.
---
## O que o torna diferente
<!--
FNXC:Docs 2026-07-15-00:00:
README must surface PostgreSQL-default storage and recently shipped operator surfaces so the public front door matches the shipped product. Legacy SQLite is a one-time migration input only; feature claims below remain grounded in release notes and linked product docs rather than new showcase media.
-->
| | |
|---|---|
| 🧠 **Planejamento com IA** | Descreva uma tarefa em linguagem natural. Os agentes de planejamento a transformam em um plano `PROMPT.md` com etapas, escopo de arquivos e critérios de aceitação. |
| 🔁 **Fluxos de trabalho selecionáveis** | Os fluxos integrados cobrem codificação, correções rápidas, trabalho com revisão intensa, execução passo a passo, Compound Engineering habilitado por plugin e fragmentos de ciclo de vida de PR. Escolha um fluxo de trabalho por tarefa ou crie fluxos personalizados no [Editor de Fluxo de Trabalho](./docs/workflow-editor.md). |
| 🛡️ **Supervisão do planejador** | O nível de supervisão por tarefa ou por fluxo de trabalho (`off` / `observe` / `steer` / `autonomous`) determina o quanto um supervisor de planejamento acompanha e intervém — ações de merge/PR e ações destrutivas sempre exigem confirmação humana explícita. Veja a [Referência de Configurações](./docs/settings-reference.md#workflow-settings) e o [Guia do Painel](./docs/dashboard-guide.md). |
| 🌳 **Isolamento de worktree** | Cada tarefa roda em sua própria branch e worktree (`fusion/{task-id}`). Tarefas em paralelo. Zero conflitos. Delegação opcional ao [worktrunk](https://github.com/max-sixty/worktrunk) via [`worktrunk.enabled`](./docs/settings-reference.md#worktree-backend-settings) (veja a [abstração WorktreeBackend](./docs/architecture.md#worktreebackend-abstraction)). |
| 🗄️ **PostgreSQL por padrão** | O Fusion usa PostgreSQL incorporado, sem configuração, para os metadados de execução locais. Arquivos SQLite legados servem apenas como entrada de migração única; use um banco de dados externo compartilhado para configurações de [múltiplos projetos e nós](./docs/multi-project.md). ([Armazenamento](./docs/storage.md)) |
| ⚡ **Controles inteligentes de merge** | Passou por todos os gates? O Fusion faz squash-merge e segue em frente. Ative aprovação manual onde quiser, herde o padrão global de auto-merge ao vivo, ou defina substituições explícitas de auto/manual por tarefa. |
| 🛰️ **Malha multi-nó** | Laptop, Mac mini, servidor Linux, VM na nuvem, celular — tudo sincronizado. Desktop, mobile, web. |
| 🧩 **Qualquer modelo** | Anthropic, OpenAI, Ollama, Google Generative AI, Z.ai, Kimi K3, runtimes locais e [provedores personalizados](./docs/dashboard-guide.md#custom-providers) definidos pelo usuário. Local e nuvem coexistem, com faixas de modelo/fallback do fluxo de trabalho configuráveis por projeto. |
| 🏢 **Empresas de agentes** | Importe equipes prontas — mais de 440 agentes em 16 empresas — e execute-as de forma autônoma por semanas. |
| 📬 **Mensagens entre agentes** | Caixa de mensagens integrada entre agentes. Delegue, esclareça, coordene; agentes com papel de engenheiro podem optar pela captura automática de backlog quando você quiser ajuda de implementação além da captação apenas por executores. |
| 🗨️ **Chat com agentes** | Chat direto, chat de tarefa que narra proativamente o progresso das etapas, falhas e resultados de revisão, anexos, cartões de pergunta no chat, streams retomáveis, e Salas de Chat multiagente experimentais em que membros mencionados respondem diretamente e membros ambientes podem entrar até um limite. ([Documentação de chat](./docs/dashboard-guide.md#chat-view)) |
| 🗺️ **Missões** | Planejamento hierárquico (Missão → Marco → Fatia → Funcionalidade → Tarefa) com piloto automático e contratos de validação. |
| 🔬 **Pesquisa** | Execuções de pesquisa limitadas com busca na web, GitHub, documentação local e síntese por LLM (além do suporte nativo do runtime a WebSearch/WebFetch nos fluxos de planejamento e síntese, quando disponível). Transforme descobertas em tarefas. ([Docs](./docs/research.md)) |
| 🧪 **Autoaperfeiçoamento** | Os agentes refletem sobre o próprio resultado e atualizam seus prompts à medida que aprendem sua base de código. |
| 🔓 **Código aberto. MIT.** | Sem dependência de fornecedor. Rode no seu próprio hardware. Lançamentos semanais. |
---
## Veja em ação
<!--
FNXC:Docs 2026-06-21-19:55:
README must lead with a smaller wordmark and a visual showcase of the latest surfaces (Command Center, selectable workflows, agent chat, multi-agent chat rooms, agent mail) so the value lands fast.
Each feature pairs a short looping GIF with value copy; Command Center additionally carries real fleet stats, the token/productivity/team graph trio, and the 70+-theme grid (incl. shadcn light/mono/orange/black) to make the data pop.
Media lives in demo/assets/ (committed, GitHub-inline GIFs); stat numbers are sourced from a live seeded fleet — refresh them if the captures are re-shot.
Each feature keeps its original Tokyo Night capture and adds a Shadcn Light + Shadcn Dark Gray + Ember trio; the theme showcase is split into a light-themes grid and a dark-themes grid. Workflow GIFs feature the Stepwise coding graph with node-level zoom/pan.
-->
As superfícies mais recentes do Fusion, em resumo — o quadro ao vivo, sua equipe de agentes, controle de missão, fluxos de trabalho visuais, chat com agentes, salas multiagente e correio entre agentes.
### 📋 O quadro e sua equipe de agentes — ao vivo, de uma frota real
<div align="center">
<img src="./demo/assets/dashboard-tokyo.png" alt="Quadro do Fusion: colunas Planejamento, A Fazer, Em Andamento, Em Revisão e Concluído com cartões de tarefas ao vivo no tema Tokyo Night" width="900" />
</div>
Cada tarefa, cada coluna, cada etapa — ao vivo. Os cartões trazem links do GitHub, contagem de etapas, níveis de revisão e ações de promover/mover/arquivar. Mude para a visualização em **Grafo** para ver as dependências entre tarefas como um grafo de nós interativo:
<table>
<tr>
<td width="50%"><img src="./demo/assets/dashboard-tokyo.png" alt="Quadro do Fusion: colunas Planejamento, A Fazer, Em Andamento, Em Revisão e Concluído com cartões de tarefas ao vivo" /><br/><sub><b>Quadro</b> — colunas kanban</sub></td>
<td width="50%"><img src="./demo/assets/dashboard-graph.png" alt="Visualização em grafo do Fusion: grafo de dependências entre tarefas com nós conectados" /><br/><sub><b>Grafo</b> — mapa de dependências</sub></td>
</tr>
</table>
Aqui está a mesma frota com uma nova aparência no tema **Ember** (grafite escuro com um destaque laranja), ao lado da lista de **Agentes**:
<table>
<tr>
<td width="50%"><img src="./demo/assets/dashboard-ember.png" alt="Quadro do Fusion no tema Ember" /><br/><sub><b>Quadro — Ember</b></sub></td>
<td width="50%"><img src="./demo/assets/agents-tokyo.png" alt="Visualização de Agentes do Fusion: CEO, Product Manager, CTO e engenheiros com papéis e status de heartbeat" /><br/><sub><b>Agentes — Tokyo Night</b></sub></td>
</tr>
</table>
Importe uma equipe e cada agente aparece aqui — papel, cadeia de subordinação, heartbeat e participação de tokens. O menu suspenso de heartbeat de cada cartão de agente mostra **Desativado** quando o agendamento está persistido como desligado; escolha Desativado para pausar os heartbeats mantendo a cadência configurada, ou selecione um intervalo para reativá-los. A lista de **Agentes** no tema Ember:
<div align="center">
<img src="./demo/assets/agents-ember.png" alt="Visualização de Agentes do Fusion no tema Ember" width="900" />
</div>
### 🛰️ Command Center — controle de missão para sua frota de agentes
<div align="center">
<img src="./demo/assets/command-center.gif" alt="Command Center do Fusion: medidores de concorrência ao vivo, gráficos de tokens e telemetria da frota em várias abas" width="900" />
</div>
Uma única tela para tudo o que seus agentes estão fazendo. Ajuste a capacidade do agendador em tempo real, acompanhe o gasto de tokens por modelo ao vivo e comprove o valor com números concretos. A aba **Visão geral** abre com medidores e gráficos ao vivo:
<div align="center">
<img src="./demo/assets/command-center-overview.png" alt="Visão geral do Command Center do Fusion: medidores de concorrência, status do engine e gráficos da frota" width="900" />
</div>
Cada aba é uma lente diferente sobre a mesma frota ao vivo:
<table>
<tr>
<td width="33%"><img src="./demo/assets/command-center-tokens.png" alt="Gráficos de tokens por modelo, tendência de tokens e tokens ao longo do tempo" /><br/><sub><b>Tokens</b> — gasto por modelo, cache vs. entrada vs. saída, ao longo do tempo.</sub></td>
<td width="33%"><img src="./demo/assets/command-center-productivity.png" alt="Produtividade: commits, horas humanas economizadas, percentis de duração das tarefas e arquivos por linguagem" /><br/><sub><b>Produtividade</b> — resultados, percentis de duração, mix de linguagens.</sub></td>
<td width="33%"><img src="./demo/assets/command-center-team.png" alt="Organograma de agentes com participação de tokens e detalhamento de tokens por agente" /><br/><sub><b>Equipe</b> — organograma de agentes e participação de tokens por agente.</sub></td>
</tr>
<tr>
<td width="33%"><img src="./demo/assets/command-center-activity.png" alt="Atividade: gráficos de throughput de tarefas e linha do tempo de eventos" /><br/><sub><b>Atividade</b> — throughput de tarefas e linhas do tempo de eventos.</sub></td>
<td width="33%"><img src="./demo/assets/command-center-signals.png" alt="Sinais: detecção de anomalias e gráficos de sinais da frota" /><br/><sub><b>Sinais</b> — detecção de anomalias e saúde da frota.</sub></td>
<td width="33%"><img src="./demo/assets/command-center-tokens.png" alt="Aba do Command Center" /><br/><sub><b>Mais</b> — Ferramentas · Ecossistema · GitHub · Sistema · Confiabilidade.</sub></td>
</tr>
</table>
> Tokens · Ferramentas · Atividade · Produtividade · Equipe · Ecossistema · GitHub · Sinais · Sistema · Confiabilidade · Controle de missões — cada aba é uma lente diferente sobre a mesma frota ao vivo.
**A mesma frota, do seu jeito** — o Command Center (e todo o painel) muda de aparência ao vivo entre **mais de 70 temas de cor**, incluindo Cobalt, Clay e Moss. Aqui está nos temas Shadcn Light, Shadcn Dark Gray e Ember:
<table>
<tr>
<td width="33%"><img src="./demo/assets/command-center-light.gif" alt="Command Center no tema Shadcn Light" /><br/><sub><b>Shadcn Light</b></sub></td>
<td width="33%"><img src="./demo/assets/command-center-gray.gif" alt="Command Center no tema Shadcn Dark Gray" /><br/><sub><b>Shadcn Dark Gray</b></sub></td>
<td width="33%"><img src="./demo/assets/command-center-ember.gif" alt="Command Center no tema Ember" /><br/><sub><b>Ember</b></sub></td>
</tr>
</table>
<details>
<summary><b>Uma dúzia de temas claros e uma dúzia de temas escuros</b> (clique para expandir)</summary>
<br/>
<div align="center">
<img src="./demo/assets/command-center-themes-light.png" alt="Command Center em 12 temas de cor claros" width="900" />
<br/><br/>
<img src="./demo/assets/command-center-themes-dark.png" alt="Command Center em 12 temas de cor escuros" width="900" />
</div>
</details>
### 🔁 Fluxos de trabalho selecionáveis, criados visualmente
<div align="center">
<img src="./demo/assets/workflows.gif" alt="Editor de Fluxo de Trabalho do Fusion: alternando entre grafos de fluxo de trabalho integrados" width="820" />
</div>
A jornada de uma tarefa da ideia até o merge é um **fluxo de trabalho** — e é você quem escolhe e molda. Escolha um integrado (Coding, Quick fix, Review-heavy, Stepwise, PR lifecycle, Compound engineering e mais), inspecione seu grafo, depois duplique e personalize colunas, gates, faixas de modelo e política de revisão no [Editor de Fluxo de Trabalho](./docs/workflow-editor.md) visual. Sem necessidade de fazer fork do engine.
Aqui está o grafo **Stepwise coding** — planeje, execute e revise cada etapa antes da próxima — explorado nó a nó em Shadcn Light, Dark Gray e Ember:
<table>
<tr>
<td width="33%"><img src="./demo/assets/workflows-light.gif" alt="Grafo do fluxo de trabalho Stepwise coding em Shadcn Light, percorrendo os nós" /><br/><sub><b>Shadcn Light</b></sub></td>
<td width="33%"><img src="./demo/assets/workflows-gray.gif" alt="Grafo do fluxo de trabalho Stepwise coding em Shadcn Dark Gray, percorrendo os nós" /><br/><sub><b>Shadcn Dark Gray</b></sub></td>
<td width="33%"><img src="./demo/assets/workflows-ember.gif" alt="Grafo do fluxo de trabalho Stepwise coding em Ember, percorrendo os nós" /><br/><sub><b>Ember</b></sub></td>
</tr>
</table>
### 🗨️ Chat com agentes — converse com seus agentes, em pleno voo
<div align="center">
<img src="./demo/assets/agent-chat.gif" alt="Chat com agentes do Fusion: uma conversa em thread com um agente diagnosticando uma tarefa que falhou" width="900" />
</div>
Chat direto e chat por tarefa com qualquer agente, em qualquer modelo. Pergunte por que uma tarefa falhou, oriente uma abordagem, solte anexos, responda cartões de pergunta no chat e retome streams de onde parou — com renderização completa de markdown e código o tempo todo.
<table>
<tr>
<td width="50%"><img src="./demo/assets/agent-chat-light.png" alt="Thread de chat com agente em Shadcn Light" /><br/><sub><b>Shadcn Light</b></sub></td>
<td width="50%"><img src="./demo/assets/agent-chat-gray.png" alt="Thread de chat com agente em Shadcn Dark Gray" /><br/><sub><b>Shadcn Dark Gray</b></sub></td>
</tr>
</table>
### 👥 Salas de chat multiagente
<div align="center">
<img src="./demo/assets/chat-rooms.gif" alt="Sala de chat do Fusion: agentes CEO, Product Manager e CTO se coordenando em #leads" width="900" />
</div>
Coloque vários agentes em uma sala e deixe que se coordenem. Mencione um membro e ele responde diretamente; membros ambientes podem entrar na conversa até um limite. Aqui os agentes **CEO**, **Product Manager** e **CTO** alinham a responsabilidade pelas tarefas em `#leads` — sem nenhum humano no loop. ([Documentação de chat](./docs/dashboard-guide.md#chat-view))
<table>
<tr>
<td width="33%"><img src="./demo/assets/chat-rooms-light.gif" alt="Sala de chat multiagente em Shadcn Light" /><br/><sub><b>Shadcn Light</b></sub></td>
<td width="33%"><img src="./demo/assets/chat-rooms-gray.gif" alt="Sala de chat multiagente em Shadcn Dark Gray" /><br/><sub><b>Shadcn Dark Gray</b></sub></td>
<td width="33%"><img src="./demo/assets/chat-rooms-ember.gif" alt="Sala de chat multiagente em Ember" /><br/><sub><b>Ember</b></sub></td>
</tr>
</table>
### 📬 Correio dos agentes — uma caixa de entrada entre seus agentes
<div align="center">
<img src="./demo/assets/agent-mail.gif" alt="Caixa de mensagens do Fusion: mensagens entre agentes com resumos de triagem e aprovações" width="900" />
</div>
Uma caixa de mensagens integrada para delegação, esclarecimentos e transferências. Os agentes registram resumos de triagem, solicitam aprovações e coordenam o trabalho em toda a frota — com visualizações de Caixa de Entrada, Caixa de Saída, Agentes e Aprovações, para que você possa auditar cada troca.
<table>
<tr>
<td width="33%"><img src="./demo/assets/agent-mail-light.gif" alt="Caixa de mensagens de agentes em Shadcn Light" /><br/><sub><b>Shadcn Light</b></sub></td>
<td width="33%"><img src="./demo/assets/agent-mail-gray.gif" alt="Caixa de mensagens de agentes em Shadcn Dark Gray" /><br/><sub><b>Shadcn Dark Gray</b></sub></td>
<td width="33%"><img src="./demo/assets/agent-mail-ember.gif" alt="Caixa de mensagens de agentes em Ember" /><br/><sub><b>Ember</b></sub></td>
</tr>
</table>
### 📱 O Fusion é uma fábrica de IA no seu bolso
O quadro completo, o Command Center, missões, agentes e chat viajam com você — aplicativos nativos para **iOS** e **Android** (Capacitor), além de um PWA instalável. Inicie uma execução no seu laptop e guie-a a partir do seu celular.
<table>
<tr>
<td width="33%"><img src="./demo/assets/mobile-board.png" alt="Fusion mobile: quadro" /></td>
<td width="33%"><img src="./demo/assets/mobile-command-center.png" alt="Fusion mobile: Command Center" /></td>
<td width="33%"><img src="./demo/assets/mobile-missions.png" alt="Fusion mobile: missões" /></td>
</tr>
<tr>
<td width="33%"><img src="./demo/assets/mobile-agents.png" alt="Fusion mobile: agentes" /></td>
<td width="33%"><img src="./demo/assets/mobile-chat.png" alt="Fusion mobile: chat com agentes" /></td>
<td width="33%"><img src="./demo/assets/mobile-chat-list.png" alt="Fusion mobile: lista de chats" /></td>
</tr>
</table>
<sub>Veja [MOBILE.md](./MOBILE.md) para o fluxo de trabalho com Capacitor + PWA.</sub>
---
## Como funciona
```mermaid
graph TD
H((You)) -->|rough idea| T["Planning<br/><i>auto-planning</i>"]
T --> TD["Todo<br/><i>scheduled for execution</i>"]
TD --> IP["In Progress<br/><i>for each step:<br/>plan, review, execute, review</i>"]
subgraph IP["In Progress"]
direction TD
NS([Begin step]) --> P[Plan]
P --> R1{Review}
R1 -->|revise| P
R1 -->|approve| E[Execute]
E --> R2{Review}
R2 -->|revise| E
R2 -->|next step| NS
R2 -->|rethink| P
end
R2 -->|done| IR["In Review<br/><i>ready to merge,<br/>or auto-complete</i>"]
IR -->|direct squash merge<br/>or merged PR| D["Done"]
style H fill:#161b22,stroke:#8b949e,color:#e6edf3
style T fill:#2d2006,stroke:#d29922,color:#d29922
style TD fill:#0d2044,stroke:#58a6ff,color:#58a6ff
style IP fill:#1a0d2e,stroke:#bc8cff,color:#bc8cff
style P fill:#1a0d2e,stroke:#bc8cff,color:#e6edf3
style R1 fill:#1a0d2e,stroke:#bc8cff,color:#e6edf3
style E fill:#1a0d2e,stroke:#bc8cff,color:#e6edf3
style R2 fill:#1a0d2e,stroke:#bc8cff,color:#e6edf3
style NS fill:#1a0d2e,stroke:#bc8cff,color:#bc8cff
style IR fill:#0d2d16,stroke:#3fb950,color:#3fb950
style D fill:#1a1a1a,stroke:#8b949e,color:#8b949e
```
Tarefas com dependências são processadas sequencialmente. Tarefas independentes rodam em paralelo. Opcionalmente, exija aprovação manual antes que as tarefas passem de Planejamento para A Fazer (configuração `requirePlanApproval`).
---
## Visão geral do fluxo de trabalho
<!--
FNXC:Docs 2026-06-16-23:10:
Fusion now exposes workflow selection and authoring as public product surfaces, so the README must explain the high-level lifecycle and link to the canonical Workflow Steps and Workflow Editor docs instead of duplicating editor internals here.
-->
Os fluxos de trabalho do Fusion definem como uma tarefa avança da ideia até a entrega. O caminho de codificação padrão ainda é o já conhecido ciclo **Plan/Triage → Execute → Workflow steps → Review → Merge**, mas agora a política vive em um fluxo de trabalho selecionável, em vez de ser apenas um comportamento fixo no engine.
- **Selecione por tarefa:** escolha um fluxo de trabalho nos controles de fluxo de trabalho da tarefa/quadro no painel, ou atribua um via `fn_workflow_select` / `workflow_id` ao criar tarefas.
- **Catálogo integrado:** Coding (`builtin:coding`), Quick fix (`builtin:quick-fix`), Review-heavy (`builtin:review-heavy`), Compound engineering (`builtin:compound-engineering`, habilitado por plugin), Stepwise coding (`builtin:stepwise-coding`) e o PR lifecycle (`builtin:pr-workflow`, um fragmento de grafo de PR reutilizável).
- **Personalize com segurança:** inspecione os integrados, duplique-os, ou crie fluxos de trabalho personalizados no [Editor de Fluxo de Trabalho](./docs/workflow-editor.md) visual. As configurações específicas de cada fluxo de trabalho cobrem faixas de modelo, política de revisão/aprovação, ajustes de execução de etapas, campos de tarefa e colunas.
Leia [Etapas do Fluxo de Trabalho](./docs/workflow-steps.md) para a semântica de execução, o comportamento dos fluxos de trabalho integrados e os templates de etapas de fluxo de trabalho; leia [Editor de Fluxo de Trabalho](./docs/workflow-editor.md) para o guia de criação no painel.
<!--
FNXC:PlannerOversight 2026-07-05-00:00:
The planner-oversight feature (FN-7508 → FN-7583) shipped fully documented in internal/reference docs (architecture.md, settings-reference.md, dashboard-guide.md, workflow-steps.md) but had no front-door entry point in README.md, so a new operator could not discover it. Add a short overview here that links out to the canonical docs instead of duplicating engine internals (FN-7598).
-->
### Supervisão do planejador
Cada fluxo de trabalho (e, opcionalmente, cada tarefa) pode definir um nível de **supervisão do planejador** — `off`, `observe`, `steer` ou `autonomous` (padrão) — que controla o quanto um supervisor de planejamento acompanha e intervém na execução daquela tarefa. Mesmo em `autonomous`, o avanço de merge/PR e qualquer efeito colateral destrutivo ou que envolva serviço externo sempre exigem uma confirmação humana explícita e registrada antes de serem executados. A verbosidade das notificações é controlada separadamente. Defina o padrão na aba **Editor de Fluxo de Trabalho → Valores**, ou substitua por tarefa a partir do diálogo Nova Tarefa / formulário de edição em Detalhe da Tarefa. Leia a [Referência de Configurações](./docs/settings-reference.md#workflow-settings) para a semântica completa das configurações e o [Guia do Painel](./docs/dashboard-guide.md) para os controles de UI.
---
## Multi-nó. Um único quadro. Todas as plataformas.
<div align="center">
<img src="./demo/assets/fusion-mesh.gif" alt="Malha do Fusion: laptop, Mac mini, servidor Linux, VM na nuvem, celular — tudo sincronizado" width="820" />
<br />
![macOS](https://img.shields.io/badge/macOS-000000?style=for-the-badge&logo=apple&logoColor=white)
![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white)
![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)
![Web](https://img.shields.io/badge/Web-4285F4?style=for-the-badge&logo=googlechrome&logoColor=white)
![iOS](https://img.shields.io/badge/iOS-000000?style=for-the-badge&logo=apple&logoColor=white)
![Android](https://img.shields.io/badge/Android-3DDC84?style=for-the-badge&logo=android&logoColor=white)
</div>
Laptop, Mac mini, servidor Linux, VM na nuvem, celular — cada nó é um par. O estado das suas tarefas, agentes, logs e diffs permanecem sincronizados em toda a malha. O mesmo Fusion é distribuído como:
- 🖥️ **Aplicativo desktop** — Electron para **macOS** (Intel + Apple Silicon), **Windows** 10/11 e **Linux**
- 📱 **Aplicativo mobile** — Capacitor para **iOS/iPadOS** e **Android** ([MOBILE.md](./MOBILE.md))
- 🌐 **Painel web** — qualquer navegador moderno, servido pelo daemon `fn dashboard`
- 🔌 **CLI** — binário `fn` + extensão para fluxos de trabalho focados em terminal
Inicie o daemon em qualquer nó, conecte seus outros dispositivos, e o quadro te acompanha para todo lugar.
---
## Execute uma empresa de agentes
<div align="center">
<img src="./demo/assets/fusion-company-reel.gif" alt="Empresa de agentes do Fusion: importe uma equipe, execute-a de forma autônoma por semanas" width="820" />
</div>
Importe uma equipe. Execute-a de forma autônoma por semanas. **Mais de 440 agentes em 16 empresas**, prontos para missões, caixas de mensagens e delegação entre agentes.
```bash
npx companies.sh add paperclipai/companies/gstack
```
---
## Compatível com as ferramentas que você já usa.
O Fusion se integra com as ferramentas que você já ama. **Hermes**, **Paperclip** e **OpenClaw** vêm todos como plugins de primeira classe — encaminhe qualquer workspace para o runtime que melhor se encaixa na tarefa. E qualquer empresa de agentes do Paperclip é importada com um único comando.
<div align="center">
<img src="./demo/assets/hermes-logo.svg" alt="Hermes" height="56" />
</div>
### [Hermes](https://hermes-agent.nousresearch.com) <sub>`experimental`</sub>
<sub>Nous Research</sub>
O agente autônomo de código aberto da **Nous Research**. Instale o plugin do Hermes e execute agentes através do Hermes para trabalhos de longa duração com contexto crescente — encaminhe qualquer workspace do Fusion para ele.
### OpenClaw <sub>`experimental`</sub>
O suporte ao runtime OpenClaw está disponível como um plugin experimental (`fusion-plugin-openclaw-runtime`) para paridade de descoberta/configuração de runtime. Configure os agentes com `runtimeConfig.runtimeHint: "openclaw"` depois de instalar o plugin.
<br />
<div align="center">
<img src="./demo/assets/paperclip-logo.svg" alt="Paperclip" height="56" />
</div>
### [Paperclip](https://paperclip.ing) <sub>`experimental`</sub>
<sub>paperclip.ing</sub>
O plano de controle humano para o trabalho de IA. Instale o plugin do Paperclip para executar agentes através do Paperclip dentro do Fusion.
O Fusion também suporta nativamente o padrão de empresa de agentes **[`companies.sh`](https://github.com/paperclipai/companies)**: importe uma equipe pronta — **mais de 440 agentes em 16 empresas** — e deixe que se coordenem através da caixa de mensagens, missões e gates de fluxo de trabalho do Fusion durante semanas de trabalho autônomo. Mesmo formato de empresa, mesmos agentes, mesmas habilidades do Paperclip.
```bash
npx companies.sh add paperclipai/companies/gstack
```
<br />
> **Hermes**, **Paperclip** e **OpenClaw** são plugins de runtime **experimentais** — APIs e formatos de comunicação podem mudar entre releases menores.
---
## Documentação
| Guia | O que cobre |
|---|---|
| [Primeiros passos](./docs/getting-started.md) | Instalação, onboarding, primeira tarefa e noções básicas de seleção de fluxo de trabalho |
| [Guia do Painel](./docs/dashboard-guide.md) | Visualizações de quadro/lista, chat, editor de fluxo de trabalho, gerenciador de git, configurações e ferramentas de UI |
| [Gestão de Tarefas](./docs/task-management.md) | Ciclo de vida da tarefa, especificações de prompt, comentários, arquivamento e integração com GitHub |
| [Referência da CLI](./docs/cli-reference.md) | Referência completa dos comandos `fn` e do daemon |
| [Referência de Configurações](./docs/settings-reference.md) | Configurações globais/de projeto, hierarquia de modelos, configurações de fluxo de trabalho e provedores personalizados |
| [Etapas do Fluxo de Trabalho](./docs/workflow-steps.md) | Execução de fluxos de trabalho, fluxos integrados, gates, templates e fases |
| [Editor de Fluxo de Trabalho](./docs/workflow-editor.md) | Criação visual, importação/exportação, campos/colunas/configurações personalizados e editor mobile |
| [Pesquisa](./docs/research.md) | Execuções de pesquisa limitadas, descobertas, exportações e integração com tarefas |
| [Agentes](./docs/agents.md) | Gestão de agentes, criação, heartbeat e fluxos de caixa de mensagens |
| [Missões](./docs/missions.md) | Hierarquia de missões, planejamento, piloto automático e contratos de validação |
| [Gestão de Plugins](./docs/plugin-management.md) | Descoberta, instalação, habilitação, configuração e solução de problemas de plugins |
| [Criação de Plugins](./docs/PLUGIN_AUTHORING.md) | Construção de plugins com hooks de ciclo de vida, rotas, ferramentas, runtimes e superfícies do painel |
| [Acesso Remoto](./docs/remote-access.md) | Acesso remoto ao painel com token, configuração do Tailscale/Cloudflare e solução de problemas |
| [Multi-Projeto](./docs/multi-project.md) | Registro central, modos de isolamento e caminhos de migração |
| [Armazenamento](./docs/storage.md) | Armazenamento de execução PostgreSQL, compatibilidade de migração e payloads baseados em arquivo |
| [Docker](./docs/docker.md) | Deploy em containers |
---
## Funcionalidades principais
- **Planejamento com IA** — O agente de planejamento gera um `PROMPT.md` detalhado com etapas, escopo de arquivos e critérios de aceitação
- **Execução passo a passo** — Ciclo Plan → Review → Execute → Review para cada etapa da tarefa, com fluxos de trabalho em modo grafo capazes de modelar explicitamente parse/execute/review/rework por etapa
- **Isolamento de Worktree do Git** — Cada tarefa roda em seu próprio worktree (branch `fusion/{task-id}`)
- **Fluxos de trabalho selecionáveis** — Escolha Coding, Quick fix, Review-heavy, Stepwise coding, Compound Engineering habilitado por plugin, fluxos de trabalho personalizados, ou fragmentos de PR lifecycle quando apropriado ([visão geral](#visão-geral-do-fluxo-de-trabalho); [Etapas do Fluxo de Trabalho](./docs/workflow-steps.md#workflow-overview))
- **Editor de Fluxo de Trabalho Visual** — Inspecione integrados somente leitura, duplique/personalize fluxos de trabalho, e edite nós do grafo, colunas, campos de tarefa, configurações tipadas e valores por projeto ([Editor de Fluxo de Trabalho](./docs/workflow-editor.md))
- **Etapas do Fluxo de Trabalho** — Gates de qualidade configuráveis (pré-merge: bloqueia o merge; pós-merge: informativo), além de etapas opcionais declaradas pelo fluxo de trabalho, como a [Verificação em Navegador](./docs/workflow-steps.md#workflow-declared-optional-steps-optional-group-nodes) opcional
- **Política nativa do fluxo de trabalho** — Planejamento em modo rápido (`leanPlanning` / `autoApproveSpec`), limites de triagem tipados, revisão/aprovação, execução de etapas e faixas de modelo/fallback são configurações do fluxo de trabalho, não constantes fixas no engine ([Referência de Configurações](./docs/settings-reference.md#workflow-native-triage-policy-settings); [configurações de fluxo de trabalho](./docs/settings-reference.md#workflow-settings))
- **Supervisão do planejador** — `plannerOversightLevel` nativo do fluxo de trabalho (`off`/`observe`/`steer`/`autonomous`), com uma substituição opcional por tarefa e uma configuração separada de verbosidade de notificações; o avanço de merge/PR e ações destrutivas sempre exigem confirmação humana explícita, mesmo em `autonomous` ([visão geral](#supervisão-do-planejador); [Referência de Configurações](./docs/settings-reference.md#workflow-settings))
- **GitHub + ciclo de vida de PR** — Importe issues com tradução opcional e anexos de captura de tela, pule issues já importadas mesmo após edições ou mudanças de capitalização no repositório, crie PRs, exiba badges de PR/issue em tempo real, e use fragmentos de grafo de PR lifecycle em modo fluxo de trabalho onde habilitado
- **Painel** — Visualizações kanban/lista/grafo em tempo real, uma Visão geral do projeto com estimativa de tokens da base de código local e tamanho em disco, gestão de agentes, terminal, gerenciador de git, planejador de missões, chat, editor de fluxo de trabalho, configuração de provedores personalizados, e ação de atualização em um clique
- **Missões** — Planejamento hierárquico (Missão → Marco → Fatia → Funcionalidade → Tarefa) com piloto automático, contratos de validação, retentativas de correção de funcionalidade, vinculação de meta de missão e semântica de transferência bloqueada
- **Multi-Projeto** — Gerencie múltiplos projetos a partir de uma única instalação com isolamento entre projetos
- **Provedores Personalizados** — Adicione provedores compatíveis com OpenAI, OpenAI Responses, compatíveis com Anthropic, ou Google Generative AI; os modelos salvos aparecem nos menus de Modelos do Projeto e de modelo do fluxo de trabalho ([Guia do Painel](./docs/dashboard-guide.md#custom-providers); [formato das configurações](./docs/settings-reference.md#customproviders))
- **Controles inteligentes de merge** — O auto-merge global permanece ativo para tarefas padrão, enquanto substituições explícitas por tarefa podem forçar o comportamento auto/manual ([Referência de Configurações](./docs/settings-reference.md#project-settings))
- **Mensagens Entre Agentes** — Mensagens integradas para coordenação entre agentes e usuários; agentes com papel de engenheiro podem optar pela captura automática de backlog para tarefas de implementação ([Referência de Configurações](./docs/settings-reference.md#project-settings))
- **Chat com Agentes + Salas de Chat** — O chat direto/de tarefa suporta anexos, streams retomáveis, cartões de resposta a perguntas e conversas renomeáveis; salas experimentais encaminham membros mencionados como respondentes diretos, com respostas ambientes opcionais ([Guia do Painel → Visualização de Chat](./docs/dashboard-guide.md#chat-view))
### Autenticação de provedores
O Fusion suporta autenticação baseada em OAuth para provedores de IA configurados em **Configurações → Autenticação**. Para a maioria dos provedores OAuth, quando o painel é acessado por um host que não é localhost (nó remoto, host/IP de LAN, ou proxy reverso), as URLs de login do provedor são reescritas para encaminhar os callbacks de OAuth através de um endpoint ponte (`/api/auth/oauth-callback`) para que os redirecionamentos cheguem à sessão de navegador ativa.
- **Anthropic (Claude)** — Usa um fluxo de código de autorização colado em Configurações/onboarding: faça login e depois cole a URL de redirecionamento final (ou o código) de volta no Fusion para concluir o login
- **OpenAI Codex** — Usa o mesmo fluxo de código de autorização colado, com validação segura de estado
- **Factory AI — via Droid CLI** *(opcional)* — requer instalação local da Droid CLI + `droid auth login`; a detecção segue o caminho efetivo do binário em tempo de execução (padrão `droid`, ou `droidBinaryPath` do plugin quando configurado), depois habilite em **Configurações → Autenticação** e reinicie o Fusion
- **llama.cpp — via servidor HTTP** *(opcional)* — configure a URL do seu servidor llama.cpp (padrão `http://127.0.0.1:8080`) e a chave de API opcional, depois habilite em **Configurações → Autenticação**
- **Outros provedores** — Autentique-se inserindo a chave de API em Configurações (incluindo chave de API do Google/Gemini, Google Generative AI, Vertex e os aliases do Cloud Code)
- **Provedores personalizados** — Adicione endpoints compatíveis com OpenAI, OpenAI Responses, compatíveis com Anthropic, ou Google Generative AI definidos pelo usuário em **Configurações → Autenticação → Provedores Personalizados**; os IDs de modelo salvos ficam selecionáveis nas faixas de modelo do projeto e do fluxo de trabalho ([Guia do Painel](./docs/dashboard-guide.md#custom-providers))
### Sistema de modelos
O Fusion usa uma hierarquia de modelos de escopo duplo com faixas independentes. As configurações globais definem os padrões de referência; as configurações de projeto fornecem substituições por projeto.
| Faixa | Propósito | Chaves de Referência Global | Chaves de Substituição por Projeto |
|------|---------|---------------------|----------------------|
| Executor | Agente de execução de tarefas | `executionGlobalProvider` + `executionGlobalModelId` | `executionProvider` + `executionModelId` |
| Planning | Agente de planejamento de tarefas | `planningGlobalProvider` + `planningGlobalModelId` | `planningProvider` + `planningModelId` |
| Validator | Revisor de plano/código | `validatorGlobalProvider` + `validatorGlobalModelId` | `validatorProvider` + `validatorModelId` |
| Merger | Agente de conflitos de merge / merge em clean-room | `mergerGlobalProvider` + `mergerGlobalModelId` | `mergerProvider` + `mergerModelId` |
| Title Summarization | Geração automática de título | `titleSummarizerGlobalProvider` + `titleSummarizerGlobalModelId` | `titleSummarizerProvider` + `titleSummarizerModelId` |
| Workflow Step Refinement | Refinamento de prompt por IA | (usa `defaultProvider`/`defaultModelId`) | (usa `modelProvider`/`modelId` em WorkflowStep) |
**Faixas de fluxo de trabalho:** O fluxo de trabalho padrão expõe as faixas de modelo Plan/Triage, Executor, Reviewer e fallback em **Configurações → Modelos do Projeto**, e configurações avançadas de fluxo de trabalho podem declarar valores tipados adicionais de modelo/política ([Referência de Configurações](./docs/settings-reference.md#workflow-settings)).
**Substituições por Tarefa:** Quick Add e Inline Create permitem que tarefas substituam as faixas de planning, executor, validator e merger; as seleções de planning, validator e merger também suportam níveis de raciocínio específicos por tarefa. (`modelProvider`/`modelId`, `validatorModelProvider`/`validatorModelId`, `planningModelProvider`/`planningModelId`, e substituições de modelo/raciocínio do merger.)
**Precedência:** Por tarefa → Substituição do projeto → Faixa global → `defaultProvider`/`defaultModelId` → Resolução automática.
Para a documentação completa de configurações, veja a [Referência de Configurações](./docs/settings-reference.md).
### Tarefas agendadas / automações
O Fusion suporta automação de tarefas agendadas através dos endpoints `/api/automations`. Automações podem executar comandos de shell ou fluxos de trabalho de múltiplas etapas em um agendamento configurável.
#### Escopo de agendamento
Automações e rotinas podem rodar em dois escopos:
- **Global** — Roda em todos os projetos. Use para manutenção entre projetos, backups ou relatórios unificados.
- **Projeto** — Roda apenas dentro de um projeto específico. Use para CI, testes ou tarefas de deploy específicas do projeto.
Quando você cria um agendamento sem escolher um escopo, o Fusion usa por padrão o **escopo de projeto** com o ID de projeto `default`, para compatibilidade com versões anteriores.
Para direcionar um escopo explicitamente:
- No modal **Scheduled Tasks** do painel, use o alternador **Global / Projeto**.
- Pela API, passe `?scope=global` ou `?scope=project&projectId=<id>` nos endpoints de automação/rotina.
**Regras de resolução de escopo:**
- `scope=global` sempre resolve para a faixa global de automação/rotina, independentemente do projeto ativo.
- `scope=project` requer um `projectId`. Se omitido, recai para `"default"`.
- Operações de CRUD, execução, alternância e webhook são estritamente isoladas por escopo: um agendamento global não pode ser modificado a partir de uma requisição com escopo de projeto, e vice-versa.
**Orientação operacional para configurações multi-projeto:**
- Prefira agendamentos **globais** para infraestrutura compartilhada (por exemplo, backups noturnos, extração de insights de memória).
- Prefira agendamentos de **projeto** para automação por repositório (por exemplo, executores de teste por projeto, hooks de deploy).
- As faixas global e de projeto são verificadas de forma independente pelo engine, então execuções pendentes em uma faixa não bloqueiam a outra.
#### Automações
| Endpoint | Método | Descrição |
|---------|--------|-------------|
| `/api/automations` | GET | Lista todas as automações (filtradas por escopo, se especificado) |
| `/api/automations` | POST | Cria uma automação (o escopo padrão é `project`) |
| `/api/automations/:id` | GET | Obtém uma automação pelo ID |
| `/api/automations/:id` | PATCH | Atualiza uma automação |
| `/api/automations/:id` | DELETE | Exclui uma automação |
| `/api/automations/:id/run` | POST | Dispara uma execução manual |
| `/api/automations/:id/toggle` | POST | Alterna entre habilitado/desabilitado |
| `/api/automations/:id/steps/reorder` | POST | Reordena as etapas da automação |
#### Rotinas
Rotinas são tarefas de agente de IA disparadas por agendamentos cron, webhooks ou execução manual. As rotinas compartilham o mesmo modelo de escopo global/projeto das automações.
| Endpoint | Método | Descrição |
|---------|--------|-------------|
| `/api/routines` | GET | Lista todas as rotinas (filtradas por escopo, se especificado) |
| `/api/routines` | POST | Cria uma rotina (o escopo padrão é `project`) |
| `/api/routines/:id` | GET | Obtém uma rotina pelo ID |
| `/api/routines/:id` | PATCH | Atualiza uma rotina |
| `/api/routines/:id` | DELETE | Exclui uma rotina |
| `/api/routines/:id/run` | POST | Disparo manual |
| `/api/routines/:id/trigger` | POST | Disparo manual canônico |
| `/api/routines/:id/runs` | GET | Obtém o histórico de execuções |
| `/api/routines/:id/webhook` | POST | Disparo via webhook (com suporte a verificação de assinatura) |
---
## Exemplos rápidos da CLI
```bash
fn task create "Fix the login bug" # Entrada rápida → planejamento
fn task plan "Build auth system" # Planejamento guiado por IA
fn task import owner/repo --labels bug # Importar issues do GitHub
fn task show FN-001 # Ver detalhes da tarefa
fn task logs FN-001 --follow # Transmitir logs de execução
fn task steer FN-001 "Use TypeScript" # Guiar o agente durante a execução
fn project add my-app /path/to/app # Registrar um projeto
fn project list # Listar todos os projetos
fn settings set maxConcurrent 4 # Definir configurações
fn settings export # Exportar configuração
fn mission create "Auth System" "Build auth" # Criar missão
fn mission activate-slice <slice-id> # Ativar uma fatia
fn skills search react # Buscar no skills.sh
fn skills install firebase/agent-skills # Instalar habilidades de agente
```
---
## Pacotes
| Pacote | Descrição |
|---------|-------------|
| `@fusion/core` | Modelo de domínio — tarefas, colunas do quadro, armazenamento PostgreSQL |
| `@fusion/dashboard` | Interface web — servidor Express + quadro kanban com SSE |
| `@fusion/engine` | Engine de IA — planejamento, execução, agendamento, etapas de fluxo de trabalho |
| `@runfusion/fusion` | CLI + extensão — publicado no npm |
---
## Desenvolvimento
```bash
pnpm install # Instalar dependências
pnpm local # Iniciar painel/API local + motor de IA em uma porta diferente da 4040
pnpm local --no-engine # Iniciar apenas o painel/API local
pnpm build # Compilar pacotes padrão do workspace (exclui desktop/mobile)
pnpm build:all # Compilar todos os pacotes (incluindo desktop/mobile)
pnpm dev dashboard # Executar painel + motor de IA
pnpm dev:watch # Painel + motor de IA; reinicia em edições de código-fonte após o esvaziamento dos agentes
pnpm dev:ui # Apenas o painel (sem motor de IA)
pnpm lint # Executar lint em todos os pacotes
pnpm typecheck # Verificar tipos em todos os pacotes
pnpm test # Executar todos os testes
```
### Compilar um executável independente
Compile um único binário `fn` autocontido usando o [Bun](https://bun.sh/):
```bash
pnpm build:exe # Compilar para a plataforma atual
pnpm build:exe:all # Compilação cruzada para todas as plataformas
```
---
## Licença
MIT — código aberto, sem dependência de fornecedor. Veja [LICENSE](./LICENSE).
<div align="center">
**[runfusion.ai →](https://runfusion.ai)**
</div>

View File

@@ -10,7 +10,7 @@
[**runfusion.ai →**](https://runfusion.ai) · [文档](./docs/README.md) · [GitHub](https://github.com/Runfusion/Fusion) · [npm](https://www.npmjs.com/package/@runfusion/fusion) · [Discord](https://discord.gg/ksrfuy7WYR)
[English](./README.md) · **简体中文** · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · [Español](./README.es.md) · [한국어](./README.ko.md)
[English](./README.md) · **简体中文** · [繁體中文](./README.zh-TW.md) · [Français](./README.fr.md) · [Español](./README.es.md) · [한국어](./README.ko.md) · [Português (Brasil)](./README.pt-BR.md)
*本文档为社区机器翻译版本,英文 README 为权威原版。*

View File

@@ -10,7 +10,7 @@
[**runfusion.ai →**](https://runfusion.ai) · [文件](./docs/README.md) · [GitHub](https://github.com/Runfusion/Fusion) · [npm](https://www.npmjs.com/package/@runfusion/fusion) · [Discord](https://discord.gg/ksrfuy7WYR)
[English](./README.md) · [简体中文](./README.zh-CN.md) · **繁體中文** · [Français](./README.fr.md) · [Español](./README.es.md) · [한국어](./README.ko.md)
[English](./README.md) · [简体中文](./README.zh-CN.md) · **繁體中文** · [Français](./README.fr.md) · [Español](./README.es.md) · [한국어](./README.ko.md) · [Português (Brasil)](./README.pt-BR.md)
*本文件為機器翻譯,英文版 README 為權威版本。*

View File

@@ -337,7 +337,7 @@ fn dashboard --lang zh-TW # force a UI locale for this run
```
The terminal UI is localized. `--lang <code>` (one of `en`, `zh-CN`, `zh-TW`,
`fr`, `es`, `ko`) takes precedence over the saved dashboard language setting and the
`fr`, `es`, `ko`, `pt-BR`) takes precedence over the saved dashboard language setting and the
`LC_ALL`/`LC_MESSAGES`/`LANG`/`LANGUAGE` environment. See
[Localization contributor guide](./i18n-contributing.md).

View File

@@ -86,7 +86,12 @@ No feature code changes are required: the dashboard discovers the locale through
the generated `app/locales/` tree, and the CLI through the regenerated import
map. Add the language's endonym to `ENDONYMS` in
`packages/dashboard/app/components/LanguageSelector.tsx` so it appears in the
Settings switcher.
Settings switcher, add a prompt label to `LOCALE_LABELS` in
`packages/dashboard/src/ai-translate.ts` (compile-enforced), and add a display
name to `localeDisplayName` in
`packages/core/src/i18n/detect-content-language.ts`. For Latin-script languages,
also consider a stopword list in `LATIN_STOPWORDS` there so content-language
detection can recognize the language (entries must be accent-stripped).
## Using a non-English locale

View File

@@ -74,7 +74,7 @@ Defaults from `DEFAULT_GLOBAL_SETTINGS`; key scope from `GLOBAL_SETTINGS_KEYS`.
| `themeMode` | `"dark" \| "light" \| "system"` | `"system"` | Dashboard theme mode. Fresh installs follow the operating system light/dark preference until the user chooses Light, Dark, or System. |
| `colorTheme` | `ColorTheme` | `"shadcn-ember"` | Dashboard color theme preset. Aurora is a built-in navy/teal/violet palette with a misty light counterpart; Calm is a low-stimulation slate/sage palette with a misty light counterpart; Dawn uses indigo/plum dark surfaces, amber accents, and dawn-white light surfaces; Midnight uses deep-navy surfaces with restrained violet/indigo accents and a cool pale light counterpart; Factory Dark uses graphite/steel surfaces, cool gunmetal borders, and restrained safety-orange accents with a concrete-gray light counterpart; Factory Light uses bright concrete/warm-white surfaces, steel-gray borders, a darkened safety-orange accent, and a warm-graphite dark counterpart. Use `"shadcn-custom"` to show the separate custom shadcn color picker in Settings → Appearance and the Command Center theme card. |
| `shadcnCustomColors` | `Record<string, string>` | `undefined` | Optional shadcn design-token override map for `"shadcn-custom"` only. Keys are CSS token names such as `--accent`, `--bg`, `--surface`, `--card`, `--border`, `--text`, `--text-muted`, workflow status tokens, and `--color-success`/`--color-warning`/`--color-error`; values must be sanitized `#RGB` or `#RRGGBB` hex colors. Missing or invalid entries fall back to the `shadcn-custom` base defaults and are not applied to other themes. |
| `language` | `"en" \| "zh-CN" \| "zh-TW" \| "fr" \| "es" \| "ko"` | `undefined` | UI language for the dashboard and TUI. When unset, the dashboard detects from localStorage → browser language and the CLI from `--lang` flag → environment locale, falling back to `en`. Validated at the store write boundary (`validateLocale`); invalid values are dropped. Reset to auto-detect via the dashboard's "Auto" language option or `fn settings set language auto` (clears the persisted key). |
| `language` | `"en" \| "zh-CN" \| "zh-TW" \| "fr" \| "es" \| "ko" \| "pt-BR"` | `undefined` | UI language for the dashboard and TUI. When unset, the dashboard detects from localStorage → browser language and the CLI from `--lang` flag → environment locale, falling back to `en`. Validated at the store write boundary (`validateLocale`); invalid values are dropped. Reset to auto-detect via the dashboard's "Auto" language option or `fn settings set language auto` (clears the persisted key). |
| `dashboardFontScalePct` | `number` | `100` | Dashboard font scale percentage used by Appearance settings. Valid range: `85` to `125`; applied pre-hydration via document root font-size so board typography (column headers/counts, task cards, and quick-entry text) scales with the setting from first paint. |
| `dismissModalsOnOutsideClick` | `boolean` | `false` | Global dashboard preference for closing fixed modal overlays by clicking/tapping the backdrop. Off by default to prevent accidental modal dismissal; explicit close, cancel, and Escape paths remain available. |
| `skipConfirmationDialogs` | `boolean` | `false` | Global-only operator preference that skips centralized confirmation dialogs for critical actions. When enabled, destructive actions such as deleting a task or resetting progress immediately take the dialog's primary/default action; project settings cannot enable it for shared-project collaborators. |

View File

@@ -29,7 +29,7 @@ const DEFERRED_I18N_LINT_FILES = [
* source, not by file path. `common` is the default namespace.
*/
export default defineConfig({
locales: ["en", "zh-CN", "zh-TW", "fr", "es", "ko"],
locales: ["en", "zh-CN", "zh-TW", "fr", "es", "ko", "pt-BR"],
extract: {
input: [
"packages/dashboard/app/**/*.{ts,tsx}",

View File

@@ -502,7 +502,7 @@ Options:
--no-engine Start dashboard only (no AI engine)
--supervise (default) Run with auto-restart on crash and System-panel restart support
--no-supervise Run the dashboard without the supervising parent process
--lang <locale> Terminal-UI locale for this run (en, zh-CN, zh-TW, fr, es, ko); the browser dashboard resolves its own language
--lang <locale> Terminal-UI locale for this run (en, zh-CN, zh-TW, fr, es, ko, pt-BR); the browser dashboard resolves its own language
--attach <file> Attach file(s) on task create (repeatable)
--depends <id> Declare dependency on task create (repeatable)
--no-dedup Bypass deterministic duplicate guard on task create

View File

@@ -40,7 +40,7 @@ vi.mock("@fusion/core", () => {
return {
GlobalSettingsStore: makeConstructibleMock(),
DEFAULT_SETTINGS,
SUPPORTED_LOCALES: ["en", "zh-CN", "zh-TW", "fr", "es", "ko"],
SUPPORTED_LOCALES: ["en", "zh-CN", "zh-TW", "fr", "es", "ko", "pt-BR"],
resolveWorktrunkSettings: (globalValue: any, projectValue: any) => ({
enabled: projectValue?.enabled ?? globalValue?.enabled ?? false,
...(projectValue?.binaryPath ?? globalValue?.binaryPath ? { binaryPath: projectValue?.binaryPath ?? globalValue?.binaryPath } : {}),

View File

@@ -12,13 +12,13 @@ import {
} from "../index.js";
describe("locale primitives", () => {
it("exposes exactly the six supported locale codes", () => {
expect([...SUPPORTED_LOCALES]).toEqual(["en", "zh-CN", "zh-TW", "fr", "es", "ko"]);
it("exposes exactly the seven supported locale codes", () => {
expect([...SUPPORTED_LOCALES]).toEqual(["en", "zh-CN", "zh-TW", "fr", "es", "ko", "pt-BR"]);
});
it("uses en as the default/source locale", () => {
expect(DEFAULT_LOCALE).toBe("en");
expectTypeOf<Locale>().toEqualTypeOf<"en" | "zh-CN" | "zh-TW" | "fr" | "es" | "ko">();
expectTypeOf<Locale>().toEqualTypeOf<"en" | "zh-CN" | "zh-TW" | "fr" | "es" | "ko" | "pt-BR">();
});
it("narrows supported codes and rejects everything else via isLocale", () => {
@@ -26,6 +26,7 @@ describe("locale primitives", () => {
expect(isLocale(code)).toBe(true);
}
expect(isLocale("zh")).toBe(false);
expect(isLocale("pt")).toBe(false);
expect(isLocale("de")).toBe(false);
expect(isLocale("")).toBe(false);
expect(isLocale(undefined)).toBe(false);
@@ -50,6 +51,7 @@ describe("language global setting", () => {
expect(validateLocale("zh-TW")).toBe("zh-TW");
expect(validateLocale("fr")).toBe("fr");
expect(validateLocale("es")).toBe("es");
expect(validateLocale("pt-BR")).toBe("pt-BR");
expect(validateLocale(undefined)).toBeUndefined();
expect(validateLocale("zh")).toBeUndefined();
expect(validateLocale("de")).toBeUndefined();

View File

@@ -28,7 +28,7 @@ export type DetectedContentLanguage = {
confidence: "high" | "medium" | "low";
};
const LATIN_STOPWORDS: Record<"en" | "fr" | "es" | "cs", readonly string[]> = {
const LATIN_STOPWORDS: Record<"en" | "fr" | "es" | "cs" | "pt-BR", readonly string[]> = {
en: [
"the", "and", "for", "that", "with", "this", "from", "have", "will", "are",
"not", "but", "you", "all", "can", "has", "was", "were", "been", "their",
@@ -55,6 +55,23 @@ const LATIN_STOPWORDS: Record<"en" | "fr" | "es" | "cs", readonly string[]> = {
"kdy", "ktere", "ktery", "na", "nebo", "nema", "neni", "po", "pro", "pri", "se", "si",
"tak", "to", "uz", "ve", "vse", "z", "ze",
],
/*
FNXC:GitHubImportTranslate 2026-08-07-22:55:
pt-BR stopwords are written accent-stripped because scoreLatinLocale strips diacritics
before matching ("não"→"nao"); accented entries would never match. "mais" is deliberately
omitted (collides with the French "mais" list entry).
FNXC:GitHubImportTranslate 2026-08-07-23:07:
"com" is deliberately omitted too (review finding, Task 3): the tokenizer only strips
protocol-prefixed URLs, so bare domains like "github.com, gitlab.com, npmjs.com" tokenize
to repeated "com" tokens, pushing ordinary English issue bodies over the high-confidence
pt-BR threshold and triggering false translate offers / wasted auto-translate model calls.
*/
"pt-BR": [
"nao", "uma", "para", "dos", "das", "pelo", "pela", "sao", "esta",
"tambem", "quando", "voce", "isso", "essa", "esse", "seu", "sua", "ate",
"apos", "ja", "fazer", "pode", "deve", "usar", "entao", "muito", "tem", "foi", "ser",
],
};
function countMatches(text: string, re: RegExp): number {
@@ -88,16 +105,16 @@ function scoreLatinLocale(text: string): { locale: Locale | "unknown"; confidenc
return { locale: "en", confidence: "low" };
}
const scores: Record<"en" | "fr" | "es" | "cs", number> = { en: 0, fr: 0, es: 0, cs: 0 };
const scores: Record<"en" | "fr" | "es" | "cs" | "pt-BR", number> = { en: 0, fr: 0, es: 0, cs: 0, "pt-BR": 0 };
for (const token of tokens) {
for (const locale of ["en", "fr", "es", "cs"] as const) {
for (const locale of ["en", "fr", "es", "cs", "pt-BR"] as const) {
if (LATIN_STOPWORDS[locale].includes(token)) {
scores[locale] += 1;
}
}
}
const ranked = (Object.entries(scores) as Array<["en" | "fr" | "es" | "cs", number]>).sort(
const ranked = (Object.entries(scores) as Array<["en" | "fr" | "es" | "cs" | "pt-BR", number]>).sort(
(a, b) => b[1] - a[1],
);
const [best, second] = ranked;
@@ -280,6 +297,8 @@ export function localeDisplayName(locale: Locale | "unknown"): string {
return "Español";
case "ko":
return "한국어";
case "pt-BR":
return "Português (Brasil)";
default:
return locale;
}

View File

@@ -186,8 +186,11 @@ export type ColorTheme = (typeof COLOR_THEMES)[number];
* source-of-truth language and the fallback for all others. Adding a locale
* here (plus translated catalogs) is the only code change a new language
* needs — see `@fusion/i18n`. zh-CN and zh-TW are independent catalogs and
* are never auto-converted between scripts. */
export const SUPPORTED_LOCALES = ["en", "zh-CN", "zh-TW", "fr", "es", "ko"] as const;
* are never auto-converted between scripts.
*
* FNXC:I18nLocales 2026-08-07-22:00:
* Added pt-BR as a dashboard/translation-target locale; catalogs are machine-drafted pending human review. */
export const SUPPORTED_LOCALES = ["en", "zh-CN", "zh-TW", "fr", "es", "ko", "pt-BR"] as const;
export type Locale = (typeof SUPPORTED_LOCALES)[number];
/** Source-of-truth language and the fallback for all locales. */
export const DEFAULT_LOCALE: Locale = "en";

View File

@@ -11,6 +11,7 @@ const ENDONYMS: Record<Locale, string> = {
fr: "Français",
es: "Español",
ko: "한국어",
"pt-BR": "Português (Brasil)",
};
/** Settings control for choosing the UI language. Applies in place (no reload). */

View File

@@ -26,9 +26,9 @@ describe("LanguageSelector", () => {
});
});
it("renders all five language endonyms", () => {
it("renders all seven language endonyms", () => {
render(<LanguageSelector />);
for (const name of ["English", "简体中文", "繁體中文", "Français", "Español"]) {
for (const name of ["English", "简体中文", "繁體中文", "Français", "Español", "한국어", "Português (Brasil)"]) {
expect(screen.getByText(name)).toBeTruthy();
}
});

View File

@@ -147,6 +147,7 @@ describe("GeneralSection - import auto-translate controls", () => {
expect(select.className).toContain("select");
expect(select.value).toBe("");
expect([...select.options].map((o) => o.textContent)).toContain("Follow dashboard language");
expect([...select.options].map((o) => o.textContent)).toContain("Português (Brasil)");
});
it("reflects and stores an explicit target locale", () => {

View File

@@ -83,7 +83,7 @@ describe("useLanguage", () => {
it("exposes the supported locale list", () => {
const { result } = renderHook(() => useLanguage());
expect([...result.current.supportedLocales]).toEqual(["en", "zh-CN", "zh-TW", "fr", "es", "ko"]);
expect([...result.current.supportedLocales]).toEqual(["en", "zh-CN", "zh-TW", "fr", "es", "ko", "pt-BR"]);
});
it("hydrates from server settings when no local choice exists", async () => {

View File

@@ -54,6 +54,21 @@ describe("detectContentLanguage", () => {
expect(detected.family).toBe("latin");
});
it("detects Brazilian Portuguese stopword-heavy prose", () => {
const text =
"Não podemos usar essa configuração quando o painel já está aberto, então você deve fazer uma revisão das tarefas para que tudo também funcione como esperado.";
const detected = detectContentLanguage(text);
expect(detected.locale).toBe("pt-BR");
expect(detected.family).toBe("latin");
});
it("does not mistake bare .com domains for Portuguese", () => {
const text =
"Please check github.com, gitlab.com, bitbucket.com, npmjs.com and registry.com to see if the package is published.";
const detected = detectContentLanguage(text);
expect(detected.locale).toBe("en");
});
it("ignores fenced code and URLs when scoring", () => {
const text = `
## Bug
@@ -227,5 +242,6 @@ describe("localeDisplayName", () => {
expect(localeDisplayName("en")).toBe("English");
expect(localeDisplayName("ko")).toBe("한국어");
expect(localeDisplayName("fr")).toBe("Français");
expect(localeDisplayName("pt-BR")).toBe("Português (Brasil)");
});
});

View File

@@ -144,12 +144,18 @@ export function createSmokeHtml() {
The fixture must include all five production icon controls before Save, including the session
advisor toggle. Omitting it understates the primary group's minimum width and could conceal a
300px overflow or wrap regression on either Board or List.
FNXC:QuickAddActionRow 2026-08-07-23:56:
pt-BR joined the supported translations (the scaffold was previously empty and now carries
machine-drafted translations) — add it here so the smoke keeps measuring the widest
emitted-font label across every shipped locale.
*/
const localizedSaveLabels = [
["en", "Save"],
["es", "Guardar"],
["fr", "Enregistrer"],
["ko", "저장"],
["pt-BR", "Salvar"],
["zh-CN", "保存"],
["zh-TW", "儲存"],
];

View File

@@ -136,6 +136,7 @@ const LOCALE_LABELS: Record<Locale, string> = {
fr: "French (Français)",
es: "Spanish (Español)",
ko: "Korean (한국어)",
"pt-BR": "Brazilian Portuguese (Português do Brasil)",
};
/**

View File

@@ -1,6 +1,6 @@
# Translation status
`en` is the authored source-of-truth. The four non-English locales below were
`en` is the authored source-of-truth. The non-English locales below were
**machine-drafted and have NOT been reviewed by a human translator.** They are
shipped so the feature is end-to-end exercisable, but each string should be
reviewed (and corrected where needed) by a fluent speaker before being treated
@@ -13,6 +13,8 @@ as production-quality.
| `zh-TW`| Traditional Chinese (TW) | Machine-drafted ⚠️ |
| `fr` | French | Machine-drafted ⚠️ |
| `es` | Spanish | Machine-drafted ⚠️ |
| `ko` | Korean | Machine-drafted ⚠️ |
| `pt-BR`| Brazilian Portuguese | Machine-drafted ⚠️ |
Notes for reviewers:
@@ -24,3 +26,6 @@ Notes for reviewers:
sweep the product name without touching catalogs.
- Keybinding accelerators inside hints (e.g. `[{{key}}]`) must stay as the
literal key — translate only the surrounding words.
- `pt-BR` is Brazilian Portuguese specifically. European Portuguese (pt-PT)
differs in vocabulary, orthography, and register — do not machine-convert one
into the other.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,226 @@
{
"tui": {
"agentDeleteConfirmHints": "[y] confirmar exclusão [qualquer outra tecla] cancelar",
"agentDeleteConfirmId": "ID:",
"agentDeleteConfirmName": "Agente:",
"agentDeleteConfirmTitle": "Excluir agente?",
"agentDeleted": "Agente {{name}} excluído",
"agentDetailCaps": "Caps:",
"agentDetailLoadError": "Não foi possível carregar o detalhe do agente.",
"agentDetailRole": "Função:",
"agentDetailSelectHint": "Selecione um agente da lista.",
"agentDetailState": "Estado:",
"agentDetailTask": "Tarefa:",
"agentDetailTitle": "Detalhe do Agente",
"agentDetailTitle2": "Título:",
"agentNarrowDetail": "detalhe",
"agentNarrowList": "lista",
"agentOpenLogsHint": "[Enter] abrir registros",
"agentRunHistory": "Histórico de execuções (mais recente primeiro):",
"agentRunId": "ID:",
"agentRunLogsBackHint": "[Esc/q] voltar às execuções",
"agentRunLogsTitle": "Registros de execução ({{index}})",
"agentsFooterHints": "[s] iniciar [x] parar [D] excluir [r] atualizar [Tab] foco ↑↓ selecionar",
"agentsListTitle_one": "Agente ({{count}})",
"agentsListTitle_other": "Agentes ({{count}})",
"agentsNoAgents": "Nenhum agente encontrado.",
"agentStarted": "Agente iniciado",
"agentStopped": "Agente parado",
"boardCreateTaskHints": "Enter para criar · Esc para cancelar",
"boardCreateTaskNoProject": "Nenhum projeto selecionado",
"boardCreateTaskTitleEmpty": "O título não pode estar vazio",
"boardCreatingTask": "Criando…",
"boardNewTaskPlaceholder": "O que precisa ser feito?",
"boardNewTaskProject": "Projeto: {{name}}",
"boardNewTaskTitle": "Nova Tarefa",
"boardNewTaskTitleLabel": "Título",
"boardOtherReadOnlyHint": "coluna personalizada — mover desativado aqui",
"copiedSuccess": "✓ Copiado!",
"copyFailed": "✗ Falha ao copiar",
"expandedLogHeader": "Entrada {{index}}/{{total}} · [Enter/Esc] fechar · [c] copiar",
"expandedLogLevel": "Nível:",
"expandedLogPrefix": "Prefixo:",
"expandedLogTime": "Hora:",
"filesBinary": "[arquivo binário, {{size}}]",
"filesEmpty": "(vazio)",
"filesEmptyFile": "(arquivo vazio)",
"filesFooterHints": "[Tab] trocar painel [↑↓/jk] mover [Enter] abrir [←/→] recolher/expandir [.] ocultos [w] quebra de linha [p] projeto [r] recarregar",
"filesMoreLines_one": "… mais {{count}} linha",
"filesMoreLines_other": "… mais {{count}} linhas",
"filesSelectProject": "Selecionar Projeto",
"filesSelectToPreview": "Selecione um arquivo para pré-visualizar",
"filesTooLarge": "{{size}} — [muito grande para pré-visualizar]",
"filesUnableToRead": "Não foi possível ler o arquivo",
"gitFetched": "Buscado",
"gitFetchFailed": "Falha ao buscar: {{output}}",
"gitFetching": "Buscando…",
"gitFooterHints": "[r] atualizar {{push}}[F] buscar [↑↓] linhas [←→] status▸branches{{worktrees}}▸commits▸alterações [p] projeto [Esc/s] voltar",
"gitNoCommits": "Nenhum commit",
"gitNoProject": "Nenhum projeto",
"gitPushDismissHint": "[Esc] descartar",
"gitPushFailed": "Falha no push",
"gitPushingToOrigin": "Fazendo push para origin/{{branch}}",
"gitPushModalAhead": "à frente",
"gitPushModalBranch": "Branch:",
"gitPushModalCommits": "Commits para push (mais antigo→mais recente):",
"gitPushModalHints": "[Enter] push [Esc] cancelar",
"gitPushModalTitle": "Push para o remoto",
"gitPushSuccessful": "Push concluído com sucesso",
"gitRefreshing": "atualizando",
"gitWorkingTreeClean": "Árvore de trabalho limpa",
"headerHelpQuitHint": "[?] ajuda [q] sair",
"headerTunnelQrHint": " [^Q] QR",
"headerTunnelRunning": "túnel",
"headerTunnelStarting": "túnel iniciando…",
"helpShortcutAdjustNumber": "Ajustar número (Configurações)",
"helpShortcutAdjustThreshold": "Ajustar limite de memória de encerramento do vitest (Utilitários)",
"helpShortcutAgents": "Visão de agentes",
"helpShortcutBoard": "Visão do quadro",
"helpShortcutClearLogs": "Limpar registros (Utilitários)",
"helpShortcutCopyEntry": "Copiar entrada de registro selecionada para a área de transferência (Registros)",
"helpShortcutCopyToken": "Copiar token de autenticação para a área de transferência (Sistema)",
"helpShortcutDeleteAgent": "Excluir agente — requer confirmação (Agentes)",
"helpShortcutExpandEntry": "Expandir entrada de registro (Registros)",
"helpShortcutExpandLog": "Expandir registro + liberar o mouse para seleção de texto (Registros)",
"helpShortcutFiles": "Arquivos (quando não estiver em Registros); alterna o filtro de severidade de registro em Registros",
"helpShortcutFirstLast": "Primeira / última entrada de registro (Registros)",
"helpShortcutForceQuit": "Forçar saída",
"helpShortcutGit": "Visão do Git",
"helpShortcutHiddenFiles": "Alternar arquivos ocultos (Arquivos)",
"helpShortcutJumpPanel": "Ir para o painel (Principal: Sistema/Registros/Estatísticas/Utilitários/Configurações)",
"helpShortcutKillVitest": "Encerrar todos os processos do vitest (Utilitários)",
"helpShortcutMain": "Principal (modo status)",
"helpShortcutMouseToggle": "Alternância manual do modo mouse (automático: ativado para Registros/Arquivos/Git/Quadro, desativado nos demais)",
"helpShortcutNavigate": "Navegar lista / entradas de registro",
"helpShortcutNewTask": "Nova tarefa (Quadro)",
"helpShortcutNextPanel": "Próximo painel (Principal; ↑/↓ rolar em Registros)",
"helpShortcutOpenUrl": "Abrir URL do painel no navegador (Sistema)",
"helpShortcutPrevPanel": "Painel anterior (Principal; ↑/↓ rolar em Registros)",
"helpShortcutProjectPicker": "Seletor de projeto (Quadro, Arquivos)",
"helpShortcutPushFetch": "Push / buscar (Git)",
"helpShortcutQuit": "Sair",
"helpShortcutRefreshStats": "Atualizar estatísticas (Utilitários)",
"helpShortcutSettings": "Visão de configurações",
"helpShortcutSwitchPane": "Trocar painel (Agentes, Configurações, Arquivos, Git)",
"helpShortcutTabBackward": "Ciclar painel / painel em foco para trás",
"helpShortcutTabForward": "Ciclar painel / painel em foco para frente",
"helpShortcutToggleAutoKill": "Alternar encerramento automático do vitest sob pressão de memória (Utilitários)",
"helpShortcutToggleBool": "Alternar booleano (Configurações)",
"helpShortcutToggleHelp": "Alternar ajuda",
"helpShortcutWordWrap": "Alternar quebra de linha (Registros / Arquivos)",
"helpTitle": "ATALHOS DE TECLADO",
"interactiveModeUnavailable": "Modo interativo indisponível — sem fonte de dados",
"loading": "Carregando…",
"loadingTasks": "Carregando tarefas…",
"logsPanelTitle": "Registros",
"narrowModeIndicator": "[estreito]",
"noEntriesMatchFilter": "Nenhuma entrada corresponde ao filtro {{filter}}.",
"noLogEntries": "Ainda não há entradas de registro.",
"noTasks": "Não há tarefas neste projeto.",
"projectSelectorChangeHint": "[p] trocar",
"projectSelectorLabel": "Projeto:",
"projectSelectorNavHints": "↑↓ navegar · Enter selecionar · Esc cancelar",
"projectSelectorNone": "(nenhum)",
"projectSelectorNoProjects": "(nenhum projeto registrado)",
"projectSelectorPickTitle": "Escolha um projeto",
"qrCloseHint": "[Esc] fechar",
"qrGenerating": "Gerando QR…",
"qrNoTunnelRunning": "Nenhum túnel remoto está em execução. Inicie um em Configurações (g).",
"qrOverlayTitle": "Acesso Remoto — Escaneie para conectar",
"readyIn": "Pronto em {{secs}}s",
"runLogNone": "Nenhum registro capturado para esta execução.",
"runLogResult": "resultado:",
"runLogSource": "origem",
"runLogStderr": "stderr:",
"runLogStdout": "stdout:",
"runLogTrigger": "gatilho",
"runStatusActive": "Ativo",
"runStatusCompleted": "Concluído",
"runStatusFailed": "Falhou",
"runStatusTerminated": "Encerrado",
"runStatusUnknown": "Desconhecido",
"settingsActivatedProvider": "Provedor ativado: {{provider}}",
"settingsAdjust1": "[+/-] ajustar em 1",
"settingsAdjust5000ms": "[+/-] ajustar em 5000ms",
"settingsAvailableModelsHeader": "──── Modelos Disponíveis ────",
"settingsBoolToggleHint": "[Espaço] alternar",
"settingsCancelledTokenInput": "Entrada de token de curta duração cancelada",
"settingsConfigureModelInDashboard": "Configure o modelo padrão no painel web",
"settingsCurrentLabel": "Atual:",
"settingsEditModelsTitle": "Editar / Modelos",
"settingsEnterTtl": "Digite o TTL em milissegundos e pressione Enter",
"settingsEnumCycleHint": "[←/→] alternar opções:",
"settingsFooterHints": "[Tab] trocar painel ↑↓ selecionar configuração [Espaço] alternar bool [+/-] ajustar núm [←/→] alternar enum [C/V/X/P/L/U/K/R] ações remotas",
"settingsInteractivePanelTitle": "Configurações",
"settingsLoadingSettings": "Carregando configurações…",
"settingsMoreModels_one": "… e mais {{count}}",
"settingsMoreModels_other": "… e mais {{count}}",
"settingsPanelTitle": "Configurações",
"settingsPersistentTokenRegenerated": "Token persistente regenerado",
"settingsQrFetched": "Payload do QR obtido",
"settingsRemoteActions1": "[C] ativar provedor [V] iniciar [X] parar [P] token persistente [L] token de curta duração",
"settingsRemoteActions2": "[U] transferir URL [K] transferir QR [R] atualizar",
"settingsRemoteAuthUrl": "URL de autenticação:",
"settingsRemoteHeader": "──── Remoto ────",
"settingsRemoteOff": "desativado",
"settingsRemoteOn": "ativado",
"settingsRemotePersistentToken": "Token persistente:",
"settingsRemoteProvider": "Provedor:",
"settingsRemoteProviderNone": "nenhum",
"settingsRemoteShortLived": "Curta duração:",
"settingsRemoteShortLivedExpires": "Expiração de curta duração:",
"settingsRemoteState": "Estado:",
"settingsRemoteStateUnknown": "desconhecido",
"settingsRemoteStatusRefreshed": "Status remoto atualizado",
"settingsRemoteToken": "Token:",
"settingsRemoteTunnelUrl": "URL do túnel:",
"settingsRemoteUrlFetched": "URL remota obtida",
"settingsSaved": "Salvo",
"settingsSavingInProgress": "Salvando…",
"settingsSelectProviderFirst": "Selecione primeiro um provedor remoto",
"settingsShortLivedTokenGenerated": "Token de curta duração gerado",
"settingsTtlHints": "[Enter] gerar [Esc] cancelar",
"settingsTtlLabel": "TTL ms:",
"settingsTtlMustBePositive": "O TTL deve ser um número positivo (ms)",
"settingsTunnelStarting": "Túnel remoto iniciando",
"settingsTunnelStopped": "Túnel remoto parado",
"settingsUnavailable": "Configurações não disponíveis.",
"statsPanelTitle": "Estatísticas",
"statsUnavailable": "Estatísticas não disponíveis.",
"statusBarHelp": "Tab alternar painel · 1-5 saltar",
"stepDurationDone": " ({{status}} — {{duration}})",
"stepDurationRunning": " (em execução — {{duration}})",
"switchProjectsHint": "Pressione [{{key}}] para trocar de projeto.",
"systemCopyTokenHint": "copiar token · selecione o texto do token para copiar manualmente",
"systemDragToSelect": "arraste para selecionar",
"systemInfoUnavailable": "Informações do sistema não disponíveis.",
"systemOpenUrl": "abrir URL",
"systemPanelTitle": "Sistema",
"tabAgents": "Agentes",
"tabBoard": "Quadro",
"tabFiles": "Arquivos",
"tabGit": "Git",
"tabMain": "Principal",
"tabSettings": "Configurações",
"taskCardUntitled": "(sem título)",
"taskDetailBack": "[Esc] voltar",
"taskDetailLoading": "Carregando detalhes da tarefa…",
"taskDetailLogsLive": "[ao vivo]",
"taskDetailLogsPaused": "[pausado]",
"taskDetailLogsSectionHeader": "── Registros ───────────────────────────────────────",
"taskDetailNoLogEntries": "(ainda sem entradas de registro)",
"taskDetailNoSteps": "(ainda sem etapas)",
"taskDetailScrollHints": "↑↓/j/k rolar · PgUp/PgDn meia página · g topo · G fim · Esc voltar",
"taskDetailStepsSectionHeader": "── Etapas ──────────────────────────────────────",
"taskDetailUnavailable": "Tarefa não está mais disponível — Esc para voltar",
"updateAvailable": "Atualização disponível: v{{currentVersion}} → v{{latestVersion}}. Execute `fn update` para um CLI instalado, ou dê pull neste checkout de código-fonte.",
"utilitiesAdjustThreshold": "Ajustar Limite ({{pct}}%)",
"utilitiesAutoKillVitest": "Auto-Encerrar Vitest >{{pct}}% Mem: {{state}}",
"utilitiesClearLogs": "Limpar Registros",
"utilitiesHelp": "Ajuda",
"utilitiesKillVitest": "Encerrar Processos Vitest",
"utilitiesPanelTitle": "Utilitários",
"utilitiesRefreshStats": "Atualizar Estatísticas",
"utilitiesToggleEnginePause": "Alternar Pausa do Motor"
}
}

View File

@@ -0,0 +1,244 @@
{
"actions": {
"send": "Enviar"
},
"agents": {
"ratings": {
"trendDeclining": "↓ Em declínio",
"trendImproving": "↑ Melhorando",
"trendInsufficient": "Dados insuficientes",
"trendStable": "→ Estável"
},
"reflections": {
"triggerManual": "Manual",
"triggerPeriodic": "Periódico",
"triggerPostTask": "Pós-tarefa",
"triggerUserRequested": "Solicitado pelo usuário"
},
"time": {
"daysAgo_one": "há {{count}}d",
"daysAgo_other": "há {{count}}d",
"hoursAgo_one": "há {{count}}h",
"hoursAgo_other": "há {{count}}h",
"inAMoment": "em instantes",
"inDays_one": "em {{count}}d",
"inDays_other": "em {{count}}d",
"inHours_one": "em {{count}}h",
"inHours_other": "em {{count}}h",
"inMinutes_one": "em {{count}}m",
"inMinutes_other": "em {{count}}m",
"justNow": "agora mesmo",
"minutesAgo_one": "há {{count}}m",
"minutesAgo_other": "há {{count}}m"
}
},
"board": {
"rejection": {
"capacityExhausted": "Essa coluna está com capacidade esgotada. Tente novamente quando uma vaga se abrir.",
"guardRejected": "Este movimento não é permitido pelo fluxo de trabalho.",
"mergeBlocked": "Esta tarefa está bloqueada para conclusão até que sua etapa de merge termine.",
"unknownColumn": "Essa coluna não existe no fluxo de trabalho desta tarefa.",
"unplannedForExecution": "Esta tarefa ainda não está pronta para execução — o planejamento ou a revisão do plano ainda está pendente.",
"workflowMismatch": "Arrastar não pode mover um cartão entre fluxos de trabalho. Use o seletor de fluxo de trabalho."
}
},
"chat": {
"failedToGetResponse": "Falha ao obter resposta",
"failureReferenceId": "ID",
"failureReferenceKind": "Tipo",
"failureReferenceLabel": "Referência",
"failureReferenceMetaLabel": "Rótulo",
"openMailboxMessage": "Abrir mensagem da caixa de entrada",
"toolCallArgsPrefix": "args",
"toolCallResultPrefix": "resultado",
"toolCallsCount_one": "{{count}} chamada de ferramenta",
"toolCallsCount_other": "{{count}} chamadas de ferramenta",
"toolCallsHeader": "Chamadas de ferramenta",
"toolCallStatusCompleted": "concluído",
"toolCallStatusError": "erro",
"toolCallStatusErrors": "erros",
"toolCallStatusRunning": "em execução",
"viewFailureDetails": "Ver detalhes da falha"
},
"commandCenter": {
"range": {
"allTime": "Todo o período",
"last24h": "Últimas 24h",
"last30d": "Últimos 30 dias",
"last7d": "Últimos 7 dias"
}
},
"health": {
"anomaly": {
"duplicateActiveId": "ID de tarefa ativa duplicado",
"idInBothStorages": "ID de tarefa presente no armazenamento ativo e arquivado",
"sequenceOverlap": "A próxima sequência do alocador sobrepõe um ID de tarefa existente",
"unknownPrefix": "Linha de tarefa usa um prefixo fora do estado do alocador"
}
},
"inline": {
"connecting": "Conectando",
"error": "Erro",
"offline": "Offline",
"online": "Online"
},
"labels": {
"name": "Nome"
},
"merge": {
"unknown": "Desconhecido"
},
"missions": {
"autopilotStateActivating": "Ativando fatia",
"autopilotStateCompleting": "Concluindo",
"autopilotStateInactive": "Inativo",
"autopilotStateUnknown": "Desconhecido",
"autopilotStateWatching": "Observando",
"interviewStatusAwaitingInput": "Aguardando entrada",
"interviewStatusComplete": "Plano pronto",
"interviewStatusError": "Precisa de nova tentativa",
"interviewStatusGenerating": "Gerando plano",
"runHelperActive": "Ao parar, as tarefas vinculadas são pausadas e a missão é marcada como bloqueada.",
"runHelperBlocked": "Ao retomar, a missão é reativada e a execução continua.",
"runHelperPlanning": "Ao iniciar, a primeira fatia é ativada para que o trabalho possa começar."
},
"models": {
"messages": {
"modelSetTo": "Modelo de {{label}} definido para {{provider}}/{{modelId}}",
"modelSetToDefault": "Modelo de {{label}} definido para o padrão"
}
},
"nodes": {
"auth": {
"differ": "As credenciais de autenticação são diferentes",
"differProviders": "As credenciais de autenticação são diferentes: {{providers}}",
"match": "As credenciais de autenticação coincidem",
"notSynced": "Autenticação não sincronizada"
},
"status": {
"connecting": "Conectando",
"creating": "Criando",
"deleting": "Excluindo",
"error": "Erro",
"exited": "Encerrado",
"offline": "Offline",
"online": "Online",
"recreating": "Recriando",
"running": "Em execução",
"stopped": "Parado"
}
},
"nodeStatus": {
"connecting": "Conectando",
"error": "Erro",
"offline": "Offline",
"online": "Online",
"unknown": "Desconhecido"
},
"research": {
"providerGitHub": "GitHub",
"providerLlmSynthesis": "Síntese por LLM",
"providerLocalDocs": "Documentos locais",
"providerPageFetch": "Busca de página",
"providerWebSearch": "Pesquisa na Web"
},
"routing": {
"policyLabel": {
"block": "Bloquear execução",
"fallback": "Recorrer ao local",
"notConfigured": "Não configurado"
}
},
"settings": {
"nodeRouting": {
"statusConnecting": "Conectando",
"statusError": "Erro",
"statusOffline": "Offline",
"statusOnline": "Online"
}
},
"setup": {
"apiKeyFormatError": "As chaves da {{providerName}} devem seguir este formato: {{hint}} (ex.: {{example}})",
"apiKeyLabel": {
"fallback": "Chave de API",
"kimiCoding": "Chave de API do Kimi",
"minimax": "Chave de API do MiniMax",
"ollama": "Endpoint do Ollama",
"openai": "Chave de API da OpenAI",
"openrouter": "Chave de API do OpenRouter",
"zai": "Chave de API da Zhipu AI"
},
"apiKeyPlaceholder": {
"fallback": "Digite a chave de API",
"kimiCoding": "Digite sua chave de API do Kimi",
"minimax": "Digite sua chave de API do MiniMax",
"zai": "Digite sua chave de API da Zhipu AI"
},
"apiKeyRequired": "A chave de API é obrigatória",
"apiKeySetup": {
"fallback": "Digite sua chave de API para este provedor.",
"kimiCoding": "Crie sua chave de API nas configurações de conta da plataforma Moonshot.",
"minimax": "Gere uma chave de API no console de desenvolvedor da plataforma MiniMax.",
"ollama": "Digite a URL do endpoint do Ollama (por exemplo, http://localhost:11434).",
"openai": "Crie uma chave de API no painel da OpenAI, em API keys.",
"openrouter": "Crie uma chave de API na página de gerenciamento de chaves da sua conta OpenRouter.",
"zai": "Crie uma chave de API nas configurações de conta da plataforma aberta da Zhipu AI."
},
"apiKeyUsage": {
"fallback": "Usada pelo Fusion para autenticar solicitações a este provedor",
"kimiCoding": "Usada para modelos Kimi/Moonshot AI na execução e no planejamento de tarefas",
"minimax": "Usada para modelos MiniMax na execução de tarefas",
"ollama": "Conecta à sua instância local do Ollama",
"openai": "Usada para modelos GPT na execução e no planejamento de tarefas",
"openrouter": "Roteia para múltiplos provedores de modelos de IA através de uma única chave",
"zai": "Usada para modelos GLM na execução de tarefas"
},
"providerDesc": {
"anthropic": "Modelos Claude — fortes em raciocínio, análise e código",
"fallback": "Provedor de IA — conecte-se para começar a usar modelos de IA",
"gemini": "Modelos Gemini — multimodais com forte raciocínio",
"google": "Modelos Gemini — multimodais com forte raciocínio",
"kimi": "Kimi da Moonshot AI — capacidades de contexto longo",
"kimiCoding": "Kimi da Moonshot AI — capacidades de contexto longo",
"minimax": "Modelos MiniMax — custo-benefício para uso de alto volume",
"moonshot": "Kimi da Moonshot AI — capacidades de contexto longo",
"ollama": "Execute modelos de código aberto localmente na sua máquina",
"openai": "Modelos GPT — versáteis para uma ampla variedade de tarefas",
"openaiCodex": "Modelos Codex da OpenAI — otimizados para tarefas de programação",
"openrouter": "OpenRouter — roteia solicitações entre múltiplos provedores de IA",
"zai": "Modelos GLM da Zhipu AI — forte suporte multilíngue"
}
},
"taskForm": {
"nodeStatusConnecting": "Conectando",
"nodeStatusError": "Erro",
"nodeStatusOffline": "Offline",
"nodeStatusOnline": "Online"
},
"taskReview": {
"never": "Nunca",
"refreshSourceBackground": "Segundo plano",
"refreshSourceInitialLoad": "Carregamento inicial",
"refreshSourceManual": "Manual"
},
"workflowNodes": {
"summaryAwaitInput": "Aguarda entrada do usuário",
"summaryCodeDefault": "TypeScript",
"summaryDefaultModel": "Modelo padrão",
"summaryGateAdvisory": "Consultivo",
"summaryGateBlocks": "Gate (bloqueia)",
"summaryHoldRelease": "Liberação: {{release}}",
"summaryLoopIterations_one": "{{count}}x",
"summaryLoopIterations_other": "{{count}}x",
"summaryLoopUntilContains": "até conter \"{{value}}\"",
"summaryLoopUntilMatches": "até corresponder a /{{pattern}}/",
"summaryNotConfigured": "Não configurado",
"summaryReviewType": "revisão de {{type}}",
"summarySeamExecute": "Executar (motor)",
"summarySeamMerge": "Limite de merge",
"summarySeamPlanning": "Planejar (motor)",
"summarySeamReview": "Revisar (motor)",
"summarySeamStepExecute": "Executar etapa (motor)",
"summarySeamUnknown": "Seam: {{seam}}"
}
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -33,6 +33,8 @@ describe("@fusion/i18n config", () => {
expect(FALLBACK_LNG.zh).toEqual(["zh-CN"]);
expect(FALLBACK_LNG["zh-Hans"]).toEqual(["zh-CN"]);
expect(FALLBACK_LNG["zh-Hant"]).toEqual(["zh-TW"]);
expect(FALLBACK_LNG.pt).toEqual(["pt-BR"]);
expect(FALLBACK_LNG["pt-PT"]).toEqual(["pt-BR"]);
expect(FALLBACK_LNG.default).toEqual(["en"]);
});
@@ -94,4 +96,11 @@ describe("normalizeToSupportedLocale", () => {
expect(normalizeToSupportedLocale("de-DE")).toBeUndefined();
expect(normalizeToSupportedLocale("")).toBeUndefined();
});
it("resolves any-region Portuguese to pt-BR", () => {
expect(normalizeToSupportedLocale("pt")).toBe("pt-BR");
expect(normalizeToSupportedLocale("pt-PT")).toBe("pt-BR");
expect(normalizeToSupportedLocale("pt_PT.UTF-8")).toBe("pt-BR");
expect(normalizeToSupportedLocale("ptx")).toBeUndefined();
});
});

View File

@@ -1,7 +1,7 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
const locales = ["en", "es", "fr", "ko", "zh-CN", "zh-TW"] as const;
const locales = ["en", "es", "fr", "ko", "pt-BR", "zh-CN", "zh-TW"] as const;
describe("database health banner catalogs", () => {
it.each(locales)("uses renderable rich-text guidance in %s", (locale) => {

View File

@@ -25,7 +25,7 @@ function readCatalogs(locale: string, namespaces = listNamespaces()): NamespaceC
describe("i18n key parity", () => {
it("passes for the live catalogs across all supported locales and en namespaces", () => {
expect([...SUPPORTED_LOCALES]).toEqual(["en", "zh-CN", "zh-TW", "fr", "es", "ko"]);
expect([...SUPPORTED_LOCALES]).toEqual(["en", "zh-CN", "zh-TW", "fr", "es", "ko", "pt-BR"]);
expect(listNamespaces()).toEqual(["app", "cli", "common", "errors"]);
const enCatalogs = readCatalogs("en");

View File

@@ -12,6 +12,9 @@ import fr_errors from "../locales/fr/errors.json";
import ko_common from "../locales/ko/common.json";
import ko_cli from "../locales/ko/cli.json";
import ko_errors from "../locales/ko/errors.json";
import pt_BR_common from "../locales/pt-BR/common.json";
import pt_BR_cli from "../locales/pt-BR/cli.json";
import pt_BR_errors from "../locales/pt-BR/errors.json";
import zh_CN_common from "../locales/zh-CN/common.json";
import zh_CN_cli from "../locales/zh-CN/cli.json";
import zh_CN_errors from "../locales/zh-CN/errors.json";
@@ -40,6 +43,11 @@ export const cliResources = {
cli: ko_cli,
errors: ko_errors,
},
"pt-BR": {
common: pt_BR_common,
cli: pt_BR_cli,
errors: pt_BR_errors,
},
"zh-CN": {
common: zh_CN_common,
cli: zh_CN_cli,

View File

@@ -35,6 +35,8 @@ export const FALLBACK_LNG: FallbackLngObjList = {
"zh-Hans": ["zh-CN"],
"zh-Hant": ["zh-TW"],
zh: ["zh-CN"],
pt: ["pt-BR"],
"pt-PT": ["pt-BR"],
default: [DEFAULT_LOCALE],
};
@@ -57,6 +59,16 @@ export function normalizeToSupportedLocale(tag: string): Locale | undefined {
if (isLocale(norm)) return norm;
const lower = norm.toLowerCase();
/*
FNXC:I18nLocales 2026-08-07-22:55:
normalizeToSupportedLocale had an explicit zh branch but no pt one, so the FALLBACK_LNG
pt/pt-PT entries were dead on both the CLI env-detection and dashboard browser-detection
paths (both funnel through this function, which returned undefined for base "pt"). Any
Portuguese region tag (pt, pt-PT, pt_PT.UTF-8) resolves to pt-BR, the only Portuguese
catalog Fusion ships; exact "pt-BR" already matches via the isLocale(norm) check above.
*/
const base = lower.split("-")[0];
if (base === "pt") return "pt-BR";
if (lower.startsWith("zh")) {
// An explicit Simplified script subtag wins over region: zh-Hans-HK /
// zh-Hans-MO are valid BCP-47 for Simplified Chinese used in HK/Macau.
@@ -72,7 +84,6 @@ export function normalizeToSupportedLocale(tag: string): Locale | undefined {
return "zh-CN";
}
const base = lower.split("-")[0];
return isLocale(base) ? base : undefined;
}