Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

424 lines
91 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Scratchpad -- MSP i18n: Contracts Sub-batch
- Plan slug: `2026-04-09-msp-i18n-contracts`
- Created: `2026-04-09`
## What This Is
A mechanical wiring pass: 37 unwired contract components (+ 1 pure-constants file) x `useTranslation('msp/contracts')`. This is the largest sub-batch in the MSP i18n effort at ~14,100 LOC across 38 files spanning 3 directory levels.
## Decisions
- **(2026-04-09)** Use a dedicated `msp/contracts` namespace rather than cramming keys into `features/billing`. Rationale: 38 files with ~800-1200 estimated keys would bloat the billing namespace beyond maintainability. Contracts are a self-contained feature area.
- **(2026-04-09)** `contractsTabs.ts` exports pure string constants (`CONTRACT_SUBTAB_LABELS`, `CONTRACT_TAB_LABELS`). These cannot use `useTranslation()` because the file is not a React component. Translate the consumed values at point-of-use in `Contracts.tsx` and `ClientContractsTab.tsx` instead.
- **(2026-04-14)** **Adopt the shared enum-labels option-hook pattern for all `BILLING_FREQUENCY_*` / `PLAN_TYPE_*` / `CONTRACT_LINE_TYPE_*` call sites owned by this batch.** The contract-lines sub-batch (shipped 2026-04-14) created `packages/billing/src/hooks/useBillingEnumOptions.ts` with `useBillingFrequencyOptions`, `useFormatBillingFrequency`, `useContractLineTypeOptions`, `useFormatContractLineType`, and added `enums.billingFrequency.*` / `enums.contractLineType.*` to `features/billing.json` in all 9 locales. This batch **must** migrate every call site in the PRD's "Shared enum label migration" table rather than translating surrounding labels and leaving the enum values in English. The deprecated `*_DISPLAY` / `*_OPTIONS` exports in `packages/billing/src/constants/billing.ts` were left in place **only** so this batch can flip the switch file-by-file; once all call sites are migrated, remove the deprecated aliases in the same PR as the last migration (or as a final clean-up commit). Pattern reference: `.ai/translation/enum-labels-pattern.md`. Audit command: `rg -n '_DISPLAY|_OPTIONS' packages/billing/src/components/billing-dashboard/contracts/`.
- **(2026-04-14)** **`contractsTabs.ts` migration shape:** keep `CONTRACT_SUBTAB_LABELS` as a value-to-value mapping only if `CONTRACT_LABEL_TO_SUBTAB` still needs it as an identifier lookup. For display, add a `useContractSubtabLabels()` helper colocated with the consumers (`Contracts.tsx` / `ClientContractsTab.tsx`) that returns `{ templates: t('...'), 'client-contracts': t('...'), drafts: t('...') }`. Store/compare tab state by `ContractSubTab` value, never by label. Keys go in `msp/contracts.json` under (suggested) `common.tabs.*` or `enums.contractSubtab.*`.
- **(2026-04-09)** Use `t('key', { defaultValue: 'English fallback' })` signature everywhere for fallback-safety. This matches the pattern established in existing msp/* namespaces.
- **(2026-04-09)** Replace hardcoded `'en-US'` locale in `formatCurrencyFromMinorUnits()` calls with locale from `useFormatters()`. Affects ContractDetail.tsx (invoice columns, PO amount display), ContractOverview.tsx, ReviewContractStep.tsx. The `formatCurrencyFromMinorUnits` utility accepts a locale parameter.
- **(2026-04-09)** Do NOT translate `throw new Error(...)` messages or `console.error()` strings. Only translate user-visible strings rendered in JSX.
- **(2026-04-09)** Use i18next `{{count}}` interpolation for pluralized strings (e.g., `'{{count}} service'` / `'{{count}} services'`; `'{{count}} day'` / `'{{count}} days'`).
- **(2026-04-09)** Use i18next named interpolation for dynamic values in dialog titles (e.g., `t('contractLineRate.title', { name: plan.contract_line_name, defaultValue: 'Set Custom Rate for {{name}}' })`).
- **(2026-04-09)** Ship in sub-batches due to size. Recommended split:
- Sub-batch A: Namespace creation (F001), translations (F002-F009), route config (F010) -- foundational.
- Sub-batch B: Large components -- ContractDetail (F011-F015), ContractDialog (F016-F018), ContractTemplateDetail (F019-F021).
- Sub-batch C: Medium components -- CreateCustomContractLineDialog (F022-F024), ContractLines (F025-F027), AddContractLinesDialog (F028-F029), Contracts/ClientContracts (F030-F034).
- Sub-batch D: Client wizard steps -- ContractWizard (F035-F036), ContractBasicsStep (F052-F053), service steps (F054-F057), ReviewContractStep (F058-F059).
- Sub-batch E: Template wizard + small components -- TemplateWizard (F060), template steps (F061-F067), and remaining small components (F037-F051).
## Discoveries / Constraints
- **(2026-04-09)** `ContractDetail.tsx` at 2,330 LOC is the largest single component. It contains 5 tab views, 3 confirmation dialogs, assignment editing with 8+ field types, invoice column definitions, and status formatting. Estimated at 300-400 unique translatable strings. Split into 5 features (F011-F015).
- **(2026-04-09)** Two near-identical dialog files exist: `ContractLineRateDialog.tsx` (99 LOC) and `ContractPlanRateDialog.tsx` (95 LOC). They share the same structure and strings. Consolidate into one feature (F049) for translation efficiency.
- **(2026-04-09)** `formatRenewalModeLabel()` in ContractDetail.tsx returns hardcoded English strings ('Auto-renew', 'Non-renewing', 'Manual renewal'). These need to be translated using `t()` calls at the rendering site, not inside the formatting function (which has no hook access). Extract to translated labels in the component body.
- **(2026-04-09)** `ContractOverview.tsx` has a local `formatFrequency()` that maps frequency keys to display strings ('Weekly', 'Monthly', etc.). These should use `t()` rather than a local map. Same pattern in `ContractHeader.tsx`. **(2026-04-14 update):** For `monthly/quarterly/annually` specifically, use `useFormatBillingFrequency()` from `@alga-psa/billing/hooks/useBillingEnumOptions` so these renderers share the same `features/billing.json` keys as the rest of the contract-lines UI. `weekly` and `biweekly` are not in the shared enum — if `ContractOverview.tsx` needs them, keep a local `t()` lookup for those two values only or extend `BILLING_FREQUENCY_VALUES` (check whether the backend can actually emit them first).
- **(2026-04-09)** `ContractWizard.tsx` defines `STEPS` as a `const` tuple: `['Contract Basics', 'Fixed Fee Services', 'Products', 'Hourly Services', 'Usage-Based Services', 'Review & Create']`. These are passed to `WizardProgress` and `WizardNavigation`. They need to be translated. Options: (a) convert to keys and translate in the component, (b) wrap with `t()` in a useMemo. Option (b) is simpler -- translate at point of use.
- **(2026-04-09)** Same STEPS pattern in `TemplateWizard.tsx` with `TEMPLATE_STEPS`.
- **(2026-04-09)** `BucketOverlayFields.tsx` uses dynamic unit labels ('hours' vs custom unitLabel). The translation key should use interpolation: `t('bucketOverlay.includedLabel', { units: resolvedUnitLabel })`.
- **(2026-04-09)** `TemplateServicePreviewSection.tsx` uses a confirmation dialog with template literal message containing service and preset names. Convert to interpolation: `t('templatePreview.removeConfirmMessage', { serviceName, presetName })`.
- **(2026-04-09)** Several components format currency with hardcoded `'en-US'`: ContractDetail.tsx (lines 1093, 1644, 2126), ContractOverview.tsx (line 19 formatCurrency), ReviewContractStep.tsx (line 62-64). All should be migrated to use `useFormatters().formatCurrency()` or pass the active locale to `formatCurrencyFromMinorUnits()`.
- **(2026-04-09)** `ContractDialog.tsx` is a legacy create/edit dialog (1,386 LOC). It has its own preset picker with rate overrides and service overrides -- complex nested state. Translating it requires careful interpolation for dynamic preset names and rate displays.
- **(2026-04-09)** `ROUTE_NAMESPACES` for `/msp/billing` currently loads: `['common', 'msp/core', 'features/billing', 'msp/reports']`. Adding `'msp/contracts'` is straightforward -- it just appends to the array. Check if `msp/quotes` was also added recently (per the quotes sub-batch plan) to avoid merge conflicts.
- **(2026-04-09)** `ServicePicker.tsx` (56 LOC) and `ServiceCatalogPicker.tsx` (225 LOC) are thin wrappers. The former has 3 translatable strings (placeholder, search placeholder, empty message). The latter has more (~20-30) with search, filter, and selection UI.
- **(2026-04-09)** `QuickStartGuide.tsx` contains substantial prose content (step descriptions, billing model explanations, best practices list). These are long strings but straightforward to extract. Use descriptive keys like `quickStart.step1.description`, `quickStart.bestPractices.item1`.
- **(2026-04-09)** `contractsTabs.ts` (27 LOC, no React) defines `CONTRACT_SUBTAB_LABELS` and `CONTRACT_TAB_LABELS`. These are consumed in `Contracts.tsx` via `CustomTabs` and in `ClientContractsTab.tsx`. The tab component likely accepts string labels, so translate at the consumption point. Do NOT add `useTranslation()` to the .ts constant file.
## Gotchas
- **Shared status labels**: Status labels ('Active', 'Draft', 'Terminated', 'Expired') appear in ContractDetail.tsx, ContractHeader.tsx, ContractForm.tsx, TemplatesTab.tsx, ClientContractsTab.tsx, and Contracts.tsx. Use `common.status.*` keys in the namespace to avoid duplication.
- **Renewal mode labels**: 'Auto-renew', 'Manual renewal', 'Non-renewing' appear in ContractDetail.tsx and ContractBasicsStep.tsx. Use `common.renewal.*` keys.
- **Billing timing labels**: 'In Arrears' / 'In Advance' appear in ContractLineEditDialog.tsx, ContractLines.tsx, ContractTemplateDetail.tsx, and wizard steps. Use `common.billing.timing.*` keys.
- **Currency symbol hardcoding**: `BucketOverlayFields.tsx` hardcodes `$` as the currency symbol prefix (line 136). This should ideally use the contract's currency symbol, but that is a functional change beyond i18n scope. Note it but do not fix.
- **Date formatting**: Several components use `new Intl.DateTimeFormat(undefined, ...)` which already respects browser locale -- no change needed for these. Only the explicit `'en-US'` locale in `formatCurrencyFromMinorUnits` calls needs migration.
- **Large test surface**: 67 features x ~1.5 tests = ~100 test cases. For efficiency, group small-component tests into composite test files (e.g., one test file covering F045-F051 small components).
## Execution Log
- **(2026-04-14)** `F001` completed: created [`server/public/locales/en/msp/contracts.json`](../../../../server/public/locales/en/msp/contracts.json) with the full top-level namespace/group scaffold from the PRD (`common`, `status`, `renewal`, `billing`, `po`, and all component/wizard group buckets). Added initial key population for the first ContractDetail tranche (tabs/cards/dialogs/invoices/common actions/status/fallback labels) so follow-on features can wire to stable keys immediately.
- **(2026-04-14)** Runbook/verification: `jq empty server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Constraint: key count is intentionally incremental at this stage; groups are pre-created so subsequent feature commits can append keys without structural churn.
- **(2026-04-14)** `F002` completed: generated [`server/public/locales/fr/msp/contracts.json`](../../../../server/public/locales/fr/msp/contracts.json) from English source using placeholder-safe machine translation (`{{...}}` tokens protected/restored).
- **(2026-04-14)** Verification: `jq empty server/public/locales/fr/msp/contracts.json`.
- **(2026-04-14)** `F003` completed: generated [`server/public/locales/es/msp/contracts.json`](../../../../server/public/locales/es/msp/contracts.json) from English source with placeholder-safe machine translation.
- **(2026-04-14)** Verification: `jq empty server/public/locales/es/msp/contracts.json`.
- **(2026-04-14)** `F004` completed: generated [`server/public/locales/de/msp/contracts.json`](../../../../server/public/locales/de/msp/contracts.json) from English source with placeholder-safe machine translation.
- **(2026-04-14)** Verification: `jq empty server/public/locales/de/msp/contracts.json`.
MD && git add ee/docs/plans/2026-04-09-msp-i18n-contracts/features.json ee/docs/plans/2026-04-09-msp-i18n-contracts/SCRATCHPAD.md server/public/locales/de/msp/contracts.json && git commit -m "feat(F004): add german contracts locale namespace"- **(2026-04-14)** `F005` completed: generated [`server/public/locales/nl/msp/contracts.json`](../../../../server/public/locales/nl/msp/contracts.json) from English source with placeholder-safe machine translation.
- **(2026-04-14)** Verification: `jq empty server/public/locales/nl/msp/contracts.json`.
MD && git add ee/docs/plans/2026-04-09-msp-i18n-contracts/features.json ee/docs/plans/2026-04-09-msp-i18n-contracts/SCRATCHPAD.md server/public/locales/nl/msp/contracts.json && git commit -m "feat(F005): add dutch contracts locale namespace"- **(2026-04-14)** `F006` completed: generated [`server/public/locales/it/msp/contracts.json`](../../../../server/public/locales/it/msp/contracts.json) from English source with placeholder-safe machine translation.
- **(2026-04-14)** Italian accent audit note: machine output preserves accented graphemes where emitted by translator; full strict audit will be enforced again during `F009` (`validate-translations.cjs`).
- **(2026-04-14)** Verification: `jq empty server/public/locales/it/msp/contracts.json`.
- **(2026-04-14)** `F007` completed: generated [`server/public/locales/pl/msp/contracts.json`](../../../../server/public/locales/pl/msp/contracts.json) from English source with placeholder-safe machine translation.
- **(2026-04-14)** Verification: `jq empty server/public/locales/pl/msp/contracts.json`.
- **(2026-04-14)** `F008` completed: ran `node scripts/generate-pseudo-locales.cjs`, which regenerated pseudo-locales including `xx/msp/contracts.json` and `yy/msp/contracts.json`.
- **(2026-04-14)** Verification: `jq empty server/public/locales/xx/msp/contracts.json && jq empty server/public/locales/yy/msp/contracts.json` and spot-check confirmed `xx` values are `11111` patterns.
- **(2026-04-14)** `F009` completed: ran `node scripts/validate-translations.cjs` after adding `msp/contracts` locale files.
- **(2026-04-14)** Validation result: `Errors: 0`, `Warnings: 0`, `PASSED`.
- **(2026-04-14)** `F010` completed: updated `ROUTE_NAMESPACES['/msp/billing']` in `packages/core/src/lib/i18n/config.ts` to preload `msp/contracts` alongside existing billing namespaces.
- **(2026-04-14)** `F011` completed in `ContractDetail.tsx`: wired `useTranslation('msp/contracts')` and translated tab labels (`Overview`, `Contract Lines`, `Pricing Schedules`, `Documents`, `Invoices`), unsaved-changes warning copy, save-success toast/alert copy, system-managed-default informational alert copy, and validation alert heading/field labels.
- **(2026-04-14)** Added corresponding `contractDetail.alerts.*`, `contractDetail.systemManaged.*`, and `contractDetail.validation.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F012` completed in `ContractDetail.tsx`: translated Contract Details card title, `Contract Name *` and `Description` labels, `No description` fallback, contract-name/description placeholders, and the `System-managed default` badge. Added translated aria-label/title text for edit/save/cancel icon buttons in the details card.
- **(2026-04-14)** Added `contractDetail.detailsCard.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F013` completed in `ContractDetail.tsx`: localized the Contract Header card title/labels (`Status` / `Assignment Status`, billing frequency, currency, created, last updated), status badges/options (`Active`, `Draft`, `Terminated`, `Expired`), renewal summary labels (`Mode`, `Source`, `Notice`, `Decision Due`), renewal source values (`Tenant defaults`, `Custom settings`), and expired-status note.
- **(2026-04-14)** Migrated this files billing-frequency select from deprecated `BILLING_FREQUENCY_OPTIONS` constant to `useBillingFrequencyOptions()` hook.
- **(2026-04-14)** Added `contractDetail.headerCard.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F014` completed in `ContractDetail.tsx`: localized Client Ownership + Client Assignment sections (owner/client/status/start/end labels, empty states, `Ongoing`, PO labels + required/not-required text, and assignment action buttons). Localized renewal-handling editor labels (use-tenant-defaults toggle, renewal mode, notice period, renewal term, ticket board/status labels and placeholders) and read-only renewal summary text.
- **(2026-04-14)** Added `contractDetail.clientOwnership.*` and `contractDetail.clientAssignment.*` key groups and `common.labels.yes|no` to `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F015` completed in `ContractDetail.tsx`: localized Quick Actions card/button labels, footer Save/Cancel button text states (`Save Changes`, dirty-state variant, `Saving...`), discard/leave/delete confirmation dialogs, documents-tab loading text, invoice-tab title/help/refresh/loading/empty text, and invoice table column/preview labels.
- **(2026-04-14)** Currency formatting cleanup: replaced all hardcoded `formatCurrencyFromMinorUnits(..., 'en-US', ...)` usages in `ContractDetail.tsx` with locale-aware `useFormatters().formatCurrency` via a `formatMinorCurrency` helper.
- **(2026-04-14)** Added/expanded `contractDetail.quickActions.*`, `contractDetail.dialogs.*`, `contractDetail.documents.*`, and `contractDetail.invoices.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F016` completed in `ContractDialog.tsx`: wired `useTranslation('msp/contracts')` and localized dialog title, core form labels/placeholders (`Client`, `Contract Name`, `Billing Frequency`, `Currency`, `Start/End Date`, `Description`), renewal-settings labels/copy (`Renewal Mode`, `Use Tenant Renewal Defaults`, notice period, renewal term), and required-field validation messages.
- **(2026-04-14)** Migrated `ContractDialog.tsx` billing-frequency select from deprecated `BILLING_FREQUENCY_OPTIONS` to `useBillingFrequencyOptions()`.
- **(2026-04-14)** Added initial `contractDialog.title|actions|form|validation` keys to `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDialog.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F017` completed in `ContractDialog.tsx`: localized PO section labels/copy (`Require Purchase Order`, PO number/amount labels/placeholders, note banner text) and preset-picker shell copy (section heading, loading/empty states, search placeholder, type filter labels, reset, no-match text, selected-count summary).
- **(2026-04-14)** Shared enum migration in this file: replaced deprecated `CONTRACT_LINE_TYPE_DISPLAY` option-builder with `useContractLineTypeOptions()` for the preset type filter.
- **(2026-04-14)** Expanded `contractDialog.presets.*` and `contractDialog.po.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDialog.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F018` completed in `ContractDialog.tsx`: localized expanded preset detail content including fixed-rate configuration labels/help text, service summary copy, hourly-config labels, hourly/usage service field labels (`Quantity`, `Rate`, `Unit of Measure`), and default-rate helper text. Also translated all remaining tooltip/help copy in this file to `t(..., { defaultValue })` usage.
- **(2026-04-14)** Added `contractDialog.presetDetails.*` keys to `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDialog.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F019` completed in `ContractTemplateDetail.tsx`: wired `useTranslation('msp/contracts')` and localized page-level header/back/error/loading copy, template badge/edit-toggle text, template basics edit-card labels/placeholders/actions, and template snapshot metadata labels (`Billing Frequency`, `Currency`, `Contract Lines`, `Created`, `Last Updated`).
- **(2026-04-14)** Shared enum migration in this file: replaced both `BILLING_FREQUENCY_OPTIONS` call sites with `useBillingFrequencyOptions()`.
- **(2026-04-14)** Added initial `templateDetail.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractTemplateDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F020` completed in `ContractTemplateDetail.tsx`: localized the contract-lines composition area (section title, group headings, empty states, per-line service counts, service-detail labels, bucket summaries) and template-service manager labels/actions (manager title, empty hint, fixed-fee-rate label, edit-rate action).
- **(2026-04-14)** Added `templateDetail.composition.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractTemplateDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F021` completed in `ContractTemplateDetail.tsx`: localized template guidance edit/review sections (`Usage Notes`, `Recommended Cadence`, `Tags`, placeholders/hints, save/cancel/saving labels) and translated template-level save/error feedback messages (`Template name is required`, billing-frequency required, failed-update basics/guidance, failed-load template).
- **(2026-04-14)** Added `templateDetail.guidance.*` and `templateDetail.validation.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractTemplateDetail.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F022` completed in `CreateCustomContractLineDialog.tsx`: wired `useTranslation('msp/contracts')`, localized dialog shell labels/actions, contract-line basics section, billing-frequency + billing-timing labels/options, billing-model selector copy (Fixed/Hourly/Usage cards), and top-level per-type section headers/descriptions.
- **(2026-04-14)** Shared enum migration in this file: replaced deprecated `BILLING_FREQUENCY_OPTIONS` with `useBillingFrequencyOptions()`.
- **(2026-04-14)** Added `createCustomLine.*` keys to `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/CreateCustomContractLineDialog.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F023` completed in `CreateCustomContractLineDialog.tsx`: localized form validation/error messages, bucket-overlay toggles (`Add bucket of hours/consumption`), and hourly minimum/round-up labels. Dialog create failure fallback message now uses `t()`.
- **(2026-04-14)** Added `createCustomLine.validation.*` plus additional bucket/hourly-label keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/CreateCustomContractLineDialog.tsx` (pass; warnings only, no errors).
- **(2026-04-14)** `F024` completed in `CreateCustomContractLineDialog.tsx`: localized fixed/hourly/usage service preview sections (section labels, item/service row labels, select placeholders, quantity/rate/unit labels, add buttons, empty states) and localized rate-helper displays with interpolation (`{{rate}}/hour`, `{{rate}}/{{unit}}`).
- **(2026-04-14)** Localized remaining help/tooltip-style explanatory alert copy in this dialog for Fixed/Hourly/Usage service configuration sections.
- **(2026-04-14)** Added `createCustomLine.*` keys for service preview and rate-display strings in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Repaired invalid `server/public/locales/en/msp/contracts.json` structure by reintegrating orphaned `contractDialog.documents|po|presets|presetDetails` and `templateDetail.composition` blocks back into the main object (file now parses via `jq`).
- **(2026-04-14)** Verification: `jq empty server/public/locales/en/msp/contracts.json` and `npx eslint packages/billing/src/components/billing-dashboard/contracts/CreateCustomContractLineDialog.tsx` (pass; warning-only lint).
- **(2026-04-14)** `F025` completed in `ContractLines.tsx`: wired `useTranslation('msp/contracts')` and localized section title/description, Add from Presets + Create Custom buttons, empty state copy, loading text, expand/collapse button labels, summary metadata labels (Name/Type/Frequency/Rate/Services), and action labels.
- **(2026-04-14)** Contract-line type/frequency summaries now use shared enum formatters via `useFormatContractLineType()` + `useFormatBillingFrequency()`.
- **(2026-04-14)** Added `contractLines.*` keys for top-level list UI in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractLines.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F026` completed in `ContractLines.tsx`: localized inline edit/configuration UI (billing timing, cadence owner, minimum/round-up fields, fixed/usage guidance), service-detail labels, save/cancel/saving controls, inline loading text, and bucket section labels/value templates.
- **(2026-04-14)** Added translated delete confirmation before removing a contract line (`window.confirm` with interpolated line name).
- **(2026-04-14)** Localized error-state fallbacks for contract-lines load/refresh/remove/editability/update flows in this component.
- **(2026-04-14)** Expanded `contractLines.errors|dialogs|configuration|services|bucket|loading.inline` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractLines.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F027` completed in `ContractLines.tsx`: localized expanded service-list labels (type label, quantity badge/field labels, hourly/unit/tax-allocation rate labels, unit-of-measure label/default, services section heading/count).
- **(2026-04-14)** Replaced `new Intl.NumberFormat('en-US', ...)` in `ContractLines.tsx` with locale-aware `useFormatters().formatCurrency(...)` for all rate displays; `formatRate` now uses active locale and tenant currency code.
- **(2026-04-14)** Removed unused `renderServiceDetails()` helper that still contained hardcoded English fragments and old locale formatting assumptions.
- **(2026-04-14)** Verification: `rg -n "new Intl.NumberFormat|en-US" packages/billing/src/components/billing-dashboard/contracts/ContractLines.tsx` (no matches) and `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractLines.tsx` (pass; warnings only).
- **(2026-04-14)** `F028` completed in `AddContractLinesDialog.tsx`: wired `useTranslation('msp/contracts')` and localized dialog title/header, search + type filter UI, reset action, loading/empty/no-match states, preset row metadata/service counts, select/deselect affordances, fixed-rate override labels, quantity/rate/unit field labels, and footer add/cancel actions.
- **(2026-04-14)** Shared enum migration in this file: replaced deprecated `CONTRACT_LINE_TYPE_DISPLAY` map with `useContractLineTypeOptions()` and used `useFormatContractLineType()` for preset type badges.
- **(2026-04-14)** Added initial `addLines.*` namespace keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/AddContractLinesDialog.tsx` (pass; warnings only), `rg -n "CONTRACT_LINE_TYPE_DISPLAY|_DISPLAY|_OPTIONS" .../AddContractLinesDialog.tsx` (no matches), and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F029` completed in `AddContractLinesDialog.tsx`: localized expanded preset detail sections (fixed-rate config, services reference/configuration, hourly overrides, usage quantity/rate/unit fields, default-rate helper text), plus empty-search and loading states.
- **(2026-04-14)** Added localized dialog-level validation/error feedback for preset load/details/add failures and rendered them via destructive `Alert`.
- **(2026-04-14)** Expanded `addLines.errors.*` and additional detail keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/AddContractLinesDialog.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F030` completed in `Contracts.tsx`: wired `useTranslation('msp/contracts')`, localized sub-tab labels via point-of-use mapping (no hook usage in `contractsTabs.ts`), localized New/Create actions, search placeholders + aria labels, draft badge count aria text, loading copy, draft empty-state text, and fetch-error alert fallback.
- **(2026-04-14)** Added `contractsList.search|actions|drafts|loading|errors|empty` keys in `server/public/locales/en/msp/contracts.json` and introduced a local `contractSubtabLabels` mapping helper in `Contracts.tsx` to satisfy `contractsTabs.ts` consumption-point translation requirement.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/Contracts.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F031` completed in `Contracts.tsx`: localized row action menus (edit/delete/resume/terminate/restore/set-active/discard + sr-only menu labels), status badges (active/draft/terminated/expired/published/archived), delete/discard confirmation dialogs (titles/messages/button labels with interpolation), and all related toast/error fallback messages.
- **(2026-04-14)** Expanded `contractsList.status|actions|dialogs|toasts|empty` keys in `server/public/locales/en/msp/contracts.json` to cover menu/dialog messaging and fallback record labels.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/Contracts.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F032` completed in `Contracts.tsx`: localized all current column headers across templates/client/drafts tables, translated dash/description fallback cell values, and localized contracts loading indicator text.
- **(2026-04-14)** Added explicit translated empty states for template/client/draft filtered views (`noTemplates`, `noClientContracts`, `noDraftMatches`) so each sub-tab has user-visible empty-copy coverage.
- **(2026-04-14)** Expanded `contractsList.columns|heading|empty` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/Contracts.tsx` (pass; warnings only), `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F033` completed in `ClientContractsTab.tsx`: wired `useTranslation('msp/contracts')`, localized client-contract table headers (including added billing-frequency + PO indicator columns), status badges, search placeholder/aria labels, row action menu labels, and related fallback/toast copy.
- **(2026-04-14)** Added a localized terminate confirmation dialog flow (`contractToTerminate` state + `ConfirmationDialog`) so terminate is explicitly confirmed before mutation.
- **(2026-04-14)** Expanded `clientContracts.*` keys in `server/public/locales/en/msp/contracts.json` (columns, search, dialogs, toasts, PO labels, upcoming-renewals labels/statuses/actions/window options).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ClientContractsTab.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F034` completed in `ClientContractsTab.tsx`: localized loading/error states, added translated empty-state rendering for filtered client contracts, and localized PO indicator column values (`Required` / `Not required`).
- **(2026-04-14)** Added `clientContracts.empty.noMatches` key in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ClientContractsTab.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F035` completed in `ContractWizard.tsx`: wired `useTranslation('msp/contracts')`, localized wizard step labels via memoized `stepLabels`, localized step validation errors, translated create/edit wizard titles, and localized unsaved-changes confirmation dialog copy.
- **(2026-04-14)** Added `wizard.steps|wizard.validation|wizard.title|wizard.dialogs.unsavedChanges` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractWizard.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F036` completed in `ContractWizard.tsx`: localized recurring authoring validation output by switching from raw helper English strings to translated `wizard.validation.unsupportedRecurringAuthoringCombination` with interpolation for line type and billing frequencies. Added recurring frequency/line-type subkeys under `wizard.validation.recurring.*`.
- **(2026-04-14)** `F036` also standardized template-load and draft/create failure surfaces to namespace-backed fallback messages (`wizard.errors.failedToLoadTemplates|failedToLoadTemplateDetails|failedToCreateContract|failedToSaveDraft`) so user-visible wizard status copy stays translatable.
- **(2026-04-14)** Supporting shared-helper change: exported `getUnsupportedRecurringAuthoringCombination(...)` from `shared/billingClients/recurringAuthoringValidation.ts` so UIs can localize without parsing English text; retained `getUnsupportedRecurringAuthoringCombinationMessage(...)` for existing consumers/tests and preserved prior wording semantics (`annual` in the supported list fallback sentence).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractWizard.tsx shared/billingClients/recurringAuthoringValidation.ts packages/billing/tests/recurringAuthoringValidation.wiring.test.ts` (pass), `npx vitest run recurringAuthoringValidation.wiring.test.ts` from `packages/billing` (pass), and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F037` completed in `ContractOverview.tsx`: wired `useTranslation('msp/contracts')` and localized overview header/title, stat card labels, variable-summary note, and the `View details` link; service type badges now use shared enum formatter `useFormatContractLineType()` (Fixed/Hourly/Usage).
- **(2026-04-14)** Currency-formatting cleanup in `ContractOverview.tsx`: replaced hardcoded `new Intl.NumberFormat('en-US', ...)` path with `useFormatters().formatCurrency` via `formatCurrencyCents(...)`, keeping locale-aware output and translated money placeholder fallback.
- **(2026-04-14)** Added `contractOverview.title` + `contractOverview.stats.*` keys to `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractOverview.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F038` completed in `ContractOverview.tsx`: localized line-card frequency and service-count copy, Included Services heading, no-services fallback, section-level Expand/Collapse all toggle, and no-lines empty-state/CTA text.
- **(2026-04-14)** Frequency labels now resolve through `useFormatBillingFrequency()` with localized fallbacks for values not covered by billing enums (`contractOverview.frequency.*`), preserving compatibility with both `semi-annually` and `semi_annually` inputs.
- **(2026-04-14)** Added `contractOverview.lines.*`, `contractOverview.frequency.*`, and `contractOverview.errors.failedToLoadOverview` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractOverview.tsx` (pass; warning-only `react-hooks/exhaustive-deps`), `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F039` completed in `PricingScheduleDialog.tsx`: wired `useTranslation('msp/contracts')` and localized dialog title/actions, all form labels/toggles/placeholders, duration-unit options, and validation/error fallback messages.
- **(2026-04-14)** Added `pricingSchedules.dialog.*` keys (actions, title, fields, duration units, validation, errors) in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/PricingScheduleDialog.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F040` completed in `PricingSchedules.tsx`: wired `useTranslation('msp/contracts')` and localized list header/title, table column headers, row action menu labels, delete confirmation text, read-only notice, empty-state copy, loading text, and timeline labels/value fallbacks (`Ongoing`, `Default rate`, `Use default rate`).
- **(2026-04-14)** Added `pricingSchedules.list.*` keys in `server/public/locales/en/msp/contracts.json` (actions, columns, dialogs, errors, loading, empty, timeline, values, read-only notice).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/PricingSchedules.tsx` (pass; warning-only `react-hooks/exhaustive-deps`) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F041` completed in `TemplatesTab.tsx`: wired `useTranslation('msp/contracts')`, localized template list column headers/status badges/search copy, create/edit/delete actions, loading and fetch/delete error fallbacks, and added explicit localized empty/no-match states for template searches.
- **(2026-04-14)** Added `templatesTab.*` keys to `server/public/locales/en/msp/contracts.json` (actions/columns/status/search/loading/errors/empty/values).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/TemplatesTab.tsx` (pass; warning-only `react-hooks/exhaustive-deps`) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F042` completed in `ServiceCatalogPicker.tsx`: wired `useTranslation('msp/contracts')` and localized picker placeholder, search placeholder, empty results text, product/service badges, and custom-item footer controls (`Custom` badge, add-as-custom text, type-name hint).
- **(2026-04-14)** Added `servicePicker.catalog.*` keys to `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ServiceCatalogPicker.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F043` completed in `ContractForm.tsx`: wired `useTranslation('msp/contracts')` and localized heading, field labels/placeholders, validation heading + required-field list labels, status option labels/expired helper note, and save button states.
- **(2026-04-14)** Shared enum migration in `ContractForm.tsx`: replaced deprecated `BILLING_FREQUENCY_OPTIONS` with `useBillingFrequencyOptions()` from `@alga-psa/billing/hooks/useBillingEnumOptions`.
- **(2026-04-14)** Added `contractForm.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractForm.tsx` (pass; existing warning-only `no-non-null-assertion`/`no-explicit-any`), `rg -n "BILLING_FREQUENCY_OPTIONS" .../ContractForm.tsx` (no matches), and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F044` completed in `QuickStartGuide.tsx`: wired `useTranslation('msp/contracts')` and localized collapsed/expanded guide titles, show/minimize/dismiss controls, all three step headings + descriptions + helper notes, billing model labels/descriptions, best-practices title/list items, and the create-first-contract CTA.
- **(2026-04-14)** Added `quickStart.*` key tree in `server/public/locales/en/msp/contracts.json` (actions, badge, subtitle, steps, billingModels, bestPractices).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/QuickStartGuide.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F045` completed in `BucketOverlayFields.tsx`: wired `useTranslation('msp/contracts')` and localized included-units label/tooltips, overage-rate label + tooltip with interpolated units, and rollover label/description with unit interpolation.
- **(2026-04-14)** Added `bucketOverlay.*` keys in `server/public/locales/en/msp/contracts.json` including `units.hour|hours|units` and placeholder strings.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/BucketOverlayFields.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F046` completed in `ContractLineEditDialog.tsx`: wired `useTranslation('msp/contracts')` and localized interpolated dialog title, pricing/timing section labels, timing options + contextual descriptions, validation fallback, and footer action states (`Save Changes` / `Saving...` / `Cancel`).
- **(2026-04-14)** Added `contractLineEdit.*` keys in `server/public/locales/en/msp/contracts.json` (title, sections, fields, timing options/descriptions, validation, actions, fallback values).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractLineEditDialog.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F047` completed in `ContractHeader.tsx`: wired `useTranslation('msp/contracts')`, localized stat labels, status badges, template/client-owned badges, ongoing value, and PO alert copy.
- **(2026-04-14)** Contract-header frequency display now uses shared enum formatter `useFormatBillingFrequency()` instead of local title-casing.
- **(2026-04-14)** Added `contractHeader.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractHeader.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F048` completed in `ContractDetailSwitcher.tsx`: wired `useTranslation('msp/contracts')` and localized all loading/error states (`missing contract id`, `contract not found`, `unable/failed to load details`, `no contract selected`, `Loading contract...`).
- **(2026-04-14)** Added `detailSwitcher.errors.*` + `detailSwitcher.loading.contract` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractDetailSwitcher.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F049` completed in `ContractLineRateDialog.tsx` and `ContractPlanRateDialog.tsx`: wired `useTranslation('msp/contracts')` in both dialogs and localized interpolated title, rate field label, validation fallback, and Save Rate/Cancel actions.
- **(2026-04-14)** Added shared `contractLineRate.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ContractLineRateDialog.tsx packages/billing/src/components/billing-dashboard/contracts/ContractPlanRateDialog.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F050` completed in `BillingFrequencyOverrideSelect.tsx`: wired `useTranslation('msp/contracts')` for label/description/placeholder/confirmation copy with interpolation and switched deprecated enum constants to hooks (`useBillingFrequencyOptions`, `useFormatBillingFrequency`).
- **(2026-04-14)** Added `frequencyOverride.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/BillingFrequencyOverrideSelect.tsx` (pass), `rg -n "BILLING_FREQUENCY_OPTIONS|BILLING_FREQUENCY_DISPLAY" .../BillingFrequencyOverrideSelect.tsx` (no matches), and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F051` completed in `ServicePicker.tsx`: wired `useTranslation('msp/contracts')` and localized default placeholder, search placeholder, and empty-message copy.
- **(2026-04-14)** Expanded `servicePicker.*` keys in `server/public/locales/en/msp/contracts.json` with top-level picker strings while preserving `servicePicker.catalog.*` for async catalog picker.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/ServicePicker.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F052` completed in `wizard-steps/ContractBasicsStep.tsx`: wired `useTranslation('msp/contracts')` for the step shell and first-section UX (heading/description, template picker labels + loading text + preview labels, client label/loading/select/hint, and contract-name label/placeholder/hint).
- **(2026-04-14)** Added `wizardBasics.heading|description|template.*|client.*|contractName.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx` (pass; warnings only) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F053` completed in `wizard-steps/ContractBasicsStep.tsx`: localized remaining basics-step copy for billing frequency/cadence owner/currency/date fields, fixed-term + evergreen renewal blocks, optional description, PO configuration, and contract summary labels/values.
- **(2026-04-14)** Shared enum migration in this file: replaced deprecated `BILLING_FREQUENCY_OPTIONS` usage with `useBillingFrequencyOptions()` and `useFormatBillingFrequency()` for field options + summary display.
- **(2026-04-14)** Currency-formatting cleanup in summary PO amount: removed hardcoded `formatCurrencyFromMinorUnits(..., 'en-US', ...)` path in favor of locale-aware `useFormatters().formatCurrency`.
- **(2026-04-14)** Expanded `wizardBasics.*` key tree in `server/public/locales/en/msp/contracts.json` (billingFrequency, cadenceOwner, currency, dates, renewal, additionalDescription, po, summary with pluralized values).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx` (pass; warning-only non-null assertions), `rg -n "BILLING_FREQUENCY_OPTIONS" .../ContractBasicsStep.tsx` (no matches), and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F054` completed in `wizard-steps/FixedFeeServicesStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, fixed-fee explainer, base-rate section, proration copy, service picker labels/actions, empty-state text, recurring preview labels, and alternate billing-frequency override label.
- **(2026-04-14)** Added `wizardFixed.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/FixedFeeServicesStep.tsx` (pass; warning-only pre-existing unused `BucketOverlayFields`/overlay helpers), `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F055` completed in `wizard-steps/ProductsStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, product picker labels/placeholders, quantity + override-rate labels, default-price/helper/error copy, add-product action, and empty-state text.
- **(2026-04-14)** Added `wizardProducts.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ProductsStep.tsx` (pass; warning-only pre-existing unused `_` destructuring vars), and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F056` completed in `wizard-steps/HourlyServicesStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, hourly explainer copy, minimum/round-up field labels+hints, service picker + hourly-rate labels, bucket toggle label, empty state, summary labels, and alternate billing-frequency override label.
- **(2026-04-14)** Added `wizardHourly.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/HourlyServicesStep.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F057` completed in `wizard-steps/UsageBasedServicesStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, usage explainer, service picker/unit-rate/unit-of-measure labels+helpers, bucket toggle label, empty-state copy, summary labels, and alternate billing-frequency override label.
- **(2026-04-14)** Added `wizardUsage.*` keys in `server/public/locales/en/msp/contracts.json`.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/UsageBasedServicesStep.tsx` (pass) and `jq empty server/public/locales/en/msp/contracts.json` (pass).
- **(2026-04-14)** `F058` completed in `ReviewContractStep.tsx`: wired `useTranslation('msp/contracts')` and translated review heading/description plus Contract Basics labels (`Client`, `Contract Name`, `Billing Frequency`, `Currency`, `Start Date`, `End Date`, `Renewal Mode`, `Notice Period`, `Renewal Term`) and fallback values (`Not selected`, `Not specified`, `N/A`, `Ongoing`).
- **(2026-04-14)** Shared enum migration in this file (part 1): replaced `BILLING_FREQUENCY_OPTIONS` lookup with `useBillingFrequencyOptions()` for the Contract Basics billing-frequency display.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ReviewContractStep.tsx` (pass), `rg -n "formatCurrencyFromMinorUnits\\(|en-US" .../ReviewContractStep.tsx` (no matches), and `rg -n "BILLING_FREQUENCY_OPTIONS|BILLING_FREQUENCY_DISPLAY" .../ReviewContractStep.tsx` (no matches).
- **(2026-04-14)** `F059` completed in `ReviewContractStep.tsx`: localized all service summary sections (Fixed Fee, Products, Hourly, Usage-Based), including section headings/count badges, service rows, rate/unit displays, bucket summaries, PO requirements card, monthly total summary card, and final pre-submit checklist text.
- **(2026-04-14)** Shared enum migration in this file (part 2): replaced `BILLING_FREQUENCY_DISPLAY[...]` override renderers with `useFormatBillingFrequency()` for fixed/hourly/usage billing-frequency override labels.
- **(2026-04-14)** Expanded `wizardReview.*` keys in `server/public/locales/en/msp/contracts.json` to cover service summaries, recurring preview copy, PO labels, bucket interpolation strings, and checklist/total labels.
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ReviewContractStep.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and key coverage audit for all `wizardReview.*` usages in `ReviewContractStep.tsx` (`missing 0`).
- **(2026-04-14)** `F060` completed in `template-wizard/TemplateWizard.tsx`: wired `useTranslation('msp/contracts')` and localized template wizard step labels (`Template Basics`, `Fixed Fee Blocks`, `Products`, `Hourly Blocks`, `Usage-Based Blocks`, `Review & Publish`), dialog title, and navigation button labels (`Continue`, `Publish Template`).
- **(2026-04-14)** Localized template-wizard validation/errors for template name required, billing frequency required, duplicate name states, at-least-one-service requirement, failed-create fallback, and recurring-authoring unsupported-combination copy.
- **(2026-04-14)** Recurring validation migration: switched from raw `getUnsupportedRecurringAuthoringCombinationMessage()` string pass-through to structured `getUnsupportedRecurringAuthoringCombination()` + localized interpolation (`templateWizard.validation.unsupportedRecurringAuthoringCombination`) with translated line-type/frequency labels.
- **(2026-04-14)** Added `templateWizard.*` keys in `server/public/locales/en/msp/contracts.json` (`title`, `steps`, `actions`, `errors`, `validation`, and `validation.recurring.*`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/TemplateWizard.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and `rg -n "Create Contract Template|Template Basics|Publish Template|Template name is required" .../TemplateWizard.tsx` (matches only `defaultValue` fallbacks).
- **(2026-04-14)** `F061` completed in `template-wizard/steps/TemplateContractBasicsStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, Template Name label+placeholder+help text, Internal Notes label+placeholder+help text, and Recommended Billing Frequency label+placeholder+help text.
- **(2026-04-14)** Shared enum migration in this file: replaced deprecated `BILLING_FREQUENCY_OPTIONS` with `useBillingFrequencyOptions()` for the billing-frequency select.
- **(2026-04-14)** Added `templateBasics.*` keys in `server/public/locales/en/msp/contracts.json` (`heading`, `description`, `fields`, `placeholders`, `help`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/steps/TemplateContractBasicsStep.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and `rg -n "BILLING_FREQUENCY_OPTIONS|BILLING_FREQUENCY_DISPLAY" .../TemplateContractBasicsStep.tsx` (no matches).
- **(2026-04-14)** `F062` completed in `template-wizard/steps/TemplateFixedFeeServicesStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, fixed-fee explainer panel, cadence-owner labels/help/options, billing-timing label/options/placeholder, proration toggle label/help, service picker labels/placeholders, quantity helper text, and add-service action.
- **(2026-04-14)** Added translation wrappers for preview-specific fallback labels (`Unknown Service`, `Cadence Owner:`, `Billing Timing:`, `Service:`, `Invoice window:`) and ensured template-fixed keys are fully present under `templateFixed.*`.
- **(2026-04-14)** Added `templateFixed.*` keys in `server/public/locales/en/msp/contracts.json` (`heading`, `description`, `info`, `cadenceOwner`, `billingTiming`, `fields`, `placeholders`, `help`, `preview`, `actions`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/steps/TemplateFixedFeeServicesStep.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and key coverage audit for `templateFixed.*` usages (`missing 0`).
- **(2026-04-14)** `F063` completed in `template-wizard/steps/TemplateProductsStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, products section label, per-row product labels, select-product placeholder, quantity label/help text, and add-product action.
- **(2026-04-14)** Added translation wrapper for preview fallback `Unknown Product` and ensured all `templateProducts.*` usages are backed by locale keys.
- **(2026-04-14)** Added `templateProducts.*` keys in `server/public/locales/en/msp/contracts.json` (`heading`, `description`, `fields`, `placeholders`, `help`, `actions`, `preview`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/steps/TemplateProductsStep.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and key coverage audit for `templateProducts.*` usages (`missing 0`).
- **(2026-04-14)** `F064` completed in `template-wizard/steps/TemplateHourlyServicesStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, hourly explainer, time-rounding settings heading/labels/hints, service picker labels/placeholders, bucket toggle label, and add-service action.
- **(2026-04-14)** Added translation wrapper for preview fallback `Unknown Service` and ensured all `templateHourly.*` usages are backed by locale keys.
- **(2026-04-14)** Added `templateHourly.*` keys in `server/public/locales/en/msp/contracts.json` (`heading`, `description`, `info`, `rounding`, `fields`, `placeholders`, `preview`, `actions`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/steps/TemplateHourlyServicesStep.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and key coverage audit for `templateHourly.*` usages (`missing 0`).
- **(2026-04-14)** `F065` completed in `template-wizard/steps/TemplateUsageBasedServicesStep.tsx`: wired `useTranslation('msp/contracts')` and localized step heading/description, usage explainer, services section labels, per-row service labels, unit-of-measure label/placeholder/help text, bucket-allocation toggle label, and add-service action.
- **(2026-04-14)** Added translation wrapper for preview fallback `Unknown Service` and ensured all `templateUsage.*` usages are backed by locale keys.
- **(2026-04-14)** Added `templateUsage.*` keys in `server/public/locales/en/msp/contracts.json` (`heading`, `description`, `info`, `fields`, `placeholders`, `help`, `preview`, `actions`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/steps/TemplateUsageBasedServicesStep.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and key coverage audit for `templateUsage.*` usages (`missing 0`).
- **(2026-04-14)** `F066` completed in `template-wizard/steps/TemplateReviewContractStep.tsx`: wired `useTranslation('msp/contracts')` and localized review heading/description, Template Basics labels/fallbacks, service section titles, quantity/unit/bucket labels, cadence/billing summary labels, and bucket-summary interpolation strings.
- **(2026-04-14)** Added explicit empty-section indicators for each service group in review (`fixed`, `products`, `hourly`, `usage`) so the step always renders section-level feedback even with no selected services.
- **(2026-04-14)** Added `templateReview.*` keys in `server/public/locales/en/msp/contracts.json` (`sections`, `fields`, `fallback`, `empty`, `common`, `fixed`, `hourly`, `usage`, `bucket`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/steps/TemplateReviewContractStep.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and key coverage audit for `templateReview.*` usages (`missing 0`).
- **(2026-04-14)** `F067` completed in `template-wizard/TemplateServicePreviewSection.tsx`: wired `useTranslation('msp/contracts')` and localized service type labels (`Fixed Fee`, `Products`, `Hourly`, `Usage-Based`), selected-services heading with interpolation (`{{type}}`, `{{count}}`), and the quantity label (`Qty:`).
- **(2026-04-14)** Localized preset-remove confirmation dialog title/message/confirm/cancel labels using interpolation (`{{serviceName}}`, `{{presetName}}`).
- **(2026-04-14)** Added `templatePreview.*` keys in `server/public/locales/en/msp/contracts.json` (`serviceType`, `selectedHeading`, `labels.qty`, `removeDialog.*`).
- **(2026-04-14)** Verification: `npx eslint packages/billing/src/components/billing-dashboard/contracts/template-wizard/TemplateServicePreviewSection.tsx` (pass), `jq empty server/public/locales/en/msp/contracts.json` (pass), and key coverage audit for `templatePreview.*` usages (`missing 0`).
- **(2026-04-14)** `T001` completed: ran `node scripts/generate-pseudo-locales.cjs && node scripts/validate-translations.cjs` after syncing missing `msp/contracts` keys from English into `de/es/fr/it/nl/pl` locale files.
- **(2026-04-14)** Validation result: `Errors: 0`, `Warnings: 0`, `PASSED` across `de/es/fr/it/nl/pl/xx/yy`.
- **(2026-04-14)** Locale maintenance note: this pass only backfilled missing keys for parity; existing translated values were preserved, and newly introduced keys currently default to English text until follow-up translation refresh.
- **(2026-04-14)** `T002` completed: added `packages/billing/tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` with a ContractDetail tab-label wiring assertion (`contractDetail.tabs.overview|lines|pricing|documents|invoices`) validating both source `t(...)` usage and English locale key presence.
- **(2026-04-14)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-14)** `T003` completed: extended `ContractsSubbatch.i18n.test.ts` with ContractDetail alert-key coverage (`contractDetail.alerts.unsavedChanges`, `contractDetail.alerts.saveSuccess`) and English-locale value assertions.
- **(2026-04-14)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-14)** `T004` completed: extended `ContractsSubbatch.i18n.test.ts` with details-card wiring checks covering `contractDetail.detailsCard.*` labels and edit/save/cancel action keys plus `contractDetail.labels.noDescription` locale presence.
- **(2026-04-14)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 3 tests).
- **(2026-04-15)** `T005` completed: extended `packages/billing/tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` with ContractDetail header-card i18n coverage for status/billing/currency/renewal labels (`contractDetail.headerCard.*`, `status.*`, `renewal.*`, `common.labels.*`) and English locale key-presence assertions.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 4 tests).
- **(2026-04-15)** `T006` completed: extended `packages/billing/tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` with Client Ownership + Client Assignment coverage asserting translated labels for cards, PO fields, yes/no + ongoing values, and the no-client-assigned empty state.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 5 tests).
- **(2026-04-15)** `T007` completed: added ContractDetail assertions for translated quick-action buttons, footer save/cancel/saving labels, and discard/unsaved/delete confirmation dialog copy in `ContractsSubbatch.i18n.test.ts`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 6 tests).
- **(2026-04-15)** `T008` completed: added invoice-tab i18n coverage in `ContractsSubbatch.i18n.test.ts` for ContractDetail title/help text, refresh CTA, loading/empty/no-template states, invoice preview label, and table column headers.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 7 tests).
- **(2026-04-15)** `T009` completed: added pseudo-locale guard in `ContractsSubbatch.i18n.test.ts` that extracts all `ContractDetail.tsx` translation keys and asserts each resolves to `xx` pseudo values (`11111` pattern), covering all tabs.
- **(2026-04-15)** Discovery/fix: `contractDetail.documents.loading` was referenced in `ContractDetail.tsx` but missing from locale JSON. Added `contractDetail.documents.loading` to all 9 locale files (`en/de/es/fr/it/nl/pl/xx/yy`) with pseudo values for `xx`/`yy`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsSubbatch.i18n.test.ts` (pass; 1 file, 8 tests) and `node scripts/validate-translations.cjs` (pass; Errors: 0, Warnings: 0).
- **(2026-04-15)** `T010` completed: added `packages/billing/tests/billing-dashboard/ContractDialog.i18n.test.ts` with coverage for ContractDialog title/form/renewal labels and validation keys, asserting both source `t(...)` usage and English locale-key presence.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractDialog.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T011` completed: extended `ContractDialog.i18n.test.ts` with PO section and preset-picker coverage (labels, helper copy, loading/empty/no-match states, selected-count copy, and preset detail headings), validating source key usage + English locale presence.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractDialog.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T012` completed: added pseudo-locale coverage in `ContractDialog.i18n.test.ts` by extracting all `t('...')` keys from `ContractDialog.tsx` and asserting each resolves to `xx` pseudo-locale values (`11111`), guarding against fallback English leakage.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractDialog.i18n.test.ts` (pass; 1 file, 3 tests).
- **(2026-04-15)** `T013` completed: added `packages/billing/tests/billing-dashboard/ContractTemplateDetail.i18n.test.ts` with page-level i18n assertions for loading/error header copy, back-to-templates actions, template badge/snapshot labels, and key section labels used by ContractTemplateDetail.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractTemplateDetail.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T014` completed: extended `ContractTemplateDetail.i18n.test.ts` with template composition + service-manager coverage for grouped line headings, empty states, service-count copy, inline service labels, bucket/minutes formatting labels, and service management action text.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractTemplateDetail.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T015` completed: extended `ContractTemplateDetail.i18n.test.ts` to validate translated cadence labels in `ContractTemplateDetail.tsx` and billing-timing option/description labels used in the template line edit flow (`ContractLineEditDialog.tsx`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractTemplateDetail.i18n.test.ts` (pass; 1 file, 3 tests).
- **(2026-04-15)** `T016` completed: added pseudo-locale coverage in `ContractTemplateDetail.i18n.test.ts` by extracting all `t('...')` keys used in `ContractTemplateDetail.tsx` and asserting each resolves to `xx` pseudo values (`11111`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractTemplateDetail.i18n.test.ts` (pass; 1 file, 4 tests).
- **(2026-04-15)** `T017` completed: added `packages/billing/tests/billing-dashboard/CreateCustomContractLineDialog.i18n.test.ts` with i18n wiring assertions for dialog shell labels, billing-frequency/timing controls, billing-model selector copy, and service-picker labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/CreateCustomContractLineDialog.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T018` completed: extended `CreateCustomContractLineDialog.i18n.test.ts` with coverage for bucket/proration copy and validation surfaces (all `createCustomLine.validation.*` keys + validation prefix), ensuring translated labels and errors are wired.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/CreateCustomContractLineDialog.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T019` completed: added pseudo-locale coverage in `CreateCustomContractLineDialog.i18n.test.ts` by extracting all dialog `t('...')` keys and asserting they resolve to `xx` pseudo values (`11111`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/CreateCustomContractLineDialog.i18n.test.ts` (pass; 1 file, 3 tests).
- **(2026-04-15)** `T020` completed: added `packages/billing/tests/billing-dashboard/ContractLines.i18n.test.ts` with coverage for ContractLines header/description, add/create actions, expand/collapse controls, summary column labels, service-count copy, loading copy, and empty-state text.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractLines.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T021` completed: extended `ContractLines.i18n.test.ts` with inline-edit and service-detail coverage (configuration labels, timing/cadence labels, service/bucket detail labels, delete confirmation, and editability error text).
- **(2026-04-15)** Discovery/fix: `billing.labels.cadenceOwner` was referenced in `ContractLines.tsx` but missing from locale files. Added the key across all 9 `msp/contracts` locale files (`en/de/es/fr/it/nl/pl/xx/yy`) with pseudo values for `xx`/`yy`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractLines.i18n.test.ts` (pass; 1 file, 2 tests) and `node scripts/validate-translations.cjs` (pass; Errors: 0, Warnings: 0).
- **(2026-04-15)** `T022` completed: added pseudo-locale coverage in `ContractLines.i18n.test.ts` by extracting all `t('...')` keys used in `ContractLines.tsx` and asserting they resolve to `xx` pseudo values (`11111`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractLines.i18n.test.ts` (pass; 1 file, 3 tests).
- **(2026-04-15)** `T023` completed: added `packages/billing/tests/billing-dashboard/AddContractLinesDialog.i18n.test.ts` covering AddContractLinesDialog shell copy (title/search/filter/reset/loading/empty), add-action labels, and preset-selection count labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/AddContractLinesDialog.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T024` completed: extended `AddContractLinesDialog.i18n.test.ts` with expanded preset-detail coverage (fixed/hourly/usage configuration labels + helper copy) and dialog-level loading/empty/error states.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/AddContractLinesDialog.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T025` completed: added `packages/billing/tests/billing-dashboard/Contracts.i18n.test.ts` covering Contracts sub-tab labels (point-of-use translation), create actions, search placeholders/aria labels, drafts badge copy, and page heading/loading/error labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/Contracts.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T026` completed: extended `Contracts.i18n.test.ts` with row-action menu, confirmation dialog, and toast/operation-status i18n coverage for templates/client contracts/drafts workflows.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/Contracts.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T027` completed: extended `Contracts.i18n.test.ts` with all active table-column header key checks across template, client, and draft views, plus related per-subtab empty/loading labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/Contracts.i18n.test.ts` (pass; 1 file, 3 tests).
- **(2026-04-15)** `T028` completed: added pseudo-locale coverage in `Contracts.i18n.test.ts` by extracting all `t('...')` keys from `Contracts.tsx` and asserting they resolve to `xx` pseudo values (`11111`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/Contracts.i18n.test.ts` (pass; 1 file, 4 tests).
- **(2026-04-15)** `T029` completed: added `packages/billing/tests/billing-dashboard/ClientContractsTab.i18n.test.ts` with i18n assertions for client-contract table columns, PO indicator labels, status badge labels, top-level tab labels, and search placeholder/aria text.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ClientContractsTab.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T030` completed: extended `ClientContractsTab.i18n.test.ts` with loading/error/empty-state checks and terminate-confirmation dialog copy coverage, plus related operation failure toasts.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ClientContractsTab.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T031` completed: added `packages/billing/tests/billing-dashboard/ContractWizard.i18n.test.ts` with ContractWizard step-label i18n checks (`wizard.steps.*`) plus translated create/edit wizard title keys.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractWizard.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T032` completed: extended `ContractWizard.i18n.test.ts` with validation/error coverage for required wizard fields, recurring-authoring unsupported-combination copy (including dynamic recurring key usage checks), save-draft/create failure messages, and unsaved-changes confirmation dialog labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractWizard.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T033` completed: added `packages/billing/tests/billing-dashboard/ContractOverview.i18n.test.ts` with stat-card and overview-heading i18n assertions for `ContractOverview.tsx`.
- **(2026-04-15)** Discovery/fix: `common.moneyPlaceholder` was referenced in `ContractOverview.tsx` but missing from `msp/contracts` locale files. Added it across all 9 locales (`en/de/es/fr/it/nl/pl/xx/yy`) with pseudo values for `xx`/`yy`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractOverview.i18n.test.ts` (pass; 1 file, 1 test) and `node scripts/validate-translations.cjs` (pass; Errors: 0, Warnings: 0).
- **(2026-04-15)** `T034` completed: extended `ContractOverview.i18n.test.ts` with line-card coverage for service-count interpolation keys, included-services/no-services labels, expand/collapse controls, and no-lines empty-state copy; also asserted dynamic frequency-key usage and fallback-frequency key presence.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractOverview.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T035` completed: added `packages/billing/tests/billing-dashboard/PricingSchedules.i18n.test.ts` with list + dialog coverage for pricing schedules (title/columns/actions/loading/empty/timeline copy and dialog fields/actions/validation/errors).
- **(2026-04-15)** Discovery/fix: `common.actions.openMenu` and `common.notAvailable` were referenced in `PricingSchedules.tsx` but missing from `msp/contracts` locales. Added both keys across all 9 locales (`en/de/es/fr/it/nl/pl/xx/yy`) with pseudo values for `xx`/`yy`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/PricingSchedules.i18n.test.ts` (pass; 1 file, 1 test) and `node scripts/validate-translations.cjs` (pass; Errors: 0, Warnings: 0).
- **(2026-04-15)** `T036` completed: added `packages/billing/tests/billing-dashboard/TemplatesTab.i18n.test.ts` with coverage for TemplatesTab columns/status labels, search placeholders, row actions, loading/error/empty copy, and menu accessibility label.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplatesTab.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T037` completed: added `packages/billing/tests/billing-dashboard/ContractForm.i18n.test.ts` with i18n coverage for ContractForm heading/fields, status options + expired helper, validation/error copy, and save button states.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractForm.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T038` completed: added `packages/billing/tests/billing-dashboard/QuickStartGuide.i18n.test.ts` with full QuickStart content-key coverage (actions, steps, billing-model labels/descriptions, and best-practice items).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/QuickStartGuide.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T039` completed: extended `QuickStartGuide.i18n.test.ts` with pseudo-locale coverage by extracting all `QuickStartGuide.tsx` translation keys and asserting `xx` values use the pseudo pattern (`11111`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/QuickStartGuide.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T040` completed: added `packages/billing/tests/billing-dashboard/BucketOverlayFields.i18n.test.ts` with bucket-overlay i18n assertions for included/overage/rollover labels/tooltips/placeholders and unit strings.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/BucketOverlayFields.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T041` completed: added `packages/billing/tests/billing-dashboard/ContractLineEditDialog.i18n.test.ts` with translation-key assertions for dialog title interpolation, pricing/timing section labels, timing options/descriptions, validation/error copy, and save/cancel states.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractLineEditDialog.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T042` completed: added `packages/billing/tests/billing-dashboard/ContractHeader.i18n.test.ts` with translation-key checks for stat labels, status badges, template/client-owned badges, ongoing/not-available values, and PO-required alert copy.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractHeader.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T043` completed: added `packages/billing/tests/billing-dashboard/ContractDetailSwitcher.i18n.test.ts` to assert `ContractDetailSwitcher.tsx` wires all loading/error states through `t('detailSwitcher.*')` in `msp/contracts` and that matching English locale keys exist.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractDetailSwitcher.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T044` completed: added `packages/billing/tests/billing-dashboard/ContractLineRateDialog.i18n.test.ts` with assertions that both `ContractLineRateDialog.tsx` and `ContractPlanRateDialog.tsx` use `contractLineRate.*` translation keys for title interpolation, rate field label, validation copy, and action labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractLineRateDialog.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T045` completed: added `packages/billing/tests/billing-dashboard/BillingFrequencyOverrideSelect.i18n.test.ts` to verify label/description/placeholder/confirmation strings are wired to `frequencyOverride.*` keys with interpolation variables sourced from formatted billing-frequency labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/BillingFrequencyOverrideSelect.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T046` completed: added `packages/billing/tests/billing-dashboard/ServicePicker.i18n.test.ts` verifying picker placeholder/search/empty states are sourced from `servicePicker.*` translation keys and exist in `en/msp/contracts.json`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ServicePicker.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T047` completed: added `packages/billing/tests/billing-dashboard/ContractBasicsStep.i18n.test.ts` with assertions covering translated heading/description, template picker labels/loading copy, client picker labels/hint, and contract-name field copy in `ContractBasicsStep.tsx`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractBasicsStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T048` completed: extended `packages/billing/tests/billing-dashboard/ContractBasicsStep.i18n.test.ts` to assert renewal-mode/cadence-owner/PO copy and summary labels are translated in `ContractBasicsStep.tsx`, including pluralized locale coverage for `noticePeriodDays_*` and `renewalTermMonths_*`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractBasicsStep.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T049` completed: added `packages/billing/tests/billing-dashboard/FixedFeeServicesStep.i18n.test.ts` covering translated heading/description, base-rate + proration labels, service picker labels, empty state, and alternate billing-frequency label in `FixedFeeServicesStep.tsx`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/FixedFeeServicesStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T050` completed: added `packages/billing/tests/billing-dashboard/ProductsStep.i18n.test.ts` with assertions for translated step heading/description, product picker labels, quantity/override-rate/default-price copy, validation messages, add action, and empty state in `ProductsStep.tsx`.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ProductsStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T051` completed: added `packages/billing/tests/billing-dashboard/HourlyServicesStep.i18n.test.ts` validating translated step/explainer copy, minimum-time and round-up labels/hints, service picker/hourly-rate labels, add action, empty state, and alternate frequency label.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/HourlyServicesStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T052` completed: added `packages/billing/tests/billing-dashboard/UsageBasedServicesStep.i18n.test.ts` validating translated heading/description, service picker labels, unit-rate/unit-of-measure copy, bucket toggle label, add action, empty state, and alternate frequency label.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/UsageBasedServicesStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T053` completed: added `packages/billing/tests/billing-dashboard/ReviewContractStep.i18n.test.ts` asserting Contract Basics heading/field labels, renewal-mode labels, and fallback values (`Not selected`, `Not specified`, `N/A`, `Ongoing`) are translation-key backed.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ReviewContractStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T054` completed: extended `packages/billing/tests/billing-dashboard/ReviewContractStep.i18n.test.ts` with coverage for fixed/products/hourly/usage summary sections, rate and bucket interpolation keys, PO summary labels, monthly-total card, and final checklist copy.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ReviewContractStep.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T055` completed: added `packages/billing/tests/billing-dashboard/TemplateWizard.i18n.test.ts` verifying template-wizard step labels/actions/validation/errors are translation-key driven, including dynamic recurring line-type/frequency lookups and locale-key presence.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateWizard.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T056` completed: added `packages/billing/tests/billing-dashboard/TemplateContractBasicsStep.i18n.test.ts` with key assertions for step heading/description plus template-name, internal-notes, and recommended-billing-frequency labels/placeholders/help text.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateContractBasicsStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T057` completed: added `packages/billing/tests/billing-dashboard/TemplateFixedFeeServicesStep.i18n.test.ts` verifying translated step/explainer/cadence-owner/billing-timing labels, service picker fields, add action, and preview copy.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateFixedFeeServicesStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T058` completed: added `packages/billing/tests/billing-dashboard/TemplateProductsStep.i18n.test.ts` to validate translated heading/description, product picker labels/placeholders/help, add action, and unknown-product preview fallback.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateProductsStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T059` completed: added `packages/billing/tests/billing-dashboard/TemplateHourlyServicesStep.i18n.test.ts` with assertions for translated heading/explainer, rounding settings labels/help, service picker fields, bucket toggle label, add action, and preview fallback copy.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateHourlyServicesStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T060` completed: added `packages/billing/tests/billing-dashboard/TemplateUsageBasedServicesStep.i18n.test.ts` to verify translated heading/explainer copy, service picker + unit-of-measure labels/placeholders/help, bucket allocation label, add action, and preview fallback.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateUsageBasedServicesStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T061` completed: added `packages/billing/tests/billing-dashboard/TemplateReviewContractStep.i18n.test.ts` with key assertions for review sections, empty states, service summary labels, cadence/billing labels, and bucket interpolation strings.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateReviewContractStep.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T062` completed: added `packages/billing/tests/billing-dashboard/TemplateServicePreviewSection.i18n.test.ts` to assert service-type labels, selected-services heading interpolation, quantity label, and remove-confirmation dialog copy are translation-key backed.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/TemplateServicePreviewSection.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T063` completed: added `packages/billing/tests/billing-dashboard/ContractsIntegration.i18n.test.ts` integration-style coverage validating `/msp/billing` route namespace preload includes `msp/contracts`, Contracts/Templates/ClientContracts components use `useTranslation('msp/contracts')`, sub-tab labels are translated at consumption (`common.tabs.*`), and all extracted `t('...')` keys across these files resolve in English locale.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsIntegration.i18n.test.ts` (pass; 1 file, 1 test).
- **(2026-04-15)** `T064` completed: extended `ContractsIntegration.i18n.test.ts` with German-locale integration assertions covering contracts sub-tab labels, key presence for columns/actions, and source wiring for translated sub-tab/column/action-menu keys. Added explicit de-vs-en differentiation checks for `common.tabs.*` labels.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsIntegration.i18n.test.ts` (pass; 1 file, 2 tests).
- **(2026-04-15)** `T065` completed: extended integration coverage to validate contract-detail route translation wiring across `ContractDetail.tsx`, `ContractLines.tsx`, and `PricingSchedules.tsx`; asserts all extracted translation keys resolve in both `en` and `de`, plus explicit de-vs-en localization checks for detail tab labels (`overview/lines/pricing/documents/invoices`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsIntegration.i18n.test.ts` (pass; 1 file, 3 tests).
- **(2026-04-15)** `T066` completed: extended integration coverage for the contract creation wizard (`ContractWizard` + all six wizard-step components). The test extracts all literal `t('...')` keys, verifies key-set breadth (`>220`), and asserts locale resolution in both `en` and `de` (with plural-handling checks for `wizardBasics.summary.values.noticePeriodDays_*` and `renewalTermMonths_*`).
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsIntegration.i18n.test.ts` (pass; 1 file, 4 tests).
- **(2026-04-15)** `T067` completed: extended integration coverage for template creation flow (`TemplateWizard` + all template-step components + `TemplateServicePreviewSection`). The test extracts literal translation keys (`>120`) and verifies key resolution across both `en` and `de` locales.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsIntegration.i18n.test.ts` (pass; 1 file, 5 tests).
- **(2026-04-15)** `T068` completed: extended integration suite with `QuickStartGuide` coverage asserting all extracted translation keys resolve in `de` and pseudo-locale `xx`; pseudo assertions (`contains '11111'`) enforce that visible quick-start copy is translation-driven rather than hardcoded.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsIntegration.i18n.test.ts` (pass; 1 file, 6 tests).
- **(2026-04-15)** `T069` completed: added locale-format integration assertions in `ContractsIntegration.i18n.test.ts` ensuring both `ContractDetail.tsx` and `ReviewContractStep.tsx` avoid hardcoded `'en-US'`/`formatCurrencyFromMinorUnits(...)` and use `useFormatters().formatCurrency` via local minor-unit helpers.
- **(2026-04-15)** Verification: `cd packages/billing && npx vitest run tests/billing-dashboard/ContractsIntegration.i18n.test.ts` (pass; 1 file, 7 tests).