2 Commits

Author SHA1 Message Date
Marcos Paulo a5d9630dd8 docs: add task 10b, locale-paired props on the six full-guide blocks
verify-and-publish / gate (push) Successful in 37m12s
verify-and-publish / publish (push) Has been skipped
Task 15d stopped on a real blocker rather than working around it: the
blocks it assembles from take plain string props, so /full-guide/ cannot
render both locales without either duplicating blocks or changing a
component interface, and both are outside page-migrator scope.

Tasks 07-11 predate the language contract task 15c wrote, which is why
none of the 19 blocks is locale-aware. This narrows the fix to the six
blocks full-guide actually uses and makes the change additive, so the
already-merged call sites that pass plain strings are unaffected.

Records that /rules/ is already fully bilingual via client-side swapping
from a content collection, and that the other five pages have no language
toggle today and must not gain one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 21:36:16 +00:00
Marcos Paulo f7985bfe2a docs: task 15d attempt 2 needs the static Portuguese finished
Attempt 2 got the structure right and said plainly it had only done the
hero, stat and thesis regions in both locales. The remaining static prose
is the 102-entry `translations.pt` selector map in app.js, which is what
gives today's /full-guide/ its Portuguese.

Also records that the 55 `.en` reads in the selector detail panels are
correct and must not be changed: GuideSelector re-renders those per locale
on languagechange, so the server render only needs the initial locale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 21:25:55 +00:00
2 changed files with 117 additions and 0 deletions
@@ -0,0 +1,72 @@
# Task 10b — Locale-paired props on the six full-guide blocks
**Agent**: `component-builder` · **Model**: **Codex** **Depends on**: 10 ·
**Blocks**: 15d **Worktree**:
`.agents/scripts/worktree.sh start 10b bilingual-blocks`
## Why this task exists
It is not in the original plan. Tasks 0711 built the primitives and blocks
before task 15c wrote the language contract, so every prose prop on all 19
blocks is a plain `string`. Task 15d then stopped, correctly, when it found it
could not render `/full-guide/` in both languages: the brief forbids it from
duplicating a block to get a second locale, and changing a block's interface is
component-builder work, not page-migrator work.
`/full-guide/` is one of only two pages with a language toggle (the other is
`/rules/`, which is already fully bilingual — all 23 of its Portuguese strings
reach the built page, because `RulesInteractive` reads them from
`src/content/rules/stages.json` and swaps client-side). The five remaining pages
have no toggle today and must not gain one.
## Scope
Exactly six files, all in `src/components/blocks/`:
`FleetDiagram.astro`, `HandoffTable.astro`, `PhasePanel.astro`,
`RouteTable.astro`, `SkillPackage.astro`, `WorktreeMap.astro`.
These are the six that `src/pages/full-guide.astro` uses. Do not touch the other
13 blocks, any primitive, any island, or any page.
## What to change
Every **prose** prop on those six accepts `Localized` as well as `string`:
```ts
type Localized = { en: string; pt: string };
```
- Given a `string`, render exactly what it renders today. Every existing call
site keeps working untouched — this is additive.
- Given a `Localized`, render the fragment twice per
`.agents/context/content-i18n.md`: `data-language-content="en"` on one and
`"pt"` on the other, English visible, Portuguese `hidden`.
Prose only. Do not widen `href`, `id`, `code`, numeric or enum props — several
are deliberately unlocalized, and task 05b recorded which (`trees.path`,
`trees.command`, `routes.score`, `commonSkills.source`).
`FleetDiagram`'s `orchestrator.title` is rendered with `set:html` because it
carries inline `<br>`. Keep that, on both locales.
## Do not
- Do not change what a block renders for a `string` prop. A diff in the built
output for the existing call sites means you got it wrong.
- Do not add a language toggle to any block. `LanguageToggle` is a separate
island and the page mounts it.
- Do not edit `scripts/verify.mjs`. 42 assertions, and you are not the
verification-engineer.
- Do not touch `src/pages/full-guide.astro`. That is 15d's file; it will pass
the `Localized` values once you land.
## Done when
- [ ] All six blocks accept `Localized` on every prose prop and `string` still
behaves identically
- [ ] Built output byte-identical for pages that pass only strings — check
`dist/` before and after for the pages that use these blocks
- [ ] `pnpm run gate` green, 42 assertions intact
- [ ] Report lists, per block, which props became locale-aware and which you
deliberately left unlocalized and why
@@ -179,3 +179,48 @@ to scraping.
`"pt"`, per `.agents/context/content-i18n.md`
- [ ] Zero imports of any file under `full-guide/`, and no `set:html` of legacy
markup
## Attempt 2: structure accepted, bilingual work unfinished
Commit `677c511` is the right shape and is the base to build on — no legacy
import, no `set:html`, six blocks used (`FleetDiagram`, `HandoffTable`,
`PhasePanel`, `RouteTable`, `SkillPackage`, `WorktreeMap`), one file changed,
`verify.mjs` untouched, 42 assertions, gate green, JS 47,079 B against the
legacy 50,338 B. Its report was honest about what it did not finish. Finish it.
**What is already correct — do not "fix" it.** The page has 55 `.en` reads and
zero `.pt` reads in the selector detail panels. That is right.
`GuideSelector.astro` re-renders every panel with `[locale]` on
`ai-for-dummies:languagechange`, so the server-rendered panel only has to match
the initial locale. Leave those alone.
**What is missing: the static prose.** Legacy `app.js` holds `translations.pt`
a map of **102** CSS-selector → Portuguese-string entries, starting at
`.chapter-links a:nth-child(1)`. `applyLanguage('pt')` walks it and calls
`setText(selector, value)`; switching back replays the captured `originals`.
That map is the full-guide page's static Portuguese, and it is the authoritative
source for this work.
The page currently carries **3** `data-language-content` pairs (hero, stat,
thesis). The other ~99 strings have no Portuguese counterpart anywhere in the
Astro output, so `/full-guide/` renders English-only for everything the selector
islands do not own.
Render each of those 102 strings twice per `.agents/context/content-i18n.md`:
the English exactly as it appears in `full-guide/index.html` today, the
Portuguese exactly as it appears in `translations.pt`. Verbatim both ways — no
retranslation, no rephrasing, no fixing what looks like a typo.
A selector in the map that targets an element the blocks now render means the
pair belongs inside that block's slot content, not bolted on afterwards. If a
block gives you no way to pass both locales, say so in the report and name the
block — do not work around it by duplicating the block.
### Done when, for this pass
- [ ] All 102 `translations.pt` entries have a rendered Portuguese counterpart
- [ ] Every localized static string wrapped in `data-language-content="en"` /
`"pt"` pairs
- [ ] No `.pt` reads added to the nine selector detail panels
- [ ] Gate green, 42 assertions, `verify.mjs` untouched
- [ ] Report lists any `translations.pt` selector you could not place, and why