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

8.1 KiB

PRD -- MSP i18n: Invoicing Sub-batch

  • Slug: 2026-04-09-msp-i18n-invoicing
  • Date: 2026-04-09
  • Status: Draft (ready to start — verified unchanged on 2026-04-17; see SCRATCHPAD "Status Recheck (2026-04-17)" for corrected file paths and upstream deltas)
  • Parent plan: /.ai/translation/MSP_i18n_plan.md

Summary

Extract all hardcoded English strings from 22 invoicing components in packages/billing/src/components/, create the msp/invoicing namespace, wire useTranslation('msp/invoicing'), and generate translations for 7 languages plus pseudo-locales. PaperInvoice.tsx (44 LOC) has zero user-facing strings and is excluded.

Problem

MSP billing pages are one of the highest-value surfaces in the application (invoicing, templates, tax management, recurring billing). All 22 invoicing components are hardcoded English -- zero currently use useTranslation. Non-English MSP users encounter a fully translated sidebar, dashboard, and settings chrome, but switch to raw English when they enter any invoicing workflow (drafts, finalized, automatic generation, manual creation, templates, tax reconciliation, etc.).

Goals

  1. Create server/public/locales/en/msp/invoicing.json with all keys extracted from 22 invoicing components
  2. Wire useTranslation('msp/invoicing') into every component with user-visible strings
  3. Use useFormatters from @alga-psa/ui/lib/i18n/client for currency and date formatting where hardcoded Intl.NumberFormat / toLocaleString is currently used
  4. Generate translations for 6 non-English locales (fr, es, de, nl, it, pl) + 2 pseudo-locales (xx, yy)
  5. Run node scripts/generate-pseudo-locales.cjs && node scripts/validate-translations.cjs green (exit 0) before shipping
  6. Measurable: invoicing coverage goes from 0% to 100% of production components wired

Non-goals

  • Translating template content (user-designed invoice layouts, template AST field names)
  • Translating invoice data (invoice numbers, client names, descriptions) -- those are tenant data, not UI chrome
  • Moving existing non-invoicing billing keys from other namespaces
  • Wiring EE-only invoicing components not exported through @alga-psa/billing/components
  • Changing layout or visual design of any component
  • Translating console.error / console.log / console.warn developer-only messages

File Inventory

Large (600+ LOC) -- 2-3 features each

Component LOC Est. strings Key content
AutomaticInvoices.tsx 1,983 ~120 Ready-to-invoice table, parent group labels, cadence badges, incompatibility reasons, materialization gap panel, recurring history table, reverse/delete dialogs, preview dialog, PO overage dialogs, error messages
ManualInvoices.tsx 859 ~50 Form labels, automated items table, line item headers, prepayment checkbox, error messages, validation, submit button states

Medium (200-600 LOC) -- 1-2 features each

Component LOC Est. strings Key content
DraftsTab.tsx 550 ~30 Table column headers, search placeholder, bulk actions, empty state, reverse confirmation dialog
FinalizedTab.tsx 506 ~30 Table column headers, search placeholder, bulk actions (download/email/unfinalize), empty state
RecurringServicePeriodsTab.tsx 458 ~40 Page title, schedule selector, form labels, summary stats, table headers, repair panel, regeneration preview
BillingCycles.tsx 397 ~25 Page title, tooltip, column headers, anchor labels, month names, search, loading text
InvoicePreviewPanel.tsx 386 ~20 Preview title, template selector, action buttons, loading/error/empty states
InvoiceTemplateEditor.tsx 345 ~20 Back nav, heading, template name label, visual/code tabs, save/cancel buttons, timestamps, validation errors
InvoiceTemplates.tsx 344 ~20 Section heading, column headers, action menu items (edit/clone/set default/delete), create button, loading text
ExternalTaxBatchImportDashboard.tsx 320 ~25 Card title/description, column headers, batch import button, progress bar labels, results summary, help text, empty state
ExternalTaxImportPanel.tsx 297 ~25 Panel title, pending/imported alerts, import button, history section, reconciliation labels, help text
SendInvoiceEmailDialog.tsx 278 ~25 Dialog title, summary counts, recipients heading, recipient source labels, custom message label, email preview, send/cancel buttons
TaxReconciliationView.tsx 222 ~20 Card title, comparison labels (Internal/External), table headers, warning alert, help text
GenerateTab.tsx 207 ~15 Invoice type selector labels, type descriptions, success dialog message

Small (< 200 LOC) -- 1 feature each

Component LOC Est. strings Key content
PrepaymentInvoices.tsx 165 ~15 Form heading, field labels, type options, placeholders, validation errors, submit button states
ContractInvoiceItems.tsx 133 ~10 Table headers (Description/Quantity/Rate/Amount), subtotal labels, product badge
InvoicingHub.tsx 94 ~5 Section heading, tab labels (Generate/Drafts/Finalized)
InvoiceTemplateManager.tsx 92 ~5 Headings (Invoice Template Manager, Sample Invoices, Template Preview)
InvoiceTaxSourceBadge.tsx 81 ~10 Badge labels (Tax: Internal/External/Pending), tooltip strings, adapter names
InvoiceAnnotations.tsx 60 ~5 Heading, internal/external labels, placeholder, add button
PurchaseOrderSummaryBanner.tsx 45 ~5 Field labels (PO Number, PO Authorized, PO Consumed, PO Remaining)

Excluded (zero user-facing strings)

Component LOC Reason
PaperInvoice.tsx 44 Pure layout wrapper, no text content

Namespace Structure

msp/invoicing.json
  automaticInvoices.*       -- Ready-to-invoice, parent groups, history, dialogs
  manualInvoices.*          -- Manual invoice form, line items, prepayment
  draftsTab.*               -- Drafts list, bulk actions, reverse dialog
  finalizedTab.*            -- Finalized list, bulk actions
  recurringServicePeriods.* -- Schedule management, repair, regeneration
  billingCycles.*           -- Billing cycle table, anchor labels
  invoicePreview.*          -- Preview panel, action buttons
  templateEditor.*          -- Template editor form, tabs
  templates.*               -- Template list, actions
  externalTax.*             -- Batch import, single import, reconciliation
  sendEmail.*               -- Email dialog, recipient info
  generateTab.*             -- Type selector, descriptions
  prepayment.*              -- Prepayment form
  contractItems.*           -- Contract invoice items table
  hub.*                     -- Invoicing hub, tab labels
  templateManager.*         -- Template manager, sample invoices
  taxBadge.*                -- Tax source badge labels, tooltips
  annotations.*             -- Annotations section
  purchaseOrder.*           -- PO summary banner
  common.*                  -- Shared strings (Search, Cancel, Actions, Loading, etc.)

Acceptance Criteria

  • All 22 components with user-visible strings import useTranslation('msp/invoicing') and wrap every user-visible string with t('key', { defaultValue: '...' })
  • server/public/locales/en/msp/invoicing.json contains all keys referenced by components
  • Currency formatting uses useFormatters or locale-aware Intl.NumberFormat instead of hardcoded 'en-US' locale
  • ROUTE_NAMESPACES for /msp/billing loads the msp/invoicing namespace
  • node scripts/generate-pseudo-locales.cjs && node scripts/validate-translations.cjs exits 0 (key parity across 9 locales, pseudo-locale fill patterns, Italian accent preservation, {{variable}} interpolation preservation)
  • All existing billing-related unit/integration tests pass
  • Visual smoke test: /msp/billing?tab=invoicing (all sub-tabs), /msp/billing?tab=billing-cycles, /msp/billing?tab=service-periods, /msp/billing?tab=templates render correctly in en and at least one non-English locale; xx pseudo-locale shows pseudo-text for every visible string