---
phase: 07-multilanguage
plan: 03
type: execute
wave: 2
depends_on:
  - "07-01"
  - "07-02"
files_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/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)/chat/page.tsx
  - packages/portal/app/(dashboard)/billing/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/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
autonomous: true
requirements:
  - I18N-01
  - I18N-04
  - I18N-05

must_haves:
  truths:
    - "Every user-visible string in the portal uses useTranslations() instead of hardcoded English"
    - "Navigation labels render in the selected language"
    - "Agent designer, wizard, and template gallery are fully translated"
    - "Onboarding flow steps are fully translated"
    - "Error messages and validation text render in the selected language"
    - "Chat UI, billing, usage, and all other pages are translated"
  artifacts:
    - path: "packages/portal/components/nav.tsx"
      provides: "Translated navigation labels"
      contains: "useTranslations"
    - path: "packages/portal/components/employee-wizard.tsx"
      provides: "Translated wizard UI"
      contains: "useTranslations"
    - path: "packages/portal/components/template-gallery.tsx"
      provides: "Translated template cards with locale-aware API calls"
      contains: "useTranslations"
    - path: "packages/portal/app/(dashboard)/chat/page.tsx"
      provides: "Translated chat interface"
      contains: "useTranslations"
  key_links:
    - from: "All portal components"
      to: "packages/portal/messages/{locale}.json"
      via: "useTranslations() hook reading from NextIntlClientProvider context"
      pattern: "useTranslations"
    - from: "packages/portal/components/template-gallery.tsx"
      to: "/api/portal/templates?locale="
      via: "Locale query param passed to templates API"
      pattern: "locale"
---

<objective>
Extract all hardcoded English strings from every portal page and component, replacing them with `useTranslations()` calls that read from the en/es/pt message files created in Plan 02.

Purpose: This is the core localization work. Every user-visible string in every TSX file must be replaced with a `t('key')` call. Without this, the message files and i18n infrastructure from Plan 02 have no effect.
Output: All 40+ portal TSX files updated with useTranslations() calls. Zero hardcoded English strings remain in user-visible UI.
</objective>

<execution_context>
@/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md
@/home/adelorenzo/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/07-multilanguage/07-CONTEXT.md
@.planning/phases/07-multilanguage/07-RESEARCH.md
@.planning/phases/07-multilanguage/07-01-SUMMARY.md
@.planning/phases/07-multilanguage/07-02-SUMMARY.md

<interfaces>
<!-- next-intl usage pattern (from Plan 02) -->
```typescript
// In Client Components ('use client'):
import { useTranslations } from 'next-intl';
const t = useTranslations('namespace');
// Then: <h1>{t('title')}</h1>

// In Server Components:
import { useTranslations } from 'next-intl';
const t = useTranslations('namespace');
// Same API — works in both

// Message file structure (from Plan 02):
// messages/en.json has nested keys: nav.dashboard, agents.pageTitle, etc.
// useTranslations('nav') gives t('dashboard') -> "Dashboard"
```

<!-- Template gallery needs locale-aware API call -->
```typescript
// Plan 01 adds ?locale= param to templates API
// Template gallery must pass current locale when fetching:
// GET /api/portal/templates?locale=es
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Extract strings from all components (nav, sidebar, forms, wizards, chat)</name>
  <files>
    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
  </files>
  <action>
    For EVERY component listed, apply this transformation:

    1. Add `import { useTranslations } from 'next-intl';` (for 'use client' components)
    2. At the top of the component function, add `const t = useTranslations('namespace');` where namespace matches the message file key group (e.g., 'nav' for nav.tsx, 'wizard' for wizard steps, 'chat' for chat components)
    3. Replace every hardcoded English string with `t('keyName')` — use the exact keys from the en.json message file created in Plan 02
    4. For strings with interpolation (e.g., "Welcome, {name}"), use `t('welcome', { name })` and ensure the message file uses ICU format: "Welcome, {name}"
    5. For nav.tsx specifically: replace the hardcoded label strings in the navItems array with t() calls. Since navItems is defined outside the component, move the labels inside the component function or use a computed items pattern.

    Specific component notes:
    - nav.tsx: navItems labels ("Dashboard", "Employees", etc.) -> t('dashboard'), t('employees'), etc. "Sign out" -> t('signOut')
    - template-gallery.tsx: Pass locale to templates API call: fetch(`/api/portal/templates?locale=${currentLocale}`). Get current locale from cookie or useLocale() from next-intl.
    - employee-wizard.tsx: All step labels, button text, form labels
    - onboarding-stepper.tsx: Step titles and descriptions
    - agent-designer.tsx: Field labels, button text, placeholders
    - chat-window.tsx: "Type a message", "Send", placeholder text
    - chat-sidebar.tsx: "New Conversation", "No conversations"
    - billing-status.tsx: Status labels, button text
    - subscription-card.tsx: Plan names, subscribe/manage buttons
    - tenant-form.tsx: Form labels, submit buttons
    - tenant-switcher.tsx: "Select tenant", "All tenants"
    - impersonation-banner.tsx: Banner text, stop button
    - budget-alert-badge.tsx: "No limit set", budget alert text

    Do NOT translate:
    - Component prop names or internal variable names
    - CSS class strings
    - API endpoint URLs
    - Console.log messages
    - aria-label values that are already descriptive (but DO translate user-visible aria-labels)
  </action>
  <verify>
    <automated>cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20</automated>
  </verify>
  <done>
    - All 22 component files use useTranslations() for every user-visible string
    - No hardcoded English strings remain in component files (except technical strings like URLs, class names)
    - Template gallery passes locale to API
    - Portal builds successfully
  </done>
</task>

<task type="auto">
  <name>Task 2: Extract strings from all page files (dashboard, agents, chat, billing, usage, etc.)</name>
  <files>
    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)/chat/page.tsx
    packages/portal/app/(dashboard)/billing/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
  </files>
  <action>
    For EVERY page file listed, apply the same transformation pattern as Task 1:

    1. Add `import { useTranslations } from 'next-intl';`
    2. Add `const t = useTranslations('namespace');` using the appropriate namespace
    3. Replace all hardcoded English strings with `t('key')` calls

    Page-specific notes:
    - dashboard/page.tsx: "Dashboard", "Welcome back", stats labels -> t('dashboard.*')
    - agents/page.tsx: "AI Employees", "New Employee", empty state text -> t('agents.*')
    - agents/[id]/page.tsx: Agent detail labels, edit/delete buttons -> t('agentDesigner.*')
    - agents/new/page.tsx: Three creation options text -> t('agentNew.*')
    - agents/new/templates/page.tsx: Template gallery page title -> t('templates.*')
    - agents/new/wizard/page.tsx: Wizard page wrapper -> t('wizard.*')
    - agents/new/advanced/page.tsx: Advanced mode labels -> t('agentDesigner.*')
    - chat/page.tsx: Chat page labels -> t('chat.*')
    - billing/page.tsx: Billing page labels, plan info -> t('billing.*')
    - usage/page.tsx & usage/[tenantId]/page.tsx: Usage labels, chart titles -> t('usage.*')
    - settings/api-keys/page.tsx: API key management labels -> t('apiKeys.*')
    - users/page.tsx: User management, invite labels -> t('users.*')
    - admin/users/page.tsx: Platform admin user list -> t('adminUsers.*')
    - tenants pages: Tenant management labels -> t('tenants.*')
    - onboarding pages + steps: All onboarding UI -> t('onboarding.*')
    - invite/[token]/page.tsx: Invitation acceptance page -> t('invite.*') (add invite namespace to message files if not already present)

    After all string extraction is complete, do a final review of messages/en.json, messages/es.json, and messages/pt.json to ensure every key used by t() exists in all three files. Add any missing keys discovered during extraction.

    IMPORTANT: If any page is a Server Component (no 'use client'), useTranslations still works the same way in next-intl v4 — it reads from the server context set up by i18n/request.ts. No change needed.
  </action>
  <verify>
    <automated>cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20</automated>
  </verify>
  <done>
    - All 22 page files use useTranslations() for every user-visible string
    - No hardcoded English strings remain in any page file
    - All translation keys used in t() calls exist in en.json, es.json, and pt.json
    - Portal builds successfully with zero errors
  </done>
</task>

</tasks>

<verification>
- Portal builds: `cd packages/portal && npx next build`
- Grep for remaining hardcoded strings: search for obvious English strings that should be translated
- All message file keys are consistent across en.json, es.json, pt.json
</verification>

<success_criteria>
- Every user-visible string in the portal uses useTranslations()
- All three message files (en/es/pt) have matching key structures
- Template gallery passes locale to API for translated template content
- Portal builds without errors
- Zero hardcoded English strings remain in user-facing UI
</success_criteria>

<output>
After completion, create `.planning/phases/07-multilanguage/07-03-SUMMARY.md`
</output>
