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

91 KiB
Raw Permalink Blame History

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 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 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 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 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 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 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 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).