# Task 15c — The language toggle **Agent**: `content-i18n-migrator` · **Model**: **Codex** **Depends on**: 05 · **Parallel with**: 15a, 15b · **Blocks**: 15d **Worktree**: `.agents/scripts/worktree.sh start 15c language-toggle` ## Why this is its own task This is the part of the full guide that does not survive a mechanical port, and it is the most likely reason task 15 failed twice. Today `applyLanguage` walks a `translations.pt` map of **CSS selector → Portuguese HTML** and overwrites `innerHTML` at each selector. It keeps an `originals` Map to restore English. That design cannot survive the migration: the selectors are page-structure coupling, and once the content is a collection the Portuguese string already lives beside the English one. ## Deliver a decision, then an implementation Write the approach down in `.agents/context/content-i18n.md` (or the rule file it points at) **before** you build, because tasks 15d, 16, and 20 all depend on it and there is currently no stated answer. The realistic options: 1. **Server-render both locales, toggle visibility.** Simple, no hydration cost for text, doubles the HTML. 2. **Server-render the saved locale, islands re-render on toggle.** Smaller HTML; every island then needs both strings client-side anyway. 3. **Separate routes per locale.** Cleanest, but changes URLs, which touches publishing and every internal link — out of scope unless you argue for it and the report flags it as a plan change. Pick one, say why, and note what it costs. ## Behaviour that must not regress - `localStorage` key `ai-for-dummies-language`, wrapped in try/catch — previews disable storage and an unguarded read throws. - `document.documentElement.lang` becomes `pt-BR` or `en`. - `[data-lang]` buttons get `.active` and `aria-pressed`. - Toggling language re-renders the active phase panel and every selector panel. Coordinate with 15a: the island must expose a way to do this. - `client:idle` — page-wide, not urgent. ## Do not - Create `src/pages/full-guide.astro`. That is 15d. - Edit `src/content/config.ts` schemas belonging to other collections beyond what the toggle genuinely needs; if a schema is wrong, report it. - Touch `verify.mjs`. - Translate, rewrite, or "improve" any string. Both locales already exist in the collections. This is plumbing, not copywriting. ## Done when - [ ] Approach written down where 15d, 16 and 20 will find it - [ ] Toggle island built, `client:idle`, storage guarded - [ ] Both locales verified on a real rendered page, not just in theory - [ ] `pnpm run gate` green — the full gate - [ ] 42 assertions intact - [ ] Report states the contract 15d must satisfy