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

391 lines
73 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: Invoicing Sub-batch
- Plan slug: `2026-04-09-msp-i18n-invoicing`
- Created: `2026-04-09`
- Last synced to codebase: `2026-04-17`
## Status Recheck (2026-04-17)
**Still 0% implemented.** Verified against the current codebase:
- `server/public/locales/en/msp/invoicing.json`**does not exist**.
- All 22 components listed in the PRD still have `useTranslation=0`.
- `features.json` / `tests.json`: 0/37 features, 0/50 tests marked implemented.
### PRD file-path correction (important)
The PRD's "File Inventory" header says files live in `packages/billing/src/components/`, but
every component actually lives in one of three subdirectories. Update mental model to:
| Component | Actual path (relative to `packages/billing/src/components/`) |
|---|---|
| AutomaticInvoices.tsx | `billing-dashboard/AutomaticInvoices.tsx` |
| ManualInvoices.tsx | `billing-dashboard/ManualInvoices.tsx` |
| DraftsTab.tsx | `billing-dashboard/invoicing/DraftsTab.tsx` |
| FinalizedTab.tsx | `billing-dashboard/invoicing/FinalizedTab.tsx` |
| RecurringServicePeriodsTab.tsx | `billing-dashboard/RecurringServicePeriodsTab.tsx` |
| BillingCycles.tsx | `billing-dashboard/BillingCycles.tsx` |
| InvoicePreviewPanel.tsx | `billing-dashboard/invoicing/InvoicePreviewPanel.tsx` |
| InvoiceTemplateEditor.tsx | `billing-dashboard/InvoiceTemplateEditor.tsx` |
| InvoiceTemplates.tsx | `billing-dashboard/InvoiceTemplates.tsx` |
| ExternalTaxBatchImportDashboard.tsx | `invoices/ExternalTaxBatchImportDashboard.tsx` |
| ExternalTaxImportPanel.tsx | `invoices/ExternalTaxImportPanel.tsx` |
| SendInvoiceEmailDialog.tsx | `billing-dashboard/invoicing/SendInvoiceEmailDialog.tsx` |
| TaxReconciliationView.tsx | `invoices/TaxReconciliationView.tsx` |
| GenerateTab.tsx | `billing-dashboard/invoicing/GenerateTab.tsx` |
| PrepaymentInvoices.tsx | `billing-dashboard/PrepaymentInvoices.tsx` |
| ContractInvoiceItems.tsx | `billing-dashboard/invoices/ContractInvoiceItems.tsx` |
| InvoicingHub.tsx | `billing-dashboard/InvoicingHub.tsx` |
| InvoiceTemplateManager.tsx | `billing-dashboard/InvoiceTemplateManager.tsx` |
| InvoiceTaxSourceBadge.tsx | `invoices/InvoiceTaxSourceBadge.tsx` |
| InvoiceAnnotations.tsx | `billing-dashboard/InvoiceAnnotations.tsx` |
| PurchaseOrderSummaryBanner.tsx | `billing-dashboard/invoicing/PurchaseOrderSummaryBanner.tsx` |
| PaperInvoice.tsx (excluded) | `billing-dashboard/PaperInvoice.tsx` |
### Upstream changes since 2026-04-09 (affect this plan)
| Commit | What changed | Impact on this plan |
|---|---|---|
| `d3ad4fa4f feat(billing): allow editing draft invoice details` | DraftsTab.tsx gained inline draft-editing UI. File grew 550 → 558 LOC. | Add an extra feature to wire new edit-draft strings (field labels, save/cancel, validation) under `draftsTab.editDraft.*`. |
| `9dd19bf02 Fix draft invoice preview nullable due date typing` | Typing tweak in InvoicePreviewPanel. | No new strings. |
| `7cd6f79e2 fix: persist automatic invoice filter for ready and approval views` | AutomaticInvoices.tsx filter UI persistence; file grew 1983 → 2073 LOC (~+90 LOC). | String count may be slightly higher than the PRD's ~120 estimate. Audit filter-mode labels (ready / needs approval) when extracting. |
| `63353605a feat(F001-F018): enforce recurring approval blockers in due-work, UI, and generation` | AutomaticInvoices.tsx surfaces unapproved-time blocker strings. | Include blocker/alert strings in `automaticInvoices.blockers.*`. |
| `0825b1191 fix(accounting): move net_amount backfill migration to 2026-04-16`, `22924f65c fix(accounting): use charge.net_amount for Xero/QBO export LineAmount`, `8671fdcbd feat(accounting): nudge tenants to let the accounting system calculate tax`, `ef36541f7 fix(accounting): coerce bigint/numeric charge fields in export adapters`, `60be5c878 fix(accounting): honor invoiceIds filter on export batches`, `f849c9f8f fix(accounting): return 409 instead of 500 when retry matches zero invoices`, `50b4164ad fix(xero): make invoice re-export idempotent via InvoiceID + LineItemID threading`, `2a14053b8 fix(accounting): make external-mode tax writeback actually complete` | Back-end/adapter-layer accounting work. No UI strings added to the 22 in-scope components. | No plan changes. Noted to avoid merge conflicts when touching `ExternalTax*` / `TaxReconciliationView` files. |
| Contract-lines batch shipped 2026-04-14; adopted the **enum-labels pattern** (`useBillingFrequencyOptions` / `useFormatBillingFrequency` from `@alga-psa/billing/hooks/useBillingEnumOptions`, keys under `features/billing.json#enums.billingFrequency.*`). | `BillingCycles.tsx` renders a month-anchor select (PRD's "MONTH_OPTIONS" gotcha); `RecurringServicePeriodsTab.tsx` and `AutomaticInvoices.tsx` render billing-frequency badges. | **New guidance:** any billing-frequency label rendering (badges, select options, cell renderers) must use `useFormatBillingFrequency()` / `useBillingFrequencyOptions()` — do **not** re-translate those strings in `msp/invoicing.json`. Route must load `features/billing` (it already does for `/msp/billing`). Month-name labels in `BillingCycles.tsx` remain local to this batch (not shared). |
| `i18n/billing_contracts` merged (PR #2325) and `i18n/biling_ctd` merged (PR #2313) — contract-facing invoice wiring translated (`test(T008): cover contract detail invoice tab translation keys`, `feat(F015): localize contract detail quick actions dialogs and invoices`). | Those are `msp/contracts` surfaces, not the 22 in-scope invoicing components. | No overlap; ensure the "Invoices" tab inside contract detail keeps using `msp/contracts` keys, not `msp/invoicing`. |
### Scratchpad addendum
- Add an explicit feature for **DraftsTab edit-draft fields** (commit `d3ad4fa4f`).
- Add an explicit feature for **AutomaticInvoices persisted-filter labels** (commit `7cd6f79e2`) and **unapproved-time blocker alerts** (commit `63353605a`).
- Remove/avoid re-translating billing-frequency labels; route them through `useFormatBillingFrequency()`.
- Re-estimate AutomaticInvoices from ~120 to **~135** strings to account for the +90 LOC.
No structural plan overhaul; proceed with the corrected paths and the three extra sub-features above.
---
## What This Is
A green-field wiring pass: 22 invoicing components x `useTranslation('msp/invoicing')`.
Unlike the tickets migration (which reused an existing namespace), this batch creates a
brand new `msp/invoicing.json` namespace from scratch. Estimated ~500 translatable strings.
## Decisions
- **(2026-04-09)** New namespace `msp/invoicing` rather than adding to an existing file.
Invoicing is a distinct billing domain with no overlap with other translated surfaces.
The namespace sits under `msp/` alongside `msp/settings`, `msp/dashboard`, etc.
- **(2026-04-09)** Use `t('key', { defaultValue: 'English fallback' })` everywhere for
fallback safety, matching the pattern specified in the project i18n docs.
- **(2026-04-09)** PaperInvoice.tsx (44 LOC) is excluded -- pure layout wrapper with zero
user-visible strings. It renders children and sets CSS dimensions only.
- **(2026-04-09)** InvoiceTemplateManager.tsx (92 LOC) has only 3 heading strings. It is
primarily a sample invoice preview utility. Wire it for completeness.
- **(2026-04-09)** Ship as independent PRs per size tier: large (AutomaticInvoices +
ManualInvoices), medium (DraftsTab + FinalizedTab + RecurringServicePeriodsTab +
BillingCycles + InvoicePreviewPanel + template components + tax components +
SendInvoiceEmailDialog + GenerateTab), small (remaining 6 components), and a final
translations-only PR.
## Gotchas
### Currency formatting
Several components use hardcoded `new Intl.NumberFormat('en-US', ...)` or `formatCurrency`
from `@alga-psa/core`. These should be replaced with locale-aware formatting via
`useFormatters` from `@alga-psa/ui/lib/i18n/client`. Files affected:
- `DraftsTab.tsx` line 294-299 -- hardcoded `Intl.NumberFormat('en-US', ...)`
- `ContractInvoiceItems.tsx` -- hardcoded `$` prefix in template literals
- `ExternalTaxBatchImportDashboard.tsx` -- local `formatCurrency` with hardcoded `$`
- `ExternalTaxImportPanel.tsx` -- local `formatCurrency` with hardcoded `$`
- `TaxReconciliationView.tsx` -- local `formatCurrency` with hardcoded `$`
- `PurchaseOrderSummaryBanner.tsx` -- uses `formatCurrencyFromMinorUnits` with `'en-US'`
### Date formatting
`toPlainDate(value).toLocaleString()` calls in DraftsTab and FinalizedTab should receive
the current locale rather than defaulting to the browser locale. Use `useFormatters` or
pass locale explicitly.
### Duplicate adapter name maps
Three files define the same `ADAPTER_NAMES` map (`ExternalTaxBatchImportDashboard`,
`ExternalTaxImportPanel`, `InvoiceTaxSourceBadge`). Consider extracting to a shared
translated key group `externalTax.adapterNames.*` to avoid triple-maintenance.
### AutomaticInvoices.tsx is massive (1983 LOC)
This file has ~120 translatable strings spanning 5 distinct UI sections. Split into
4 features (F010-F014) for tractability. The inline helper functions
(`getParentGroupSummary`, `resolveIncompatibilityReasons`, `formatCadenceSourceBadge`,
`getRecurringAssignmentContext`) return English strings that must move to t() calls.
Some of these are called outside the component body, so they will need the `t` function
passed as a parameter or the strings must be moved inline.
### Helper functions returning hardcoded strings
Several module-level functions return English text:
- `getParentGroupSummary()` returns combinability labels
- `resolveIncompatibilityReasons()` returns reason strings
- `formatCadenceSourceBadge()` returns cadence source labels
- `summarizeCadenceSources()` joins labels
- `getRecurringAssignmentContext()` returns assignment context strings
These are defined outside the React component, so they cannot directly call `t()`.
Options: (1) move them inside the component, (2) return translation keys and call
`t()` at the render site, or (3) pass `t` as a parameter. Option (2) is cleanest
for this pattern -- return keys, translate at render.
### Interpolation needs
Several strings require `{{count}}` or `{{name}}` interpolation:
- "Actions (N)" -- bulk action button labels in DraftsTab, FinalizedTab
- "Generate Invoices for Selected Periods (N)" -- AutomaticInvoices
- "Reversing N draft invoices will delete them..." -- DraftsTab plural
- "N invoice(s) pending tax import" -- ExternalTaxBatchImportDashboard
- "N Invoice(s)" / "N ready to send" / "N missing email" -- SendInvoiceEmailDialog
- "Send N Email(s)" -- SendInvoiceEmailDialog
- "Sending N invoice(s)..." -- toast in SendInvoiceEmailDialog
- "Importing N/M..." -- ExternalTaxBatchImportDashboard progress
- "over by $X" -- PO overage dialogs
### Month names in BillingCycles
The `MONTH_OPTIONS` array has hardcoded January-December. These should be translated
via t() keys like `billingCycles.months.january` through `billingCycles.months.december`.
### RecipientSourceLabels in SendInvoiceEmailDialog
The `recipientSourceLabels` object maps enum values to display strings. These should
become `t('sendEmail.recipientSource.billingContact')` etc.
### TAX_SOURCE_CONFIG in InvoiceTaxSourceBadge
The config object has `label` and `tooltip` fields with English strings. These should
be translated at render time, not at definition time (move t() calls to render).
## Key Count Estimate
| Group | Estimated keys |
|-------|---------------|
| automaticInvoices | ~120 |
| manualInvoices | ~50 |
| draftsTab | ~30 |
| finalizedTab | ~30 |
| recurringServicePeriods | ~40 |
| billingCycles | ~25 |
| invoicePreview | ~20 |
| templateEditor | ~20 |
| templates | ~20 |
| externalTax | ~50 |
| sendEmail | ~25 |
| generateTab | ~15 |
| prepayment | ~15 |
| contractItems | ~10 |
| hub | ~5 |
| templateManager | ~5 |
| taxBadge | ~10 |
| annotations | ~5 |
| purchaseOrder | ~5 |
| common | ~15 |
| **Total** | **~515** |
## Progress Log
- **(2026-04-18) F001 complete:** created [server/public/locales/en/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/en/msp/invoicing.json) with the planned top-level namespace groups in PRD order and seeded English keys across all invoicing domains.
Rationale: unblock component wiring against a stable `msp/invoicing` namespace now, then expand/refine individual keys as each component lands instead of coupling every first component edit to file creation.
Commands: `node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync('server/public/locales/en/msp/invoicing.json','utf8')); console.log(Object.keys(data).join(','));"`
Gotcha: keeping the JSON top-level key order aligned with the PRD makes the eventual namespace-shape test straightforward and avoids churn when additional locale packs are generated.
- **(2026-04-18) F002 complete:** updated [packages/core/src/lib/i18n/config.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/core/src/lib/i18n/config.ts) so `ROUTE_NAMESPACES['/msp/billing']` preloads `msp/invoicing` alongside the existing billing/report/contract namespaces.
Rationale: the invoicing screens render under `/msp/billing` tabs, so namespace preloading must be in place before any `useTranslation('msp/invoicing')` call can resolve outside fallback/default strings.
- **(2026-04-18) F003 complete:** wired the `Ready to Invoice` chrome in [packages/billing/src/components/billing-dashboard/AutomaticInvoices.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/AutomaticInvoices.tsx) to `useTranslation('msp/invoicing')` for the section heading, explanatory copy, preview/generate actions, filter controls, and parent-group table headers.
Validation: added [packages/billing/tests/AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts) and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts` from `server/` (pass).
Gotcha: in this test/runtime fallback path, interpolated `defaultValue` strings are rendered literally, so count-bearing button copy needs a pre-expanded fallback string even when the translation key still receives `count` for real locale interpolation.
- **(2026-04-18) F004 complete:** converted AutomaticInvoices parent-group summary helpers from hardcoded English to translation-key metadata, then translated the rendered item/contract/line counts, combinability badges, and incompatibility-reason list through `msp/invoicing`.
Validation: expanded [packages/billing/tests/AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts) with the `T004` static contract and reran `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts` from `server/` (pass).
Decision: the helper layer now returns stable enum-like keys and CSS state only; actual user-facing copy is resolved at render time so later locale work can change strings without touching grouping logic.
- **(2026-04-18) F005 complete:** localized AutomaticInvoices child-row chrome for cadence, billing timing, service period, pending-amount fallback, assignment-context labels, unresolved-work marker, and attribution warnings; also added a targeted formatter for approval-blocker reasons with raw fallback for unknown blocker text.
Validation: extended [packages/billing/tests/AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts) with the `T005` static contract and reran `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts` from `server/` (pass).
Gotcha: cadence labels are shared between ready rows and recurring-history badges, so `formatCadenceSourceBadge()` now exposes a translation key alongside its English fallback instead of forcing the component to reverse-map labels later.
- **(2026-04-18) F006 complete:** localized AutomaticInvoices recurring-history action items plus the reverse/delete/preview/PO-overage dialog copy, including preview table headers/totals and the PO overage decision options.
Validation: extended [packages/billing/tests/AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts) with combined `T006/T007/T008` coverage and reran `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts` from `server/` (pass).
Decision: reverse/delete selection state now keeps raw cadence-source values instead of pretranslated English so every dialog render path can consistently reuse the same `formatCadenceSourceText()` translation bridge.
- **(2026-04-18) F007 complete:** localized AutomaticInvoices recurring-history chrome (title, filter, table headers, badges, row-menu sr-only text), wired the materialization-gap panel to `msp/invoicing`, and translated the ready-surface loading/error panel copy that sits on the same workflow surface. The recurring-history invoice-date cell now uses `useFormatters().formatDate(...)` instead of `toLocaleString()` so it follows the active locale.
Validation: reran `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts` from `server/` (pass). Also ran `npx tsc -p packages/billing/tsconfig.json --noEmit`; the only remaining failure is a pre-existing unrelated repo issue in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts) requiring a missing `pt` locale entry.
Commands: `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts`, `npx tsc -p packages/billing/tsconfig.json --noEmit`
Decision: the history panel now reuses the same cadence translation bridge as the ready table (`formatCadenceSourceText`) so contract-anniversary/client-schedule labels stay consistent across both AutomaticInvoices sub-surfaces.
- **(2026-04-18) Added F038/T051:** the original AutomaticInvoices split missed several user-visible strings outside F003-F007 (needs-approval panel, preview limitation note, expand/collapse aria labels, selection hints, metadata plural copy, unknown fallbacks, PO fallback labels).
Rationale: the PRD acceptance criterion is “every user-visible string” in the component. Tracking the remainder as a dedicated atomic follow-up keeps the running commits honest and avoids silently declaring AutomaticInvoices complete while leaving untranslated chrome behind.
- **(2026-04-18) F008 complete:** wired [packages/billing/src/components/billing-dashboard/ManualInvoices.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/ManualInvoices.tsx) to `useTranslation('msp/invoicing')` for the create/edit headings, explanatory copy, client and invoice-number labels, client-picker and invoice-number placeholders, automated-items table chrome, line-item section headings, and total label. This pass also swapped the automated-items table and total summary from `@alga-psa/core` `formatCurrency(..., 'en-US', ...)` to `useFormatters().formatCurrency(...)`.
Validation: added [packages/billing/tests/ManualInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ManualInvoices.i18n.test.ts) for `T011` static coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/ManualInvoices.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Gotcha: `ManualInvoices.tsx` has helper subcomponents outside the main form body, so localized table/header copy and locale-aware currency formatting needed to be wired in both `ManualInvoicesContent` and `AutomatedItemsTable` rather than only at the parent render site.
- **(2026-04-18) F009 complete:** localized the remaining ManualInvoices control/error surface: add-charge/add-discount buttons, submit/save/processing states, prepayment and credit-expiration copy, validation/backend-known error messages, unknown-service fallback text, and the `ErrorBoundary` fallback title/retry action.
Validation: expanded [packages/billing/tests/ManualInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ManualInvoices.i18n.test.ts) with static `T012/T013` coverage and reran `npx vitest run --config vitest.config.ts ../packages/billing/tests/ManualInvoices.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit`; the only remaining failure is still the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: known backend/manual-form errors now flow through a single `translateManualInvoiceError()` helper so both thrown exceptions and `success:false` action payloads resolve through the same translation keys instead of duplicating string-matching logic in multiple branches.
- **(2026-04-18) F010 complete:** wired [packages/billing/src/components/billing-dashboard/invoicing/DraftsTab.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/invoicing/DraftsTab.tsx) to `useTranslation('msp/invoicing')` across the drafts table columns, draft badge, search/bulk-action controls, row menu items, loading and empty states, reverse confirmation dialog, and the user-visible error messages. The tables amount/date cells now use `useFormatters()` instead of hardcoded `Intl.NumberFormat('en-US')` / `toLocaleString()`.
Validation: added [packages/billing/tests/DraftsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/DraftsTab.i18n.test.ts) for static `T014/T015` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/DraftsTab.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit`; the only remaining failure is still the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Gotcha: the locale file already used pluralized `bulkActions_*` and reverse-dialog message keys, so the new static contract test has to validate those plural leaves rather than a single flat `bulkActions`/`message` node even though the component calls `t('draftsTab.bulkActions', { count })` and `t('draftsTab.reverseDialog.message', { count })`.
- **(2026-04-18) F011 complete:** localized [packages/billing/src/components/billing-dashboard/invoicing/FinalizedTab.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/invoicing/FinalizedTab.tsx) for the finalized invoices table chrome, finalized badge, search/bulk controls, row actions (download/email/unfinalize), loading and empty states, and finalized-tab error messages. Amount/date cells now use `useFormatters()` instead of `formatCurrencyFromMinorUnits(..., 'en-US', ...)` / `toLocaleString()`.
Validation: added [packages/billing/tests/FinalizedTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/FinalizedTab.i18n.test.ts) for static `T016/T017` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/FinalizedTab.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit`; the only remaining failure is still the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F012 complete:** wired [packages/billing/src/components/billing-dashboard/RecurringServicePeriodsTab.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/RecurringServicePeriodsTab.tsx) to `useTranslation('msp/invoicing')` for the page heading/description, schedule selector and schedule-key entry controls, localized load/validation errors, the recurring-obligation summary labels, and the summary stat cards. The schedule option formatter now builds its labels from translated cadence/timing/unknown-client values instead of hardcoded English.
Validation: added [packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts) with static `T018` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: although `F012` only requires the shell/form layer, this pass also introduced key-based helpers for recurring-service-period lifecycle labels, provenance reasons, governance actions, and regeneration-conflict copy so the remaining table/panel work in `F013` can reuse the same translation bridge instead of rendering raw English from shared helpers.
- **(2026-04-18) F013 complete:** finished the [RecurringServicePeriodsTab.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/RecurringServicePeriodsTab.tsx) table/panel surface by localizing the table headers, repair-state panel, repair result summary, regeneration-preview panel, conflict count/empty state, and the table row metadata that previously leaked English from shared helper return values (lifecycle labels/details, provenance reasons, governance-action chips, conflict labels/reasons).
Validation: expanded [packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts) for static `T019/T020` coverage and reran `npx vitest run --config vitest.config.ts ../packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts` from `server/` (pass).
Gotcha: the shared recurring-service-period helpers expose translated English strings, not translation keys, so this component now maps lifecycle state / provenance reason / governance action / conflict kind back to stable `msp/invoicing` keys at render time instead of trusting the helper copy directly.
- **(2026-04-18) F014 complete:** wired [packages/billing/src/components/billing-dashboard/BillingCycles.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/BillingCycles.tsx) to `useTranslation('msp/invoicing')` for the page heading, tooltip/description, filter controls, table headers, loading and error states, and the “View Client Billing” action. The anchor summary formatter now translates month names plus `Weekday`, `Rolling`, `Starts`, and `Day` patterns, and the table body no longer leaks English for cycle labels, assignment-id prefixes, or `No active assignments` / `Not set` / `Unknown` fallbacks.
Validation: added [packages/billing/tests/BillingCycles.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/BillingCycles.i18n.test.ts) for static `T021/T022` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/BillingCycles.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F015 complete:** wired [packages/billing/src/components/billing-dashboard/invoicing/InvoicePreviewPanel.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/invoicing/InvoicePreviewPanel.tsx) to `useTranslation('msp/invoicing')` for the panel heading, template selector placeholder, empty/loading/error states, source-quote CTA, and all preview action buttons. This pass also localized the template “(Standard)” badge and the preview/action alert messages so translated button labels do not fall back to English inside error alerts.
Validation: added [packages/billing/tests/InvoicePreviewPanel.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicePreviewPanel.i18n.test.ts) for static `T023/T024` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoicePreviewPanel.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F016 complete:** localized [packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx) for the back navigation, create/edit headings, template-name and AST labels, visual/code tabs, read-only code alert, timestamp labels, save/cancel states, and the validation/load/save/AST-export error messages. The created/updated timestamps now use `useFormatters().formatDate(..., { dateStyle, timeStyle })` instead of raw `toLocaleString()`.
Validation: added [packages/billing/tests/InvoiceTemplateEditor.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplateEditor.i18n.test.ts) for static `T025/T026` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoiceTemplateEditor.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F017 complete:** rewired [packages/billing/src/components/billing-dashboard/InvoiceTemplates.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/InvoiceTemplates.tsx) to `useTranslation('msp/invoicing')` for the list title, table headers, type labels, action-menu items, sr-only menu label, create button, loading state, and clone/set-default/fetch errors. This pass also localized system-generated clone names (`(Copy)`, `Copy of {{name}}`), the standard-template suffix, the delete-dialog fallback entity name, and the client-side delete-validation fallback messages.
Validation: added [packages/billing/tests/InvoiceTemplates.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplates.i18n.test.ts) for static `T027/T028` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoiceTemplates.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F018 complete:** localized [packages/billing/src/components/invoices/ExternalTaxBatchImportDashboard.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/invoices/ExternalTaxBatchImportDashboard.tsx) for the batch-import card title/description, pending summary, table columns, import/refresh/import-all actions, progress/results states, empty state, help text, adapter names, and toast/error copy. This pass also replaced the components hardcoded `$...` and `toLocaleDateString()` helpers with `useFormatters().formatCurrency(..., 'USD')` and `useFormatters().formatDate(...)` so the rendered amounts/dates follow the active locale instead of English defaults.
Validation: added [packages/billing/tests/ExternalTaxBatchImportDashboard.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ExternalTaxBatchImportDashboard.i18n.test.ts) for static `T029/T030` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/ExternalTaxBatchImportDashboard.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: because the dashboard payload carries cents but no per-invoice currency code, the locale-aware formatter currently preserves existing semantics with `'USD'` rather than a hardcoded English string template. If later API work exposes row currency, this helper can switch without touching the translated UI chrome.
- **(2026-04-18) F019 complete:** localized [packages/billing/src/components/invoices/ExternalTaxImportPanel.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/invoices/ExternalTaxImportPanel.tsx) for the panel title, show/hide history toggle, pending/imported alert copy, adapter-specific import CTA, reconciliation labels, significant-difference warning, import history heading/states, tooltip text, help text, and import-result toast/error copy. This pass also replaced the components hardcoded currency/date helpers with `useFormatters().formatCurrency(..., 'USD')` and `useFormatters().formatDate(...)` for reconciliation totals and history timestamps.
Validation: added [packages/billing/tests/ExternalTaxImportPanel.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ExternalTaxImportPanel.i18n.test.ts) for static `T031/T032` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/ExternalTaxImportPanel.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: both external-tax components now share the same translated adapter-name mapping pattern (`quickbooks_online` -> `externalTax.adapterNames.quickbooks`, etc.) so QuickBooks/Xero/Sage labels stay consistent across the batch dashboard, invoice-level panel, and the later tax-badge/reconciliation work.
- **(2026-04-18) F020 complete:** localized [packages/billing/src/components/billing-dashboard/invoicing/SendInvoiceEmailDialog.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/invoicing/SendInvoiceEmailDialog.tsx) for the dialog title, loading state, invoice/recipient summary counts, recipient-source badges, missing-email fallback, due/additional-message labels, preview sentence, cancel/send/sending button states, and the load/send toast/error messages.
Validation: added [packages/billing/tests/SendInvoiceEmailDialog.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/SendInvoiceEmailDialog.i18n.test.ts) for static `T033/T034` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/SendInvoiceEmailDialog.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: the email-preview copy now resolves through a single interpolated `sendEmail.preview` key with translated default sender/company fallbacks, which keeps pseudo-locale coverage intact even when the backend returns no `fromEmail` or `companyName`.
- **(2026-04-18) F021 complete:** localized [packages/billing/src/components/invoices/TaxReconciliationView.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/invoices/TaxReconciliationView.tsx) for the reconciliation card title/description, status tooltips, internal/external summary labels, significant-difference warning, line-breakdown heading, table headers, line-number fallback, total row, loading/no-data states, and help text. This pass also replaced the components hardcoded currency formatting with `useFormatters().formatCurrency(..., 'USD')` and switched percentage text to locale-aware `formatNumber(...)`.
Validation: added [packages/billing/tests/TaxReconciliationView.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/TaxReconciliationView.i18n.test.ts) for static `T035/T036` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/TaxReconciliationView.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: reconciliation-specific copy now lives under `externalTax.reconciliationView.*` instead of overloading the simpler single-invoice import-panel keys. That keeps the invoice-panel labels short while giving the standalone reconciliation card its own line-breakdown/table vocabulary.
- **(2026-04-18) F022 complete:** localized [packages/billing/src/components/billing-dashboard/invoicing/GenerateTab.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/invoicing/GenerateTab.tsx) for the invoice-type label, automatic/manual/prepayment option labels, the three type descriptions, the load-data error, and the success-dialog message. The English source for `generateTab.descriptions.*` was updated to match the current component copy instead of the earlier scaffolded placeholder text.
Validation: added [packages/billing/tests/GenerateTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/GenerateTab.i18n.test.ts) for static `T037` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/GenerateTab.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F023 complete:** localized [packages/billing/src/components/billing-dashboard/PrepaymentInvoices.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/PrepaymentInvoices.tsx) for the heading/description variants, field labels, type options, amount/description placeholders, validation errors, and submit button states.
Validation: added [packages/billing/tests/PrepaymentInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/PrepaymentInvoices.i18n.test.ts) for static `T038` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/PrepaymentInvoices.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: the form now preserves the specific “credit memos are not yet supported” validation path instead of collapsing it into the generic “Error generating invoice” catch-all, which keeps the translated UX aligned with the actual blocked behavior.
- **(2026-04-18) F024 complete:** localized [packages/billing/src/components/billing-dashboard/invoices/ContractInvoiceItems.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/invoices/ContractInvoiceItems.tsx) for the shared table headers, product badge, contract/other-item subtotal labels, and the “Other Items” section heading. This pass also replaced the components hardcoded `$...` strings with `useFormatters().formatCurrency(..., 'USD')`.
Validation: added [packages/billing/tests/ContractInvoiceItems.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ContractInvoiceItems.i18n.test.ts) for static `T039` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/ContractInvoiceItems.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F025 complete:** localized [packages/billing/src/components/billing-dashboard/InvoicingHub.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/InvoicingHub.tsx) for the page heading and the Generate / Drafts / Finalized sub-tab labels.
Validation: added [packages/billing/tests/InvoicingHub.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicingHub.i18n.test.ts) for static `T040` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoicingHub.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
- **(2026-04-18) F026 complete:** localized [packages/billing/src/components/billing-dashboard/InvoiceTemplateManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/InvoiceTemplateManager.tsx) for the manager heading, sample-invoices heading, template-preview heading, and the sample invoice `Invoice #...` prefix using `useTranslation('msp/invoicing')`.
Validation: added [packages/billing/tests/InvoiceTemplateManager.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplateManager.i18n.test.ts) for static `T041` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoiceTemplateManager.i18n.test.ts` from `server/` (pass).
Gotcha: this component still carries legacy unused local template state from older editor wiring; the i18n pass left that behavior untouched and only translated the user-facing chrome.
- **(2026-04-18) F027 complete:** localized [packages/billing/src/components/invoices/InvoiceTaxSourceBadge.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/invoices/InvoiceTaxSourceBadge.tsx) for badge labels, static/default tooltips, adapter-name mappings, and the dynamic adapter/imported-at tooltip variants. The imported-at suffix now uses `useFormatters().formatDate(...)` instead of `toLocaleDateString()`.
Validation: added [packages/billing/tests/InvoiceTaxSourceBadge.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTaxSourceBadge.i18n.test.ts) for static `T042` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoiceTaxSourceBadge.i18n.test.ts` from `server/` (pass).
Decision: the badge config now stores stable translation-key metadata (`labelKey` / `tooltipKey`) instead of English copy so no user-facing string remains stranded in module scope outside hook access.
- **(2026-04-18) F028 complete:** localized [packages/billing/src/components/billing-dashboard/InvoiceAnnotations.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/InvoiceAnnotations.tsx) for the section heading, internal/external labels, textarea placeholder, and add button copy using `msp/invoicing`.
Validation: added [packages/billing/tests/InvoiceAnnotations.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceAnnotations.i18n.test.ts) for static `T043` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoiceAnnotations.i18n.test.ts` from `server/` (pass).
Gotcha: the component still hardcodes `current_user_id` for annotation creation, but that is existing non-i18n debt and remained out of scope for this sub-batch.
- **(2026-04-18) F029 complete:** localized [packages/billing/src/components/billing-dashboard/invoicing/PurchaseOrderSummaryBanner.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/invoicing/PurchaseOrderSummaryBanner.tsx) for the PO number/authorized/consumed/remaining labels and replaced the banners hardcoded `formatCurrencyFromMinorUnits(..., 'en-US', ...)` calls with `useFormatters().formatCurrency(...)`.
Validation: added [packages/billing/tests/PurchaseOrderSummaryBanner.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/PurchaseOrderSummaryBanner.i18n.test.ts) for static `T044` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/PurchaseOrderSummaryBanner.i18n.test.ts` from `server/` (pass).
Decision: the banner keeps its existing `currencyCode` prop and now formats cents-to-major-units inline before delegating to the locale-aware formatter, which avoids reintroducing an English locale argument through shared core helpers.
- **(2026-04-18) F038 complete:** finished the remaining [packages/billing/src/components/billing-dashboard/AutomaticInvoices.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/billing-dashboard/AutomaticInvoices.tsx) chrome that the original split missed: needs-approval section title/body/field labels/action, grouped-preview limitation note, expand/collapse aria labels, ready-table selection hints, parent-group attribution-metadata plural copy, unknown cadence/client fallbacks, and PO-overage fallback labels.
Validation: expanded [packages/billing/tests/AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts) with static `T051` coverage and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts` from `server/` (pass). Reran `npx tsc -p packages/billing/tsconfig.json --noEmit --pretty false`; the only failure remains the unrelated missing-`pt` locale mapping in [packages/ui/src/lib/dateFnsLocale.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/ui/src/lib/dateFnsLocale.ts).
Decision: unknown cadence handling now flows through key metadata returned by `formatCadenceSourceBadge()` so grouped summary chips, row badges, and delete/reverse dialogs all share the same translation path instead of leaking raw helper strings.
- **(2026-04-18) Added F039:** repo-wide `node scripts/validate-translations.cjs` checks every real locale present under [server/public/locales](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales), and this repo already ships a Portuguese (`pt`) locale pack.
Rationale: without `server/public/locales/pt/msp/invoicing.json`, translation validation would fail even if the originally planned six production locales and two pseudo-locales were complete. Track Portuguese parity explicitly rather than sneaking in an untracked file.
- **(2026-04-18) F030 complete:** generated [server/public/locales/fr/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/fr/msp/invoicing.json) for the full `msp/invoicing` namespace.
Validation: spot-checked the generated file with `jq '.automaticInvoices.ready.needsApproval, .sendEmail, .purchaseOrder.labels, .templateManager' server/public/locales/fr/msp/invoicing.json` and parsed it with `python3 - <<'PY' ... json.loads(...) ... PY` (pass).
Decision: locale generation now uses translation-memory reuse from existing aligned locale packs first, then fills only unmatched strings via chunked machine translation while preserving `{{variables}}` and `\n` placeholders verbatim.
- **(2026-04-18) F031 complete:** generated [server/public/locales/es/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/es/msp/invoicing.json) for the full `msp/invoicing` namespace.
Validation: spot-checked the generated file with `jq '.automaticInvoices.ready.needsApproval, .sendEmail.summary, .purchaseOrder.labels, .templateManager' server/public/locales/es/msp/invoicing.json` and parsed it with `python3 - <<'PY' ... json.loads(...) ... PY` (pass).
Gotcha: machine translation incorrectly rendered the short PO label once; normalized [server/public/locales/es/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/es/msp/invoicing.json) `purchaseOrder.labels.short` back to `PO` before committing so downstream overage copy keeps the standard abbreviation.
- **(2026-04-18) F032 complete:** generated [server/public/locales/de/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/de/msp/invoicing.json) for the full `msp/invoicing` namespace.
Validation: spot-checked the generated file with `jq '.automaticInvoices.ready.needsApproval, .sendEmail.summary, .purchaseOrder.labels, .templateManager' server/public/locales/de/msp/invoicing.json` and parsed it with `python3 - <<'PY' ... json.loads(...) ... PY` (pass).
Decision: after the Spanish `PO` miss, the generator was updated to keep the short PO abbreviation as a literal no-translate token for the remaining locale packs.
- **(2026-04-18) F033 complete:** generated [server/public/locales/nl/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/nl/msp/invoicing.json) for the full `msp/invoicing` namespace.
Validation: spot-checked the generated file with `jq '.automaticInvoices.ready.needsApproval, .sendEmail.summary, .purchaseOrder.labels, .templateManager' server/public/locales/nl/msp/invoicing.json` and parsed it with `python3 - <<'PY' ... json.loads(...) ... PY` (pass).
- **(2026-04-18) F034 complete:** generated [server/public/locales/it/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/it/msp/invoicing.json) for the full `msp/invoicing` namespace.
Validation: spot-checked the generated file with `jq '.automaticInvoices.ready.needsApproval, .sendEmail.summary, .purchaseOrder.labels, .templateManager' server/public/locales/it/msp/invoicing.json`, parsed it with `python3 - <<'PY' ... json.loads(...) ... PY`, and audited accent coverage with `python3 - <<'PY' ... print(sorted(set(ch for ch in text if ch in \"àèéìòù\"))) ... PY` (pass; file includes `àèéìòù`).
- **(2026-04-18) F039 complete:** generated [server/public/locales/pt/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/pt/msp/invoicing.json) so repo-wide locale parity validation can succeed against the already-shipped Portuguese locale pack.
Validation: spot-checked the generated file with `jq '.automaticInvoices.ready.needsApproval, .sendEmail.summary, .purchaseOrder.labels, .templateManager' server/public/locales/pt/msp/invoicing.json` and parsed it with `python3 - <<'PY' ... json.loads(...) ... PY` (pass).
- **(2026-04-18) F035 complete:** generated [server/public/locales/pl/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/pl/msp/invoicing.json) for the full `msp/invoicing` namespace.
Validation: spot-checked the generated file with `jq '.automaticInvoices.ready.needsApproval, .sendEmail.summary, .purchaseOrder.labels, .templateManager' server/public/locales/pl/msp/invoicing.json` and parsed it with `python3 - <<'PY' ... json.loads(...) ... PY` (pass).
- **(2026-04-18) F036 complete:** regenerated pseudo-locales with `node scripts/generate-pseudo-locales.cjs`, which updated [server/public/locales/xx/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/xx/msp/invoicing.json) and [server/public/locales/yy/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/yy/msp/invoicing.json) from the current English source.
Validation: spot-checked pseudo output with `jq '.automaticInvoices.ready.needsApproval, .templateManager, .purchaseOrder.labels' server/public/locales/{xx,yy}/msp/invoicing.json` and confirmed the fill markers plus preserved `{{count}}` / `{{number}}` placeholders are present.
- **(2026-04-18) F037 complete:** ran `node scripts/validate-translations.cjs` and cleared the only reported issue.
Validation: first pass failed on [server/public/locales/it/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/it/msp/invoicing.json) `billingCycles.values.monthDay`, where the translator had mangled the placeholder mask into `TOKEN {{month}} PHVAR1`; corrected it to `{{day}} {{month}}` and reran validation (pass, 0 errors / 0 warnings).
- **(2026-04-19) T001 complete:** reran `node scripts/validate-translations.cjs` after the real/pseudo locale generation work and confirmed full repo-wide parity passes for `de, es, fr, it, nl, pl, pt, xx, yy`.
Follow-up fix: while authoring locale smoke coverage, found `billingCycles.values.dash` had been machine-translated to `null`/`-` in several real locale files even though validator ignores value semantics; normalized that leaf back to the intended em dash (`—`) across `fr/es/de/nl/it/pl/pt`, then reran validation (pass).
- **(2026-04-19) T002 complete:** added [packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts) and ran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts` from `server/` (pass).
Coverage: the new `T002` assertion locks the English namespace top-level group order/shape to the PRD, and the same file also provides the representative locale smoke coverage needed for `T048-T050`.
- **(2026-04-19) T003 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices ready-to-invoice chrome; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T004 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices parent-group combinability coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T005 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices child execution-row coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T006 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices reverse-dialog coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T007 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices preview-dialog coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T008 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices PO-overage dialog coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T009 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices recurring-history coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T010 complete:** checklist closed against [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) for AutomaticInvoices materialization-gap coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T011 complete:** checklist closed against [ManualInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ManualInvoices.i18n.test.ts:1) for ManualInvoices form heading/field coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T012 complete:** checklist closed against [ManualInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ManualInvoices.i18n.test.ts:1) for ManualInvoices action/validation coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T013 complete:** checklist closed against [ManualInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ManualInvoices.i18n.test.ts:1) for ManualInvoices error-fallback coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T014 complete:** checklist closed against [DraftsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/DraftsTab.i18n.test.ts:1) for DraftsTab table/search coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T015 complete:** checklist closed against [DraftsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/DraftsTab.i18n.test.ts:1) for DraftsTab empty-state/dialog coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T016 complete:** checklist closed against [FinalizedTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/FinalizedTab.i18n.test.ts:1) for FinalizedTab table/search coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T017 complete:** checklist closed against [FinalizedTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/FinalizedTab.i18n.test.ts:1) for FinalizedTab empty-state/bulk-action coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T018 complete:** checklist closed against [RecurringServicePeriodsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts:1) for RecurringServicePeriodsTab page/form coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T019 complete:** checklist closed against [RecurringServicePeriodsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts:1) for RecurringServicePeriodsTab table/stat coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T020 complete:** checklist closed against [RecurringServicePeriodsTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts:1) for RecurringServicePeriodsTab repair/regeneration coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T021 complete:** checklist closed against [BillingCycles.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/BillingCycles.i18n.test.ts:1) for BillingCycles heading/column/action coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T022 complete:** checklist closed against [BillingCycles.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/BillingCycles.i18n.test.ts:1) for BillingCycles month/anchor fallback coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T023 complete:** checklist closed against [InvoicePreviewPanel.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicePreviewPanel.i18n.test.ts:1) for InvoicePreviewPanel heading/action coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T024 complete:** checklist closed against [InvoicePreviewPanel.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicePreviewPanel.i18n.test.ts:1) for InvoicePreviewPanel empty/loading/error coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T025 complete:** checklist closed against [InvoiceTemplateEditor.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplateEditor.i18n.test.ts:1) for InvoiceTemplateEditor heading/tab/action coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T026 complete:** checklist closed against [InvoiceTemplateEditor.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplateEditor.i18n.test.ts:1) for InvoiceTemplateEditor validation/timestamp coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T027 complete:** checklist closed against [InvoiceTemplates.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplates.i18n.test.ts:1) for InvoiceTemplates heading/table/create coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T028 complete:** checklist closed against [InvoiceTemplates.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplates.i18n.test.ts:1) for InvoiceTemplates action/error coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T029 complete:** checklist closed against [ExternalTaxBatchImportDashboard.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ExternalTaxBatchImportDashboard.i18n.test.ts:1) for ExternalTaxBatchImportDashboard card/table/import coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T030 complete:** checklist closed against [ExternalTaxBatchImportDashboard.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ExternalTaxBatchImportDashboard.i18n.test.ts:1) for ExternalTaxBatchImportDashboard progress/result coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T031 complete:** checklist closed against [ExternalTaxImportPanel.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ExternalTaxImportPanel.i18n.test.ts:1) for ExternalTaxImportPanel title/alert/reconciliation coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T032 complete:** checklist closed against [ExternalTaxImportPanel.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ExternalTaxImportPanel.i18n.test.ts:1) for ExternalTaxImportPanel history/warning/help coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T033 complete:** checklist closed against [SendInvoiceEmailDialog.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/SendInvoiceEmailDialog.i18n.test.ts:1) for SendInvoiceEmailDialog summary/button coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T034 complete:** checklist closed against [SendInvoiceEmailDialog.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/SendInvoiceEmailDialog.i18n.test.ts:1) for SendInvoiceEmailDialog recipient/preview coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T035 complete:** checklist closed against [TaxReconciliationView.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/TaxReconciliationView.i18n.test.ts:1) for TaxReconciliationView title/table coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T036 complete:** checklist closed against [TaxReconciliationView.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/TaxReconciliationView.i18n.test.ts:1) for TaxReconciliationView alert/state/help coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T037 complete:** checklist closed against [GenerateTab.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/GenerateTab.i18n.test.ts:1) for GenerateTab type/description coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T038 complete:** checklist closed against [PrepaymentInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/PrepaymentInvoices.i18n.test.ts:1) for PrepaymentInvoices form coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T039 complete:** checklist closed against [ContractInvoiceItems.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/ContractInvoiceItems.i18n.test.ts:1) for ContractInvoiceItems table/subtotal coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T040 complete:** checklist closed against [InvoicingHub.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicingHub.i18n.test.ts:1) for InvoicingHub tab coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T041 complete:** checklist closed against [InvoiceTemplateManager.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTemplateManager.i18n.test.ts:1) for InvoiceTemplateManager heading/prefix coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T042 complete:** checklist closed against [InvoiceTaxSourceBadge.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceTaxSourceBadge.i18n.test.ts:1) for InvoiceTaxSourceBadge badge/tooltip coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T043 complete:** checklist closed against [InvoiceAnnotations.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoiceAnnotations.i18n.test.ts:1) for InvoiceAnnotations surface coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T044 complete:** checklist closed against [PurchaseOrderSummaryBanner.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/PurchaseOrderSummaryBanner.i18n.test.ts:1) for PurchaseOrderSummaryBanner label/formatter coverage; coverage was added and validated during the paired feature work, so no new code changes were required in this close-out commit.
- **(2026-04-19) T045 complete:** reran `node scripts/validate-translations.cjs` from the repo root (pass, 0 errors / 0 warnings) and closed the Italian accent-preservation checklist item against the earlier [server/public/locales/it/msp/invoicing.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/it/msp/invoicing.json) accent audit (`àèéìòù` present).
- **(2026-04-19) T046 complete:** closed interpolation-variable preservation from the same fresh `node scripts/validate-translations.cjs` pass, which verified placeholder parity across `de, es, fr, it, nl, pl, pt, xx, yy` for the full `msp/invoicing` namespace.
- **(2026-04-19) T048 complete:** reran `npx vitest run --config vitest.config.ts ../packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts` from `server/` (pass) and closed the pseudo-locale invoicing-hub smoke check against the representative `xx` assertions for `hub`, `generateTab`, `draftsTab`, and `finalizedTab` chrome in [InvoicingLocaleSmoke.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts:1).
- **(2026-04-19) T049 complete:** closed the template pseudo-locale smoke check from the same fresh [InvoicingLocaleSmoke.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts:1) run, which asserts representative `xx` coverage for the template list, template editor, and template manager surfaces.
- **(2026-04-19) T050 complete:** closed the German billing-cycles smoke check from the same fresh [InvoicingLocaleSmoke.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts:1) run, which verifies translated `de` column headers, action text, month names, and anchor-label building blocks for `billingCycles`.
- **(2026-04-19) T047 complete:** reran the consolidated billing i18n regression suite from `server/` with `npx vitest run --config vitest.config.ts ../packages/billing/tests/AutomaticInvoices.i18n.test.ts ../packages/billing/tests/ManualInvoices.i18n.test.ts ../packages/billing/tests/DraftsTab.i18n.test.ts ../packages/billing/tests/FinalizedTab.i18n.test.ts ../packages/billing/tests/RecurringServicePeriodsTab.i18n.test.ts ../packages/billing/tests/BillingCycles.i18n.test.ts ../packages/billing/tests/InvoicePreviewPanel.i18n.test.ts ../packages/billing/tests/InvoiceTemplateEditor.i18n.test.ts ../packages/billing/tests/InvoiceTemplates.i18n.test.ts ../packages/billing/tests/ExternalTaxBatchImportDashboard.i18n.test.ts ../packages/billing/tests/ExternalTaxImportPanel.i18n.test.ts ../packages/billing/tests/SendInvoiceEmailDialog.i18n.test.ts ../packages/billing/tests/TaxReconciliationView.i18n.test.ts ../packages/billing/tests/GenerateTab.i18n.test.ts ../packages/billing/tests/PrepaymentInvoices.i18n.test.ts ../packages/billing/tests/ContractInvoiceItems.i18n.test.ts ../packages/billing/tests/InvoicingHub.i18n.test.ts ../packages/billing/tests/InvoiceTemplateManager.i18n.test.ts ../packages/billing/tests/InvoiceTaxSourceBadge.i18n.test.ts ../packages/billing/tests/InvoiceAnnotations.i18n.test.ts ../packages/billing/tests/PurchaseOrderSummaryBanner.i18n.test.ts ../packages/billing/tests/InvoicingLocaleSmoke.i18n.test.ts` (pass: 22 files, 45 tests).
- **(2026-04-19) T051 complete:** closed the remaining AutomaticInvoices approval/ready chrome checklist item from the same fresh regression run, which includes [AutomaticInvoices.i18n.test.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/tests/AutomaticInvoices.i18n.test.ts:1) passing all 7 assertions including the F038 remainder coverage for approval-panel copy, grouped-preview note, aria labels, selection hints, attribution metadata, and unknown fallbacks.