# Draft: l10n(pt-BR): pilot translation — Payments Direct 2.0 (@v2026.03) [DOC-6061]

## 1. What this is

Proof-of-concept pilot for the semi-automatic pt-BR localization pipeline for Ripple
Payments Direct 2.0 documentation (`@v2026.03`). This MR is a **draft** and is **not
intended to merge**. It exists to demonstrate the internal translation system end to end
and to route the pilot pages through native review. Future sessions branch off
`l10n/pt-br/pilot` rather than off a merge, so the branch is kept self-contained
(scaffolding, termbase, manifest, chrome overrides, and translations all present).

- Branch: `l10n/pt-br/pilot` (based on `l10n/pt-br/bootstrap`; neither merges to default).
- Jira: DOC-6061 (epic DOC-6059). Config lives here rather than in DOC-6062 per the bundle
decision.
- Reviewers: Tiago Leite and Luis Pain (**pending confirmation — left unassigned**).
`payment-identities.md` needs the extra-care terminology pass.
- English source is unmodified. Source defects are reported below, not fixed.


## 2. Scope of this MR

- **Four** pilot pages translated into `@l10n/pt-BR/products/payments-direct-2/@v2026.03/`
(Markdown-only pilot — the 5th file, the API-reference `.yml`, was deferred; see §5).
- `@l10n/pt-BR/translations.yaml` chrome-key overrides (pt-PT defaults corrected to pt-BR).
- `.l10n-sync/manifest.json` updated with translation-time source-section hashes.
- Config: `.vale.ini` exclusion and the `redocly.yaml` `l10n` block (preview only).
- Not in this MR: sidebar labels (docs-team dependency), any out-of-scope product, any
`@v2025.11` / `@v2026.04` content, TM entries.


## 3. Files changed (CLAUDE.md §3: source files / sections changed)

| Source path (`@v2026.03/`) | Type | Sections translated | Screenshots referenced | Notes |
|  --- | --- | --- | --- | --- |
| `introduction/concepts/payment-identities.md` | conceptual (terminology stress) | 36/36 | 0 | Precedent-setter; extra review |
| `api-docs/developer-guides/create-a-payment.md` | developer guide | 25/25 | 0 | Code blocks byte-identical except 2 translated comments |
| `api-docs/payments-direct-api/payments-direct-2-api.yml` | API reference (subset) | **deferred** | n/a | Phase 2 render check did not pass locally — see §5 |
| `api-docs/integration-resources/latam/br.md` | Brazil corridor | 3/3 | 0 | Small page |
| `api-docs/integration-resources/latam/br/brl.md` | Brazil corridor | 4/4 | 0 | Small page; purpose-code enum table |


Config and pipeline files also changed:

- `@l10n/pt-BR/translations.yaml`: ~23 chrome keys overridden to pt-BR (26 lines changed).
- `.l10n-sync/manifest.json`: 5 files, 69 hashed sections recorded (4 translated, 1 deferred).
- `.vale.ini`, `redocly.yaml` (see §11).
- `.l10n-sync/PILOT-REPORT.md` (this session's report); `.l10n-sync/templates/` and this
filled MR-description working copy.


## 4. English source reference (CLAUDE.md §3: the English diff or link)

English is unchanged by this MR. The pt-BR files mirror these source paths at ref
`3dc80784c` (tip of `l10n/pt-br/bootstrap`; English source identical to
`main-enterprise-product-docs` for these paths):

- `products/payments-direct-2/@v2026.03/introduction/concepts/payment-identities.md`
- `products/payments-direct-2/@v2026.03/api-docs/developer-guides/create-a-payment.md`
- `products/payments-direct-2/@v2026.03/api-docs/integration-resources/latam/br.md`
- `products/payments-direct-2/@v2026.03/api-docs/integration-resources/latam/br/brl.md`


## 5. Mirrored-OpenAPI render check (Phase 2, gating)

Result: **FELL BACK TO MARKDOWN-ONLY**

- The mirrored `.yml` (byte-for-byte, only `info.description` translated) linted clean and
was valid YAML, but `npx @redocly/cli preview` **crashed** on the OAS loader
(`Error in "load-oas" loader: "undefined" is not valid JSON`) before any server started.
- **Controlled baseline test:** a clean bootstrap tree (no `l10n` block, no mirrored spec)
crashes **identically** — so the failure is **pre-existing on the English build in this
local environment, not caused by the mirror**.
- Root cause: `info.description` contains `{% $env.PUBLIC_VAR_RPD %}`; the local preview's
OAS menu-builder can't resolve `$env` in a spec description (`Markdoc.fromJSON` receives
`"undefined"`). Hosted Reunite tolerates this via `reunite.ignoreMarkdocErrors: true`; the
local NPX preview's OAS loader does not.
- **Action taken (owner decision):** removed the mirrored spec, shipped the 4 Markdown pages
only, deferred the API-reference file. The `.yml` stays in `scope.json` (`translated: false`); target dir keeps its `.gitkeep`.
- **Redocly support item:** local `@redocly/cli preview` cannot render any OAS whose
`description` uses `{% $env %}`, in EN or pt-BR. Validate mirrored-OAS localization on the
Reunite MR preview.


Preview evidence: local preview unavailable (crashes as above); **defer render validation to
the Reunite preview build for this MR**.

## 6. Structural preservation (CLAUDE.md §5) — confirm each

- [x] Heading hierarchy and section count preserved per page (verified: 34/34, 23/23, 1/1,
2/2 headings src↔dst).
- [x] Markdoc tags left in place, names/attributes untranslated (structural attrs `type=`,
`width=` untouched; visible-title `name=`/`label=` values translated — see reviewer
item).
- [x] Code blocks byte-for-byte except explanatory comments (verified via code-fence diff:
only the 2 intended comment lines differ).
- [x] Front matter keys unchanged and in the same order; only `title` / `description` values
translated (`toc` block in create-a-payment left as config).
- [x] `{% $env.PUBLIC_VAR_... %}` product-name variables preserved byte-for-byte (counts
match: 1 / 3 / 0 / 0).
- [x] Do-Not-Translate terms untouched; wire-format literals in samples not reformatted;
prose numbers localized (`10,000 USD` → `10.000 USD`).
- [x] `#fragment` links inside pt-BR copies rewritten to translated slugs (anchor policy
§5.3); cross-page fragment to untranslated `quotes.md` kept English; no dangling
same-page fragments. Rewritten links: **2** (accent-slug verification deferred to
Reunite preview).


## 7. Terminology and termbase (CLAUDE.md §3: new termbase entries proposed)

Proposed new entries, harvested mostly from `payment-identities.md`. All Seed status,
pending native-reviewer promotion.

| EN | pt-BR | Domain | First seen (page) | Rationale / ambiguity note | Status |
|  --- | --- | --- | --- | --- | --- |
| payment identity | identidade de pagamento | API / Identity | payment-identities | Core concept | Seed |
| identity | identidade | API / Identity | payment-identities |  | Seed |
| financial instrument | instrumento financeiro | API / Identity | payment-identities | "where money goes" vs identity "who" | Seed |
| payout rail | trilho de pagamento | API / Payments | payment-identities | **Precedent.** Alt: keep "rails" (EN) or "meios de pagamento". High frequency | Seed |
| payout method | método de pagamento | API / Payments | payment-identities |  | Seed |
| first-party (payment) | (pagamento de) primeira parte | API / Payments | create-a-payment | **Precedent.** Alt: "em nome próprio" | Seed |
| third-party (payment) | (pagamento de) terceiros | API / Payments | create-a-payment | **Precedent.** Alt: "em nome de terceiros" | Seed |
| PII | informações de identificação pessoal (PII) | Compliance / PII | payment-identities | Acronym kept | Seed |
| quote collection | coleção de cotações | FX / API | create-a-payment |  | Seed |
| natural persons | pessoas físicas | PII / Legal | payment-identities | BR legal register | Seed |
| versioning | versionamento | API | payment-identities |  | Seed |
| lifecycle (state) | (estado do) ciclo de vida | API | payment-identities |  | Seed |
| deduplication | deduplicação | API | payment-identities |  | Seed |
| idempotency | idempotência | API | payment-identities | (cf. termbase "chave de idempotência") | Seed |
| schema (kept EN) | schema | API docs | payment-identities | vs "esquema"; house-style call | Seed |
| timestamp (kept EN) | timestamp | API docs | payment-identities |  | Seed |
| upstream (kept EN) | upstream | API docs | payment-identities |  | Seed |
| tenant (kept EN) | tenant | API docs | create-a-payment |  | Seed |


Termbase pairs reaffirmed (already in seed termbase, applied here): originator → ordenante;
cross-border payment → pagamento internacional; purpose of payment → finalidade do
pagamento; quote → cotação; fee → tarifa; request → requisição; response → resposta.

Ambiguity-trap calls made this session: `saldo`/`balanço` (n/a — no "balance" prose);
`tarifa` used for "fee"; `requisição` for "request" throughout; `token de acesso` for
"access token" (disambiguated from crypto/OTP "token"); `chave` reserved (no Pix key in
these pages). No `reembolso`/`estorno` occurrences.

## 8. Reviewer attention items (CLAUDE.md §3)

- **`payment-identities.md` (extra-care):**
  - **payout rail → "trilho de pagamento"** — precedent; confirm vs. keeping "rails" (EN) or
"meios de pagamento". Appears ~30×.
  - **PII → "informações de identificação pessoal (PII)"** — confirm expansion + acronym.
  - **"compliance" kept in English** (auditoria e compliance / análise de compliance) —
confirm vs. "conformidade".
  - **"ordenante"** for `ORIGINATOR` role in prose — confirm vs "remetente" in role context.
  - **"schema"** kept in English ("versão do schema") — confirm vs "esquema".
- **`create-a-payment.md`:**
  - **first-party / third-party → "primeira parte / (de) terceiros"** — confirm phrasing.
  - Prose amount localized: "10,000 USD" → "10.000 USD"; wire values in samples untouched.
- **Cross-cutting (all pages):**
  - **Markdoc visible-title attributes translated** (admonition `name=`, tab `label=`);
product/feature names kept ("Identity Management v3"). Confirm this policy.
  - **Link text to out-of-scope untranslated pages kept in English** (Payout network,
Financial instruments, Create and manage identities, Funding model, Error handling) to
match English-fallback destinations. Confirm policy.
  - **Fragment-slug accents:** the 2 rewritten same-page anchors use accented slugs; verify
they resolve in the Reunite preview (local preview unavailable).


## 9. English-screenshot gap log (CLAUDE.md §5.5)

**None.** No image is referenced by any of the four translated pages (checked for `![...]`,
`images/`, `img`). The English UI screenshots noted at bootstrap are under `user-interface/`
pages, which are out of the pilot set.

Total gaps logged: **0**.

## 10. Source defects found (CLAUDE.md §9 — reported, not fixed)

Already reported at bootstrap (BOOTSTRAP-REPORT.md §5), referenced not re-filed: hardcoded
strings in the 9 Direct2 landing components; sidebar labels not localizable (no
`labelTranslationKey`); stale `redocly.yaml` ignore entries; dead `partialsFolders` entry;
empty legacy `api-docs/` tree; stock `.gitlab-ci.yml`.

Newly found during translation:

| Defect | Location | Impact on l10n | Suggested owner |
|  --- | --- | --- | --- |
| Duplicated word "of of" | `.../payment-identities.md:22` | none (cosmetic) | docs team |
| Typo "istruments" in admonition title | `.../payment-identities.md:119` | renders in title (EN + pt-BR mirrors it verbatim per structure rule) | docs team |
| Typo "requirede" | `.../create-a-payment.md:176` | none (cosmetic) | docs team |
| "Endpoint" not an `###` heading (inconsistent) | `.../create-a-payment.md:390` | minor TOC/structure | docs team |
| Stray tab-indented "3." breaks numbered list | `.../create-a-payment.md:470` | list renders wrong | docs team |
| Vale style uses unsupported `scope: link` (E201) | `ci/vale/styles/Ripple/MeaningfulLinkWords.yml:10` | Vale can't run locally | docs/tooling team |


## 11. Config changes (preview only; do not enable in production here)

**`.vale.ini`**: exclude mirrored pt-BR content so English rulesets do not flood:

```ini
[@l10n/**]
BasedOnStyles =
```

**`redocly.yaml`**: `l10n` block so the preview renders pt-BR. Present for preview only;
because this branch will not merge, production locale enablement does not happen here and
would need its staging treatment (CLAUDE.md §7.2 / bootstrap §4.4) as its own change if this
PoC is later promoted:

```yaml
l10n:
  defaultLocale: en
  locales:
    - code: en
      name: English
    - code: pt-BR
      name: Português (Brasil)
```

Portal-wide-picker note: once `pt-BR` is enabled in production, the language picker appears
on all products and out-of-scope content falls back to English. Sign-off happens in preview
per the staging decision. No picker suppression (bootstrap §4.4).

## 12. Translation memory

`tm.jsonl` is unchanged this session; TM is harvested from approved segments, not drafts.
**Open item:** because this PoC branch will not merge, the harvest trigger (currently defined
as post-merge) needs redefining to key off **reviewer approval on the draft branch**. Flagged
for the decision log; harvesting logic unchanged for now.

## 13. Pipeline / manifest

- `manifest.json` updated: 5 files, 69 sections, source hashes at translation time (4 files
`translated: true`, the deferred `.yml` `translated: false`).
- Drift check `generate-manifest.mjs --check`: **green** on the fresh set.


## 14. Review gate

Native pt-BR review required before this could ever be considered for merge. Do not
self-approve, mark ready, merge, or resolve discussions. Route to Tiago Leite and Luis Pain
once confirmed; unassigned until then.

Reviewer checklist:

- [ ] Terminology on `payment-identities.md` is correct and precedent-worthy (esp. payout
rail, PII, first-party/third-party).
- [ ] Register and variant are pt-BR (você, gerunds, no pt-PT surface forms).
- [ ] Do-Not-Translate terms and wire formats untouched.
- [ ] Chrome overrides read pt-BR (e.g. "Baixar", "aba", "Carregando...").
- [ ] Proposed termbase entries approved or amended (promote from Seed).


## 15. Open items and human calls

1. Confirm native reviewers (Tiago Leite, Luis Pain) — MR unassigned until then.
2. Mirrored-OpenAPI render outcome — verify on the Reunite MR preview; pursue the
Redocly-support item (§5) before re-attempting the API-reference file.
3. Fragment-slug accent behavior — verify the 2 rewritten anchors resolve in the Reunite
preview.
4. TM-harvest trigger redefinition for a non-merging PoC (§12).
5. Terminology sign-off / promotion from Seed after native review.
6. Chrome sweep completeness — `catalog.*` and `asyncapi.*` pt-PT defaults still pending a
dedicated pass.