Skip to content

chore(ui): translate hardcoded UI strings to pt-BR#4433

Open
ramonmatias19 wants to merge 1 commit intopaperclipai:masterfrom
ramonmatias19:feature/pt-translations
Open

chore(ui): translate hardcoded UI strings to pt-BR#4433
ramonmatias19 wants to merge 1 commit intopaperclipai:masterfrom
ramonmatias19:feature/pt-translations

Conversation

@ramonmatias19
Copy link
Copy Markdown

@ramonmatias19 ramonmatias19 commented Apr 24, 2026

⚠️ Depends on: #4428 (adds language to CreateConfigValues), #4431 (i18n module + react-i18next), #4434 (TopBarUsageChip component). Verify/e2e red on this branch because touched files reference symbols from all three. Expected sequence: #4428 + #4431 + #4434 merge → lockfile refresh bot → rebase this PR → green.

Summary

Bulk swap of English literal strings to Portuguese across dialogs, config fields, pages, and minor components (61 files). These are still hardcoded literals, not i18n.t() calls — follow-up work should migrate them to the translation bundles introduced in #4431.

Scope is strings only (labels, placeholders, toasts, breadcrumbs). No logic changes.

Depends on: #4431 (i18n bootstrap) — this PR is a content stopgap, not a replacement for the bundled translation work.

Test plan

  • Smoke-click every touched dialog / page — verify the UI still renders without layout breaks
  • Confirm no behavior regressions (this is pure strings)

Follow-up

  • Track migrating these literals into the i18n.ts bundles in a separate issue

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 24, 2026

Greptile Summary

This PR translates 61 UI files from English literals to pt-BR as a stopgap ahead of the full i18n bundle migration. The majority of the string swaps are clean, but three files contain undisclosed logic changes that contradict the PR description's claim of "no logic changes."

  • ActivityRow.tsx: ACTION_VERBS, humanizeValue, and formatVerb are added but never called — the render path still uses the original formatActivityVerb import, making these dead code with no UI effect.
  • AgentConfigForm.tsx: A net-new Idioma / language config field is introduced in both create and edit modes; this is a feature addition, not a string swap, and needs backend validation coverage.
  • useLiveRunTranscripts.ts: Log-offset tracking is changed from JS character count to UTF-8 byte count via Blob.size — a real behavioral fix that is unlabeled and has no test plan entry.

Confidence Score: 3/5

Not safe to merge as-is — three undisclosed logic changes need to be addressed, and the PR is missing required template sections (Thinking Path, Model Used, screenshots).

Two P1 findings (dead code in ActivityRow that silently drops the Portuguese verb translations, and an undocumented new Language field in AgentConfigForm) plus one borderline P1 (offset calculation change in useLiveRunTranscripts) warrant a score below 4. The PR description explicitly contradicts what the diff contains, and required CONTRIBUTING.md sections are absent.

ui/src/components/ActivityRow.tsx (dead code), ui/src/components/AgentConfigForm.tsx (undocumented Language field), ui/src/components/transcript/useLiveRunTranscripts.ts (undocumented offset logic change)

Important Files Changed

Filename Overview
ui/src/components/ActivityRow.tsx Adds ACTION_VERBS, humanizeValue, and formatVerb — all dead code; the render path still calls the existing formatActivityVerb import and the new functions are never invoked.
ui/src/components/AgentConfigForm.tsx String translations are correct, but a net-new Idioma/Language config field was added in both create and edit modes — an undocumented logic change that the PR description does not mention.
ui/src/components/transcript/useLiveRunTranscripts.ts Changes log offset tracking from JS string length to UTF-8 byte length via Blob — a real behavioral change that is unlabeled in the PR description and has no test plan entry.
ui/src/lib/utils.ts Adds locale-aware date formatting via i18n singleton; two separate imports from @/i18n can be merged into one, minor circular-dependency risk.
ui/src/pages/Auth.tsx Straightforward string translations to pt-BR; no logic changes.
ui/src/pages/ApprovalDetail.tsx Straightforward string translations to pt-BR across labels, breadcrumbs, and error fallbacks; no logic changes.
ui/src/adapters/openclaw-gateway/config-fields.tsx Field labels and option values translated to pt-BR; no logic changes.
ui/src/components/ScheduleEditor.tsx Schedule presets, day abbreviations, and description strings translated to pt-BR; no logic changes.

Comments Outside Diff (1)

  1. ui/src/lib/utils.ts, line 1-12 (link)

    P2 Two imports from @/i18n — potential module resolution risk

    import i18n from "@/i18n" and import { localeMap } from "@/i18n" can be collapsed into a single import statement. More importantly, utils.ts is a low-level utility module; importing from i18n creates a circular dependency risk if i18n.ts ever imports from utils.ts. Consider passing the locale as a parameter instead of reading it from the module singleton.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: ui/src/lib/utils.ts
    Line: 1-12
    
    Comment:
    **Two imports from `@/i18n` — potential module resolution risk**
    
    `import i18n from "@/i18n"` and `import { localeMap } from "@/i18n"` can be collapsed into a single import statement. More importantly, `utils.ts` is a low-level utility module; importing from `i18n` creates a circular dependency risk if `i18n.ts` ever imports from `utils.ts`. Consider passing the locale as a parameter instead of reading it from the module singleton.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: ui/src/components/ActivityRow.tsx
Line: 10-71

Comment:
**Dead code: `ACTION_VERBS`, `humanizeValue`, and `formatVerb` are never called**

These three additions are unreachable — line 95 still calls `formatActivityVerb` (the existing import from `../lib/activity-format`), so the new `formatVerb` function and its helpers are never invoked. The translated Portuguese verb strings silently have no effect on the rendered UI.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: ui/src/components/AgentConfigForm.tsx
Line: 547-558

Comment:
**New "Language" field is an undocumented logic change, not a string swap**

The PR description states "Scope is strings only — no logic changes," but this block adds a brand-new `Idioma` form field backed by `adapterConfig.language` in both create and edit modes. This introduces a new config key that may not be validated server-side and is not documented in the PR. It should be called out explicitly, with verification that the backend accepts and forwards `language`.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: ui/src/components/transcript/useLiveRunTranscripts.ts
Line: 209-215

Comment:
**Offset calculation changed from character count to byte count — undocumented logic change**

The PR description says "no logic changes," but this replaces `result.content.length` (JS UTF-16 code-unit count) with `new Blob([result.content]).size` (UTF-8 byte count). If the server uses byte-based offsets this is a real fix, but it is a behavioral change with no test plan entry and no mention in the PR description. If the server actually uses character-based offsets, this will now under-advance the offset for multi-byte characters and repeat log lines.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: ui/src/lib/utils.ts
Line: 1-12

Comment:
**Two imports from `@/i18n` — potential module resolution risk**

`import i18n from "@/i18n"` and `import { localeMap } from "@/i18n"` can be collapsed into a single import statement. More importantly, `utils.ts` is a low-level utility module; importing from `i18n` creates a circular dependency risk if `i18n.ts` ever imports from `utils.ts`. Consider passing the locale as a parameter instead of reading it from the module singleton.

```suggestion
import i18n, { localeMap } from "@/i18n";
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "chore(ui): translate hardcoded UI string..." | Re-trigger Greptile

Comment on lines +10 to +71
const ACTION_VERBS: Record<string, string> = {
"issue.created": "criou",
"issue.updated": "atualizou",
"issue.checked_out": "assumiu",
"issue.released": "liberou",
"issue.comment_added": "comentou em",
"issue.attachment_added": "anexou arquivo em",
"issue.attachment_removed": "removeu anexo de",
"issue.document_created": "criou documento para",
"issue.document_updated": "atualizou documento em",
"issue.document_deleted": "excluiu documento de",
"issue.commented": "comentou em",
"issue.deleted": "excluiu",
"agent.created": "criou",
"agent.updated": "atualizou",
"agent.paused": "pausou",
"agent.resumed": "retomou",
"agent.terminated": "encerrou",
"agent.key_created": "criou chave API para",
"agent.budget_updated": "atualizou orçamento de",
"agent.runtime_session_reset": "reiniciou sessão de",
"heartbeat.invoked": "invocou heartbeat para",
"heartbeat.cancelled": "cancelou heartbeat para",
"approval.created": "solicitou aprovação",
"approval.approved": "aprovou",
"approval.rejected": "rejeitou",
"project.created": "criou",
"project.updated": "atualizou",
"project.deleted": "excluiu",
"goal.created": "criou",
"goal.updated": "atualizou",
"goal.deleted": "excluiu",
"cost.reported": "relatou custo para",
"cost.recorded": "registrou custo para",
"company.created": "criou empresa",
"company.updated": "atualizou empresa",
"company.archived": "arquivou",
"company.budget_updated": "atualizou orçamento de",
};

function humanizeValue(value: unknown): string {
if (typeof value !== "string") return String(value ?? "none");
return value.replace(/_/g, " ");
}

function formatVerb(action: string, details?: Record<string, unknown> | null): string {
if (action === "issue.updated" && details) {
const previous = (details._previous ?? {}) as Record<string, unknown>;
if (details.status !== undefined) {
const from = previous.status;
return from
? `alterou status de ${humanizeValue(from)} para ${humanizeValue(details.status)} em`
: `alterou status para ${humanizeValue(details.status)} em`;
}
if (details.priority !== undefined) {
const from = previous.priority;
return from
? `alterou prioridade de ${humanizeValue(from)} para ${humanizeValue(details.priority)} em`
: `alterou prioridade para ${humanizeValue(details.priority)} em`;
}
}
return ACTION_VERBS[action] ?? action.replace(/[._]/g, " ");
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.

P1 Dead code: ACTION_VERBS, humanizeValue, and formatVerb are never called

These three additions are unreachable — line 95 still calls formatActivityVerb (the existing import from ../lib/activity-format), so the new formatVerb function and its helpers are never invoked. The translated Portuguese verb strings silently have no effect on the rendered UI.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/ActivityRow.tsx
Line: 10-71

Comment:
**Dead code: `ACTION_VERBS`, `humanizeValue`, and `formatVerb` are never called**

These three additions are unreachable — line 95 still calls `formatActivityVerb` (the existing import from `../lib/activity-format`), so the new `formatVerb` function and its helpers are never invoked. The translated Portuguese verb strings silently have no effect on the rendered UI.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread ui/src/components/AgentConfigForm.tsx Outdated
Comment on lines +547 to +558
<DraftInput
value={eff(
"adapterConfig",
"language",
String(config.language ?? ""),
)}
onCommit={(v) => mark("adapterConfig", "language", v || undefined)}
immediate
className={inputClass}
placeholder="ex. Português (Brasil), Español, English"
/>
</Field>
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.

P1 New "Language" field is an undocumented logic change, not a string swap

The PR description states "Scope is strings only — no logic changes," but this block adds a brand-new Idioma form field backed by adapterConfig.language in both create and edit modes. This introduces a new config key that may not be validated server-side and is not documented in the PR. It should be called out explicitly, with verification that the backend accepts and forwards language.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/AgentConfigForm.tsx
Line: 547-558

Comment:
**New "Language" field is an undocumented logic change, not a string swap**

The PR description states "Scope is strings only — no logic changes," but this block adds a brand-new `Idioma` form field backed by `adapterConfig.language` in both create and edit modes. This introduces a new config key that may not be validated server-side and is not documented in the PR. It should be called out explicitly, with verification that the backend accepts and forwards `language`.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 209 to +215
return;
}
if (result.content.length > 0) {
logOffsetByRunRef.current.set(run.id, offset + result.content.length);
// Use byte length (not JS string length) since the server offset is byte-based.
// new Blob is used because TextEncoder().encode().byteLength would also work but
// Blob is available in all browsers and avoids allocating a full Uint8Array.
const byteLength = new Blob([result.content]).size;
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.

P1 Offset calculation changed from character count to byte count — undocumented logic change

The PR description says "no logic changes," but this replaces result.content.length (JS UTF-16 code-unit count) with new Blob([result.content]).size (UTF-8 byte count). If the server uses byte-based offsets this is a real fix, but it is a behavioral change with no test plan entry and no mention in the PR description. If the server actually uses character-based offsets, this will now under-advance the offset for multi-byte characters and repeat log lines.

Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/components/transcript/useLiveRunTranscripts.ts
Line: 209-215

Comment:
**Offset calculation changed from character count to byte count — undocumented logic change**

The PR description says "no logic changes," but this replaces `result.content.length` (JS UTF-16 code-unit count) with `new Blob([result.content]).size` (UTF-8 byte count). If the server uses byte-based offsets this is a real fix, but it is a behavioral change with no test plan entry and no mention in the PR description. If the server actually uses character-based offsets, this will now under-advance the offset for multi-byte characters and repeat log lines.

How can I resolve this? If you propose a fix, please make it concise.

@ramonmatias19 ramonmatias19 force-pushed the feature/pt-translations branch 3 times, most recently from 70e51fe to 5011fcf Compare April 24, 2026 21:24
Bulk swap of English literal strings to Portuguese across dialogs,
config fields, pages, and minor components (57 files). These are still
hardcoded literals, not i18n.t() calls — follow-up work should migrate
them to the translation bundles introduced in paperclipai#4431.

Scope is strings only (labels, placeholders, toasts, breadcrumbs). No
logic changes. Files that referenced symbols from other in-flight PRs
(AgentConfigForm, BreadcrumbBar, MobileBottomNav, lib/utils) were
excluded from this PR.
@ramonmatias19 ramonmatias19 force-pushed the feature/pt-translations branch from 5011fcf to 0896679 Compare April 24, 2026 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant