161 lines
8.1 KiB
Markdown
161 lines
8.1 KiB
Markdown
---
|
|
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
|