Skip to content

feat(i18n): add Brazilian Portuguese (pt-BR) locale#171

Merged
Sun-sunshine06 merged 6 commits intoOpenCoworkAI:mainfrom
DavidgFernandes:feat/pt-BR-locale
Apr 22, 2026
Merged

feat(i18n): add Brazilian Portuguese (pt-BR) locale#171
Sun-sunshine06 merged 6 commits intoOpenCoworkAI:mainfrom
DavidgFernandes:feat/pt-BR-locale

Conversation

@DavidgFernandes
Copy link
Copy Markdown
Contributor

Summary

  • Adds full Brazilian Portuguese translation (820/820 UI strings) as a third supported locale next to en and zh-CN.
  • Auto-detects pt-* system locales; users can also switch manually from the topbar toggle or Settings → Appearance → Language.
  • Default locale (DEFAULT_LOCALE) stays en; no behavior change for existing users.

What's inside

  • packages/i18n/src/locales/pt-BR.json — 820 UI strings, full parity with en.json
  • packages/templates/src/locales/pt-BR.ts — 4 built-in demos (title, description, prompt)
  • packages/templates/src/examples/locales/pt-BR.ts — 21 hub examples (title, description)
  • packages/i18n/src/index.ts — register pt-BR in availableLocales, resources, normalizeLocale (accepts pt, pt-BR, pt_br, pt-*)
  • Templates registries pointed to the new pt-BR files (no en fallback)
  • Settings.tsx dropdown + LanguageToggle.tsx cycle now include pt-BR
  • langPtBR label added to en.json and zh-CN.json so the dropdown works across all locales

Translation quality notes

  • Terminology glossary applied consistently (tweaks → Ajustes, design system → design system, snapshot → snapshot, etc.)
  • {{interpolations}} and _one/_other plural suffixes preserved
  • 32 strings kept identical to EN (product names, file paths, unit suffixes, tech jargon) — no mistranslations
  • Reviewed end-to-end for tone, grammar, and accuracy (standardized novamente, fixed redacted → redigido bug, Nota fiscal → Fatura for semantic accuracy, etc.)

Test plan

  • `pnpm lint && pnpm typecheck && pnpm test` all pass locally (pre-push hook confirms)
  • App boots with zero `missing translation` / `unsupported locale` warnings
  • Settings → Appearance → Language shows `Português (BR)`; selection persists across restart
  • Topbar globe toggle cycles `EN → ZH → PT → EN`
  • System locale `pt-BR` auto-selects pt-BR on first launch
  • Hub Examples gallery and built-in demos render in PT
  • No UI clipping from longer PT strings (sidebar, settings, onboarding)

@github-actions github-actions Bot added the area:desktop apps/desktop (Electron shell, renderer) label Apr 22, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] pt-BR locale is incomplete after being added as a selectable/apply-able locale, causing raw i18n keys to surface in provider-import/save-error UI paths instead of user-facing text. Evidence: packages/i18n/src/index.ts:22 enables pt-BR, keys are consumed at apps/desktop/src/renderer/src/components/Settings.tsx:1027, apps/desktop/src/renderer/src/components/Settings.tsx:1032, apps/desktop/src/renderer/src/components/Settings.tsx:2234, apps/desktop/src/renderer/src/components/Settings.tsx:2235, but missing in packages/i18n/src/locales/pt-BR.json:223 and packages/i18n/src/locales/pt-BR.json:285.
    Suggested fix:
    {
      "settings": {
        "providers": {
          "import": {
            "ollamaMenu": "Ollama (local)",
            "ollamaMenuDesc": "Adicionar provedor local localhost:11434",
            "ollamaDone": "Provedor Ollama adicionado"
          },
          "toast": {
            "saveFailed": "Não foi possível salvar as alterações"
          }
        }
      }
    }

Questions

  • None.

Summary

  • Review mode: initial
  • 1 issue found (major): incomplete pt-BR keyset introduces visible i18n regressions in changed locale behavior.
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs in this checkout.

Testing

  • Not run (automation). Suggested: add a Vitest parity check asserting pt-BR contains all keys from en, and a renderer test for provider import menu/toast strings under pt-BR.

open-codesign Bot

"switchToDropdown": "Escolher da lista",
"switchToManual": "Digitar manualmente"
},
"import": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Major] Missing pt-BR keys used by Settings provider flows: settings.providers.import.ollamaMenu, settings.providers.import.ollamaMenuDesc, settings.providers.import.ollamaDone, and settings.providers.toast.saveFailed.

These keys are now reachable because pt-BR is enabled globally; missing keys will render fallback key text in UI.

Suggested fix:

"import": {
  "ollamaMenu": "Ollama (local)",
  "ollamaMenuDesc": "Adicionar provedor local localhost:11434",
  "ollamaDone": "Provedor Ollama adicionado"
},
"toast": {
  "saveFailed": "Não foi possível salvar as alterações"
}

@github-actions github-actions Bot added docs Documentation area:ui packages/ui (design system) labels Apr 22, 2026
@Sun-sunshine06
Copy link
Copy Markdown
Collaborator

Hey @DavidgFernandes! Thanks for this great work adding Brazilian Portuguese locale 🇧🇷

I've fixed the failing DCO check by adding to all commits (rebase done while preserving your original authorship for every commit). The DCO check should pass now.

Review:

This is a really high-quality contribution:

  • ✅ Full 820/820 UI strings translated
  • ✅ Correct locale normalization for , , , all handled properly
  • ✅ All template/examples translations are included and correctly registered in the registries
  • ✅ Language toggle cycle updated correctly
  • ✅ Language label added to all existing locale files so it shows up properly in the dropdown regardless of current language
  • ✅ Your translation quality notes show great attention to detail — consistent terminology, preserved interpolations/plurals, kept technical terms in English where appropriate
  • ✅ All existing CI checks (lint/typecheck/test) pass

Everything looks ready to go! Welcome to the project contributor list 🎉

@Sun-sunshine06
Copy link
Copy Markdown
Collaborator

Hey @DavidgFernandes! Thanks for this great work adding Brazilian Portuguese locale 🇧🇷

I've fixed the failing DCO check by adding Signed-off-by to all commits (rebase done while preserving your original authorship for every commit). The DCO check should pass now.

Review:

This is a really high-quality contribution:

  • ✅ Full 820/820 UI strings translated
  • ✅ Correct locale normalization for pt, pt-BR, pt_br, pt-* all handled properly
  • ✅ All template/examples translations are included and correctly registered in the registries
  • ✅ Language toggle cycle updated correctly
  • ✅ Language label added to all existing locale files so it shows up properly in the dropdown regardless of current language
  • ✅ Your translation quality notes show great attention to detail — consistent terminology, preserved interpolations/plurals, kept technical terms in English where appropriate
  • ✅ All existing CI checks (lint/typecheck/test) pass

Everything looks ready to go! Welcome to the project contributor list 🎉

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Auto-discovery can apply stale results from an older request after the user has already changed baseUrl / apiKey / wire, which can populate the dropdown with wrong models and auto-select the wrong default model. Evidence: apps/desktop/src/renderer/src/components/AddCustomProviderModal.tsx:123, apps/desktop/src/renderer/src/components/AddCustomProviderModal.tsx:127, apps/desktop/src/renderer/src/components/AddCustomProviderModal.tsx:133.
    Suggested fix:
    const discoveryReqId = useRef(0);
    
    async function runDiscovery(currentBaseUrl: string, currentApiKey: string, currentWire: WireApi) {
      if (!window.codesign?.config) return;
      const reqId = ++discoveryReqId.current;
      setDiscovery({ kind: 'discovering' });
      try {
        const res = await window.codesign.config.testEndpoint({
          wire: currentWire,
          baseUrl: currentBaseUrl.trim(),
          apiKey: currentApiKey.trim(),
        });
        if (reqId !== discoveryReqId.current) return; // ignore stale response
        if (res.ok && res.models.length > 0) {
          setDiscovery({ kind: 'found', models: res.models });
          if (!userPickedModel.current) setDefaultModel(pickBestModel(res.models));
        } else {
          setDiscovery({ kind: 'failed' });
        }
      } catch {
        if (reqId === discoveryReqId.current) setDiscovery({ kind: 'failed' });
      }
    }

Questions

  • None.

Summary

  • Review mode: follow-up after new commits
  • 1 issue found (major): async discovery race can surface stale model lists/defaults in the custom provider modal.
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.

Testing

  • Not run (automation). Suggested: add a Vitest/RTL test that simulates two overlapping discovery calls and asserts only the latest response updates discovery and defaultModel.

open-codesign Bot

apiKey: currentApiKey.trim(),
});
if (res.ok && res.models.length > 0) {
setDiscovery({ kind: 'found', models: res.models });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Major] This async discovery path has no stale-response guard. If request A starts, user edits endpoint, then request B starts and finishes first, request A can still finish later and overwrite discovery/defaultModel with outdated models.

Suggested fix:

const discoveryReqId = useRef(0);

async function runDiscovery(currentBaseUrl: string, currentApiKey: string, currentWire: WireApi) {
  const reqId = ++discoveryReqId.current;
  // ... fetch
  if (reqId !== discoveryReqId.current) return;
  // apply state
}

@DavidgFernandes
Copy link
Copy Markdown
Contributor Author

Thanks for the quick review and the DCO fix, @Sun-sunshine06! Really appreciate the welcome 🙏

One small thing to flag: I had pushed a 6th commit translating the 4 new Ollama strings from upstream #170 (ollamaMenu, ollamaMenuDesc, ollamaDone, saveFailed), but it looks like our two rebases overlapped and my commit got dropped when you force-pushed the DCO fix.

I'll re-push that commit now on top of your work, with Signed-off-by this time so DCO stays green. No changes to any of your existing signed commits.

- Add packages/i18n/src/locales/pt-BR.json (799 UI strings translated)
- Register pt-BR in i18n index, normalizeLocale accepts pt/pt-BR/pt-*
- Point pt-BR to enDemos/enExamples as fallback in templates registries
- Add Português (BR) option to Settings language dropdown
- Cycle LanguageToggle across en → zh-CN → pt-BR

Signed-off-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
- Translate 36 new keys (ChatGPT login flow, CLIProxyAPI preset, add-context menu, etc.)
- Restructure diagnostics.report.error from string to {generic, notesTooLong}
- Drop keys removed upstream (diagnostics.toast, comingSoon, etc.)
- Refresh chatgptLogin copy now that the feature is shipping

Signed-off-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
- Add packages/templates/src/locales/pt-BR.ts (4 built-in demos fully translated incl. prompt)
- Add packages/templates/src/examples/locales/pt-BR.ts (21 hub examples translated)
- Wire pt-BR registries to the new files (no more en fallback)
- Translate starterPrompts.* (8 prompts injected on click)
- Translate demos.*.prompt in pt-BR.json
- Translate emptyState.starterDesc.* card descriptions
- Fix opencodeFound missing {{providers}} interpolation picked up from upstream

Signed-off-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
Terminology glossary applied consistently across 50+ strings:
- Standardize 'de novo' → 'novamente' everywhere
- Standardize 'não dá para' → 'não é possível' for errors
- Map 'sign in/out' → 'entrar/sair'; 'snapshot' → 'snapshot' (kept jargon)
- Fix 'redacted' mistranslated as 'redigido' → 'com dados sensíveis removidos'
- Refresh 'crashed' → 'travou'; 'break' semantics in error boundary
- 'Rode Testar' → 'Clique em Testar' (idiomatic)
- Replace 'guardada/guardadas' → 'armazenada/armazenadas' for keys
- Tighten Ollama/error messages; add missing articles
- 'per design' → 'em cada design' (resolves EN/PT ambiguity)
- Duplicate name template: 'X cópia' → 'X (cópia)'
- Fix CODEX_TOKEN_NOT_LOGGED_IN to read as login-first message

Copy tightening:
- 'Crie com IA' → 'Crie designs com IA' (preserves EN 'design' verb)
- 'sandbox' explained in parens
- 'referencia' verb → 'faz referência a' (more natural)
- 'em torno desse alvo' → 'focando nesse alvo'
- 'Só este elemento' → 'Apenas este elemento'
- 'Inícios rápidos' → 'Sugestões rápidas'
- 'nav interativa' → 'navegação interativa'
- 'conteúdo com cara de real' → 'conteúdo realista'
- 'num follow-up' → 'em uma versão futura'
- 'Nota fiscal' → 'Fatura' (accuracy — not Brazilian tax doc)
- 'pull quotes' → 'citações em destaque'
- 'sensação de lightbox' → 'visual de lightbox'

Also: opencodeFound already fixed to include {{providers}} var;
geminiBlocked rewritten to match updated upstream EN.

All 820 keys parity, 0 interpolation mismatches, 0 plural mismatches,
32 identical-to-EN strings all legitimate (marks/paths/units/jargon).

Signed-off-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
PT-BR descriptions exceed the line-length budget after translation;
Biome auto-wraps them over two lines. Pure formatting — no content change.

Signed-off-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
…rkAI#170

Upstream PR OpenCoworkAI#170 added 4 new keys when making Ollama opt-in:
- settings.providers.import.ollamaMenu
- settings.providers.import.ollamaMenuDesc
- settings.providers.import.ollamaDone
- settings.providers.toast.saveFailed

Signed-off-by: David Fernandes <davidggffernandes@gmail.com>
@github-actions github-actions Bot removed docs Documentation area:ui packages/ui (design system) labels Apr 22, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • None.

Summary

  • Review mode: follow-up after new commits
  • No new issues found in the current diff.
  • docs/VISION.md and docs/PRINCIPLES.md: Not found in repo/docs.

Testing

  • Not run (automation). Residual risk: no added Vitest/Playwright coverage for pt-BR locale selection/cycling and localized templates/examples rendering paths.

open-codesign Bot

@Sun-sunshine06 Sun-sunshine06 merged commit b2e4bfe into OpenCoworkAI:main Apr 22, 2026
7 checks passed
@DavidgFernandes DavidgFernandes deleted the feat/pt-BR-locale branch April 22, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:desktop apps/desktop (Electron shell, renderer)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants