Files
suaveplan/openspec/changes/enterprise-react-translate/tasks.md
2026-05-27 23:29:53 +01:00

4.8 KiB

Tasks: enterprise-react-translate

Change ID: enterprise-react-translate Package: @suaveplan/react-translate Target path: react/platform/react-translate Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/logger


0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create directory tree. Write package.json at 0.1.0, tsconfig.json, vitest.config.ts, scripts.
  • Dependencies: @suaveplan/error workspace:^, @suaveplan/logger workspace:^, i18next catalog:i18n, react-i18next catalog:i18n, i18next-browser-languagedetector catalog:i18n, i18next-http-backend catalog:i18n, @opentelemetry/api catalog:observability, tslib catalog:build.

2. Error codes and types

  • Define TranslationError; codes: TRANSLATION_INIT_FAILED, TRANSLATION_LOAD_FAILED.
  • Define types: I18nConfig, I18nNamespace, SupportedLanguage, LanguageBundle, TranslationProviderProps, UseTranslationReturn, UseErrorMessageReturn, UseDirectionReturn.

3. i18n config and lazy loader

  • createI18nConfig(options) — builds i18next config with missingKeyHandler that forwards to @suaveplan/logger + OTel counter. Throws TranslationError(TRANSLATION_INIT_FAILED) on invalid config.
  • src/i18n/lazy/ — createLazyLoader(namespaces) returns dynamic-import factory per language for Suspense-compatible lazy bundles.
  • Write i18n-config.test.ts + lazy-loader.test.ts (≤500 lines total): config init, missing-key telemetry fires, lazy-load resolves. { timeout: 10000 }.
  • Write .md for each.

4. Translation bundles

  • Write all 10 base bundles: en.ts, en-gb.ts, cy.ts, cy-gb.ts, de.ts, es.ts, fr.ts, ar.ts, zh.ts, zh-cn.ts.
  • Write 8 auth-namespace bundles: auth-en.ts, auth-cy.ts, auth-de.ts, auth-es.ts, auth-fr.ts, auth-ar.ts, auth-zh.ts, auth-en-gb.ts.
  • Export legacy aliases: cy → cyGb, en → enGb, zh → zhCn with JSDoc deprecation notes documenting the aliasing.

5. Provider

TranslationProvider

  • Wraps app with i18next instance. Accepts config, language, bundles. OTel span on init.
  • Write test + md.

6. Hooks

useTranslation

  • Wraps react-i18next useTranslation. Throws TranslationError in NODE_ENV !== 'production' when no provider is mounted; logs warning via @suaveplan/logger in production.
  • Write use-translation.test.ts (≤500 lines): happy path, missing-key stub-guard dev throw, prod soft-fail, namespace overrides. { timeout: 5000 }.
  • Write md.

useErrorMessage

  • Maps SuaveplanError instances to i18n strings via error code lookup. Falls back to error.message.
  • Write test + md.

useDirection

  • Returns { direction: 'ltr' | 'rtl', locale } based on current i18next language. RTL languages: ar, he, fa, ur.
  • Write test + md.

7. HOC

withTranslation

  • Higher-order component wrapping a component with t and i18n props injected.
  • Write test + md.

8. Utils

  • utils.ts — formatDate(date, locale), formatCurrency(amount, currency, locale), negotiateLanguage(preferred, available).
  • Write utils.test.ts (≤500 lines). { timeout: 5000 }.
  • Write md.

9. Storybook

  • provider.stories.tsx — language switcher playground (dropdown to switch en/de/ar/fr).
  • rtl.stories.tsx — Arabic layout with mirrored direction.
  • plurals.stories.tsx — count-based plural form demo.
  • formatting.stories.tsx — date + currency formatting bridge.

10. E2E

  • e2e/translate.spec.ts — Playwright:
    • Switch language from English to German; verify UI strings change.
    • Switch to Arabic; verify dir="rtl" applied to layout.
    • Test lazy-bundle load; verify Suspense fallback then content.
    • Verify missing-key counter increments when a key is absent.

11. Verify and publish

  • bunx turbo lint typecheck test --filter=@suaveplan/react-translate — green.
  • bunx turbo test:coverage --filter=@suaveplan/react-translate — 100%.
  • bun scripts/publish.ts --package @suaveplan/react-translate.
  • Archive change folder.