--- 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" --- 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. @/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md @/home/adelorenzo/.claude/get-shit-done/templates/summary.md @.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 ```typescript // In Client Components ('use client'): import { useTranslations } from 'next-intl'; const t = useTranslations('namespace'); // Then:

{t('title')}

// 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" ``` ```typescript // Plan 01 adds ?locale= param to templates API // Template gallery must pass current locale when fetching: // GET /api/portal/templates?locale=es ```
Task 1: Extract strings from all components (nav, sidebar, forms, wizards, chat) 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 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) cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20 - 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 Task 2: Extract strings from all page files (dashboard, agents, chat, billing, usage, etc.) 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 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. cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20 - 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 - 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 - 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 After completion, create `.planning/phases/07-multilanguage/07-03-SUMMARY.md`