docs(07-03): complete portal i18n string extraction plan

This commit is contained in:
2026-03-25 17:05:08 -06:00
parent 1018269f82
commit 6e9441215b
3 changed files with 169 additions and 6 deletions

View File

@@ -141,7 +141,7 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
| 4. RBAC | 3/3 | Complete | 2026-03-24 |
| 5. Employee Design | 4/4 | Complete | 2026-03-25 |
| 6. Web Chat | 3/3 | Complete | 2026-03-25 |
| 7. Multilanguage | 2/4 | In Progress| |
| 7. Multilanguage | 3/4 | In Progress| |
---

View File

@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
status: completed
stopped_at: Completed 07-multilanguage-02-PLAN.md
last_updated: "2026-03-25T22:30:25.808Z"
stopped_at: Completed 07-multilanguage-03-PLAN.md
last_updated: "2026-03-25T23:04:58.017Z"
last_activity: 2026-03-23 — Completed 03-02 onboarding wizard, Slack OAuth, BYO API keys
progress:
total_phases: 7
completed_phases: 6
total_plans: 29
completed_plans: 27
completed_plans: 28
percent: 100
---
@@ -79,6 +79,7 @@ Progress: [██████████] 100%
| Phase 06-web-chat P03 | verification | 1 tasks | 0 files |
| Phase 07-multilanguage P01 | 7min | 2 tasks | 12 files |
| Phase 07-multilanguage P02 | 9min | 2 tasks | 14 files |
| Phase 07-multilanguage P03 | 45min | 2 tasks | 48 files |
## Accumulated Context
@@ -177,6 +178,8 @@ Recent decisions affecting current work:
- [Phase 07-multilanguage]: i18n/locales.ts created to separate client-safe constants from server-only i18n/request.ts (next/headers import)
- [Phase 07-multilanguage]: Cookie name konstruct_locale for cookie-based locale with no URL routing
- [Phase 07-multilanguage]: LanguageSwitcher isPreAuth prop skips DB PATCH and session.update() on login page
- [Phase 07-multilanguage]: onboarding/page.tsx uses getTranslations() not useTranslations() — Server Component requires next-intl/server import
- [Phase 07-multilanguage]: billing-status.tsx trialEnds key uses only {date} param — boolean ICU params rejected by TypeScript strict mode
### Roadmap Evolution
@@ -192,6 +195,6 @@ None — all phases complete.
## Session Continuity
Last session: 2026-03-25T22:30:25.805Z
Stopped at: Completed 07-multilanguage-02-PLAN.md
Last session: 2026-03-25T23:04:58.013Z
Stopped at: Completed 07-multilanguage-03-PLAN.md
Resume file: None

View File

@@ -0,0 +1,160 @@
---
phase: 07-multilanguage
plan: "03"
subsystem: portal-i18n
tags:
- i18n
- next-intl
- portal
- components
- pages
dependency_graph:
requires:
- 07-01
- 07-02
provides:
- fully-translated-portal-ui
affects:
- packages/portal/components
- packages/portal/app
- packages/portal/messages
tech_stack:
added: []
patterns:
- next-intl useTranslations() in client components
- next-intl getTranslations() in server components
- ICU message format with named params
- useTemplates(locale) locale-aware API call
key_files:
created: []
modified:
- packages/portal/components/nav.tsx
- packages/portal/components/agent-designer.tsx
- packages/portal/components/billing-status.tsx
- packages/portal/components/budget-alert-badge.tsx
- packages/portal/components/chat-message.tsx
- packages/portal/components/chat-sidebar.tsx
- packages/portal/components/chat-window.tsx
- packages/portal/components/employee-wizard.tsx
- packages/portal/components/impersonation-banner.tsx
- packages/portal/components/message-volume-chart.tsx
- packages/portal/components/onboarding-stepper.tsx
- packages/portal/components/provider-cost-chart.tsx
- packages/portal/components/subscription-card.tsx
- packages/portal/components/template-gallery.tsx
- packages/portal/components/tenant-form.tsx
- packages/portal/components/tenant-switcher.tsx
- packages/portal/components/wizard-steps/step-role.tsx
- packages/portal/components/wizard-steps/step-persona.tsx
- packages/portal/components/wizard-steps/step-tools.tsx
- packages/portal/components/wizard-steps/step-channels.tsx
- packages/portal/components/wizard-steps/step-escalation.tsx
- packages/portal/components/wizard-steps/step-review.tsx
- packages/portal/app/(dashboard)/dashboard/page.tsx
- packages/portal/app/(dashboard)/agents/page.tsx
- packages/portal/app/(dashboard)/agents/[id]/page.tsx
- packages/portal/app/(dashboard)/agents/new/page.tsx
- packages/portal/app/(dashboard)/agents/new/templates/page.tsx
- packages/portal/app/(dashboard)/agents/new/wizard/page.tsx
- packages/portal/app/(dashboard)/agents/new/advanced/page.tsx
- packages/portal/app/(dashboard)/billing/page.tsx
- packages/portal/app/(dashboard)/chat/page.tsx
- packages/portal/app/(dashboard)/usage/page.tsx
- packages/portal/app/(dashboard)/usage/[tenantId]/page.tsx
- packages/portal/app/(dashboard)/settings/api-keys/page.tsx
- packages/portal/app/(dashboard)/users/page.tsx
- packages/portal/app/(dashboard)/admin/users/page.tsx
- packages/portal/app/(dashboard)/tenants/page.tsx
- packages/portal/app/(dashboard)/tenants/new/page.tsx
- packages/portal/app/(dashboard)/tenants/[id]/page.tsx
- packages/portal/app/(dashboard)/onboarding/page.tsx
- packages/portal/app/(dashboard)/onboarding/steps/connect-channel.tsx
- packages/portal/app/(dashboard)/onboarding/steps/configure-agent.tsx
- packages/portal/app/(dashboard)/onboarding/steps/test-message.tsx
- packages/portal/app/invite/[token]/page.tsx
- packages/portal/lib/queries.ts
- packages/portal/messages/en.json
- packages/portal/messages/es.json
- packages/portal/messages/pt.json
decisions:
- "onboarding/page.tsx uses getTranslations() not useTranslations() — Server Component requires next-intl/server import"
- "TIME_RANGE_OPTIONS moved inside component body — module-level constants cannot access t() hook"
- "billing-status.tsx trialEnds key simplified to only {date} param — removed boolean hasDays ICU param that caused TypeScript error"
- "WhatsApp credential step instructions stored as plain-text translation keys — avoids dangerouslySetInnerHTML for HTML-marked-up steps"
- "useTemplates(locale?) accepts optional locale and passes as ?locale= query param — enables locale-aware template API calls"
metrics:
duration: ~45min
completed: 2026-03-25
tasks_completed: 2
files_modified: 48
---
# Phase 7 Plan 3: Portal i18n String Extraction Summary
All 44 portal TSX files now use next-intl `useTranslations()` for every user-visible string — zero hardcoded English in components or pages, with full EN/ES/PT translations for all keys including new namespaces `billingStatus`, `budgetAlert`, `subscriptionCard`, and `invite`.
## Tasks Completed
### Task 1: Extract strings from 22 component files
All component files migrated to `useTranslations()`:
- **Navigation**: `nav.tsx` — nav labels, sign out
- **Tenant management**: `tenant-form.tsx`, `tenant-switcher.tsx` — form labels, switcher UI
- **Billing**: `billing-status.tsx`, `budget-alert-badge.tsx`, `subscription-card.tsx` — all subscription states, budget thresholds, plan details
- **Templates**: `template-gallery.tsx` — category labels, deploy buttons, preview modal
- **Employee wizard**: `employee-wizard.tsx` + all 6 step components (role, persona, tools, channels, escalation, review)
- **Onboarding**: `onboarding-stepper.tsx`, `impersonation-banner.tsx`
- **Chat**: `chat-sidebar.tsx`, `chat-window.tsx`, `chat-message.tsx`, `message-volume-chart.tsx`, `provider-cost-chart.tsx`
- **Agent designer**: `agent-designer.tsx`
### Task 2: Extract strings from 22 page files
All page files migrated to `useTranslations()`:
- **Core pages**: dashboard, chat, billing, usage (list + detail)
- **Agent pages**: agents list, agent detail, new agent picker, templates, wizard, advanced designer
- **Settings**: api-keys
- **User management**: users, admin/users
- **Tenant management**: tenants list, tenant detail, new tenant
- **Onboarding**: onboarding page (Server Component with `getTranslations`), plus all 3 step components (connect-channel, configure-agent, test-message)
- **Public**: invite accept page
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Fixed TypeScript error in billing-status.tsx**
- **Found during:** Task 1
- **Issue:** `hasDays: days !== null` passed a boolean to an ICU message parameter typed as `string | number | Date` — TypeScript strict mode rejects this
- **Fix:** Removed `hasDays` parameter entirely; simplified `trialEnds` key to `"Trial ends {date}"` using only `{date}`
- **Files modified:** `components/billing-status.tsx`, `messages/en.json`, `messages/es.json`, `messages/pt.json`
- **Commit:** 20f4c5b
**2. [Rule 2 - Missing functionality] Added onboarding step translations not in plan scope**
- **Found during:** Task 2
- **Issue:** `onboarding/steps/connect-channel.tsx`, `configure-agent.tsx`, `test-message.tsx` contained hardcoded English; plan listed them in `files_modified` but original task breakdown only mentioned 22 pages without explicitly calling out the step components as separate
- **Fix:** Added ~60 new keys to the `onboarding` namespace in all three message files; rewrote all three step components with `useTranslations("onboarding")`
- **Files modified:** all 3 step files + 3 message files
**3. [Rule 1 - Bug] TIME_RANGE_OPTIONS moved inside component**
- **Found during:** Task 2
- **Issue:** `app/(dashboard)/usage/[tenantId]/page.tsx` had `TIME_RANGE_OPTIONS` defined at module level with hardcoded English strings, which cannot access the `t()` hook
- **Fix:** Moved array construction inside the component function body
- **Files modified:** `app/(dashboard)/usage/[tenantId]/page.tsx`
**4. [Rule 2 - Missing functionality] WhatsApp instructions as plain text**
- **Found during:** Task 1 (connect-channel.tsx)
- **Issue:** Original file used `<strong>` HTML inside `<li>` elements for emphasis in credential instructions; direct translation keys can't hold HTML safely
- **Fix:** Stored instructions as plain-text translation keys (no HTML); bold emphasis replaced with readable text
- **Files modified:** `components/wizard-steps/step-channels.tsx` was already in scope; `onboarding/steps/connect-channel.tsx` instructions simplified
## Verification
TypeScript type check (`npx tsc --noEmit`) passes with zero errors after all changes.
## Self-Check: PASSED
Files created/modified confirmed present. Commits verified:
- `20f4c5b` — feat(07-03): extract i18n strings from portal components
- `c499029` — feat(07-03): extract i18n strings from portal pages