Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
8.5 KiB
PRD — MSP i18n: Billing Dashboard Sub-batch
- Slug:
2026-04-09-msp-i18n-billing-dashboard - Date:
2026-04-09 - Status: Draft
- Parent plan:
/.ai/translation/MSP_i18n_plan.md
Summary
Extract hardcoded English strings from 17 top-level billing dashboard components, create a
new msp/billing namespace, wire useTranslation('msp/billing'), generate translations for
7 languages + 2 pseudo-locales, and update ROUTE_NAMESPACES to load the new namespace on
the /msp/billing route.
These 17 files are the billing dashboard "shell" components that do not belong to the contracts,
quotes, invoicing, credits, or service-catalog sub-batches. None of them currently use
useTranslation.
Problem
MSP users navigating to /msp/billing see a fully translated sidebar and navigation chrome
but hit an English-only billing dashboard. The 17 components in this batch collectively render
~350-450 hardcoded English strings including page titles, tab labels, column headers, button
labels, toast messages, form labels, validation messages, dialog titles, status badges, and
empty states. Non-English MSP users experience a jarring language switch when entering the
billing area.
Goals
- Create
server/public/locales/en/msp/billing.jsonwith all keys needed by these 17 components - Wire
useTranslation('msp/billing')into all 17 components - Generate translations for 6 non-English locales (fr, es, de, nl, it, pl) + 2 pseudo-locales (xx, yy)
- Update
ROUTE_NAMESPACES['/msp/billing']to includemsp/billing - Measurable: 0 of 17 components wired -> 17 of 17 wired
Non-goals
- Translating components in sub-directories that belong to other sub-batches:
contracts/,quotes/,contract-lines/,reports/, invoice-related components (InvoiceTemplates, InvoiceTemplateEditor, InvoicingHub, BillingCycles, RecurringServicePeriodsTab, TaxRates), or settings components (ServiceCatalogManager, ProductsManager) - Translating template engine output (TemplateRendererCore renders invoice HTML, not UI chrome)
- Translating tenant data (invoice content, service names, client names)
- Splitting
msp/billinginto micro-namespaces per component - Changing
features/billingnamespace (used by client-portal billing)
File Inventory
| # | Component | LOC | Size | Est. Strings | Key Content |
|---|---|---|---|---|---|
| 1 | ReconciliationResolution.tsx | 1129 | XL | ~80 | Stepper labels, resolution options (recommended/custom/no-action), four-eyes approval flow, verification code UI, balance comparison labels, correction summary, confirmation dialog, toast/error messages |
| 2 | DiscrepancyDetail.tsx | 921 | L | ~70 | Back nav, status badges (Open/In Review/Resolved), balance comparison, transaction history table headers, credit tracking table headers, issue detail alerts, resolution dialog, recommended fix labels |
| 3 | UsageTracking.tsx | 685 | L | ~45 | Bucket hours overview, usage records table headers (Client/Service/Quantity/Usage Date/Contract Line/Actions), add/edit/delete usage dialogs, filter labels, toast messages, contract line selector guidance |
| 4 | LineItem.tsx | 514 | M | ~40 | Line item labels (Service/Quantity/Rate/Description), discount fields (type/amount/percentage), apply-to selector, taxable/non-taxable badges, subtotal, collapsed summary text |
| 5 | FixedContractLineServicesList.tsx | 500 | M | ~35 | Table headers (Service Name/Category/Billing Method/Quantity/Default Rate/Actions), billing method options, add services section, product/service badges, dropdown actions (Edit Quantity/Remove) |
| 6 | AccountingExportsTab.tsx | 458 | M | ~40 | Accounting Exports title/description, batch table headers (Batch/Adapter/Status/Created/Updated/Actions), new export dialog (Adapter/Start Date/End Date/Client Search/Invoice Statuses/Notes), batch detail dialog, status labels, action buttons |
| 7 | FixedContractLinePresetServicesList.tsx | 446 | M | ~35 | Same column structure as FixedContractLineServicesList, unsaved changes warning, save/reset buttons, navigation warning dialog, add services section, billing method labels |
| 8 | RecommendedFixPanel.tsx | 429 | M | ~40 | Recommended/Alternative/No-Action fix panels, fix dialog titles and descriptions per fix type, impact summary, notes field, custom adjustment amount, cancel/apply buttons |
| 9 | TemplateRendererCore.ts | 415 | M | ~3 | Template engine logic; few user-visible strings ("N/A", "Unknown value", "No data for list"). Most output is invoice content, not UI chrome. |
| 10 | Overview.tsx | 297 | M | ~35 | Metric card titles (Active Contract Lines/Billing Clients/Monthly Revenue/Active Services/Outstanding Amount/Credit Balance/Pending Approvals), feature card titles and descriptions, Monthly Activity, Service Catalog Management, beta warning |
| 11 | BillingDashboard.tsx | 246 | M | ~5 | Page title "Billing", beta warning banner, back-to-presets nav, quote templates heading |
| 12 | EditContractLineServiceQuantityDialog.tsx | 175 | S | ~10 | Dialog title, quantity label, validation messages (empty, not positive), save/cancel buttons, saving indicator |
| 13 | billingTabsConfig.ts | 136 | S | ~16 | Tab labels: Quotes, Quote Layouts, Quote Templates, Client Contracts, Accounting Exports, Contract Templates, Invoicing, Invoice Layouts, Tax Rates, Contract Line Presets, Billing Cycles, Service Periods, Usage Tracking, Reports, Service Catalog, Products |
| 14 | TemplateRenderer.tsx | 131 | S | ~4 | Loading text, error display, empty state message |
| 15 | PropertyEditor.tsx | 85 | S | ~7 | Field labels (Content/Data Field/Width/Height/Font Size/Color), "Select a field" placeholder |
| 16 | ConditionalRuleManager.tsx | 77 | S | ~6 | "Conditional Display Rules" heading, action options (Show/Hide/Format), input placeholders (Condition/Target), "Add Rule" button |
| 17 | ContractsHub.tsx | 77 | S | ~4 | "Contracts" heading, tab labels (Templates/Client Contracts) |
Total estimated strings: ~475
Namespace Structure
Namespace: msp/billing
File: server/public/locales/{lng}/msp/billing.json
Key groups (preliminary):
dashboard.*-- page title, beta warning, tab labelsoverview.*-- metric titles, feature cards, monthly activity, service catalog sectionreconciliation.*-- stepper, resolution options, balance comparison, four-eyes approvaldiscrepancy.*-- status badges, transaction/credit tracking tables, issue detailrecommendedFix.*-- fix panels, dialog titles/descriptions, impact summaryusage.*-- bucket overview, usage records table, add/edit/delete forms, filterslineItem.*-- service/discount fields, taxable badges, subtotalcontractLineServices.*-- service list table, add services, billing methods, actionspresetServices.*-- preset service list, unsaved changes, save/resetaccountingExports.*-- batch table, new export dialog, batch detail dialogtemplateRenderer.*-- loading, error, empty statestemplateDesigner.*-- property editor labels, conditional rulescontractsHub.*-- heading, sub-tabseditQuantityDialog.*-- dialog title, validation, buttonscommon.*-- shared labels (Cancel, Save, Delete, Error, etc.) -- reusecommonnamespace where possible
ROUTE_NAMESPACES Update
Update packages/core/src/lib/i18n/config.ts:
'/msp/billing': ['common', 'msp/core', 'features/billing', 'msp/reports', 'msp/billing'],
This adds msp/billing to the existing route entry. Future billing sub-batches may add
additional namespaces (e.g., msp/billing-contracts, msp/billing-invoicing).
Acceptance Criteria
server/public/locales/en/msp/billing.jsonexists with all keys referenced by the 17 components- All 17 components import
useTranslation('msp/billing')and wrap all user-visible strings witht('key', { defaultValue: 'English fallback' }) TemplateRendererCore.tshas its 2-3 user-visible strings translated (or documented as N/A if they only appear in generated HTML)billingTabsConfig.tstab labels are translatable (either viat()calls in the config or in the consuming component that reads tab definitions)ROUTE_NAMESPACES['/msp/billing']includesmsp/billing- Translations exist for all 9 locales (en, fr, es, de, nl, it, pl, xx, yy)
node scripts/generate-pseudo-locales.cjs && node scripts/validate-translations.cjsexits 0- All existing billing-related tests pass
- Visual smoke test:
/msp/billingrenders correctly inenand at least one non-English locale;xxpseudo-locale shows pseudo-text for every visible string