chore(ui): translate hardcoded UI strings to pt-BR#4433
chore(ui): translate hardcoded UI strings to pt-BR#4433ramonmatias19 wants to merge 1 commit intopaperclipai:masterfrom
Conversation
Greptile SummaryThis 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."
Confidence Score: 3/5Not 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
|
| 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, " "); |
There was a problem hiding this 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.
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.| <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> |
There was a problem hiding this 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.
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.| 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; |
There was a problem hiding this 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.
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.70e51fe to
5011fcf
Compare
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.
5011fcf to
0896679
Compare
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.
Test plan
Follow-up
i18n.tsbundles in a separate issue