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
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
461 lines
36 KiB
Markdown
461 lines
36 KiB
Markdown
# SCRATCHPAD — MSP i18n: Billing & Tax Settings
|
|
|
|
## Key Decisions
|
|
|
|
### New namespace, not reusing existing
|
|
Unlike the tickets migration (which wired into existing `features/tickets.json`), this
|
|
batch creates `msp/billing-settings.json` from scratch. The billing settings surface has
|
|
no client-portal counterpart, so there is no shared namespace to reuse.
|
|
|
|
### TaxSettingsForm included in this batch
|
|
`TaxSettingsForm.tsx` lives at `packages/billing/src/components/tax/` (outside the
|
|
`settings/` directory) but is functionally part of the billing/tax settings surface.
|
|
Including it here avoids a standalone sub-batch for a single component. If the namespace
|
|
exceeds ~500 keys, consider splitting `clientTaxSettings.*` into a separate namespace.
|
|
|
|
### Select option translation strategy
|
|
Constants like `POLICY_OPTIONS`, `LICENSE_TERM_OPTIONS`, `BILLING_METHOD_OPTIONS` are
|
|
currently defined outside components. To support locale-reactive labels, wrap them in
|
|
`useMemo` inside the component with `t()` calls, or move the constant inside the
|
|
component body. Do NOT try to call `t()` at module scope -- it will not have access to
|
|
the i18n context.
|
|
|
|
### F001 English namespace shape
|
|
`server/public/locales/en/msp/billing-settings.json` now exists and intentionally mixes
|
|
component-specific groups (`serviceCatalog.*`, `clientTaxSettings.*`, `tax.thresholds.*`)
|
|
with a small shared `common.*` / `import.*` layer. The file is broad rather than minimal:
|
|
it includes strings for all 17 target components up front so later wiring PRs can mostly
|
|
reuse existing keys instead of constantly expanding the namespace.
|
|
|
|
### Zod schema messages stay English
|
|
Zod validation `.message()` strings in `TaxRegionsManager`, `TaxThresholdEditor`,
|
|
`TaxComponentEditor`, and `TaxHolidayManager` are NOT translated. They are developer-
|
|
facing validation constraints. The rendered `<p>` error messages that display these to
|
|
users already get their text from `form.formState.errors.fieldName?.message` -- if we
|
|
want to translate those, we would need `t()` in the `<p>` tag wrapping the Zod message,
|
|
or switch to custom validation. For now, leave Zod messages as English and translate
|
|
only the surrounding UI chrome. This matches the pattern used elsewhere in the codebase.
|
|
|
|
### handleError second-argument strings
|
|
`handleError(error, 'Failed to load settings')` displays the second argument as a toast
|
|
fallback. These ARE user-visible and should be translated:
|
|
`handleError(error, t('errors.failedToLoadSettings', { defaultValue: 'Failed to load settings' }))`.
|
|
|
|
### PaymentSettingsConfig excluded
|
|
The `PaymentSettingsConfig` component is dynamically imported via `@product/billing/entry`
|
|
and resolves to either EE or OSS version at build time. It is outside this batch's scope
|
|
and should be handled in an EE-specific i18n pass.
|
|
|
|
### NumberingSettings excluded
|
|
`NumberingSettings` from `@alga-psa/reference-data/components` is rendered inside
|
|
`BillingSettings.tsx` but belongs to the `reference-data` package. Its strings should be
|
|
translated in a separate sub-batch covering the `reference-data` package namespace.
|
|
|
|
## Gotchas
|
|
|
|
1. **ServiceCatalogManager is 996 lines** -- the edit dialog alone has ~30 field labels.
|
|
Break the wiring into two features (F040 table chrome + F041 edit dialog) to keep
|
|
PRs reviewable.
|
|
|
|
2. **Duplicate BILLING_METHOD_OPTIONS** -- defined separately in `ServiceCatalogManager`,
|
|
`QuickAddService`, and `QuickAddProduct`. The i18n keys should be consistent across
|
|
all three. Use the same keys from the namespace (e.g., `common.billingMethod.fixed`,
|
|
`common.billingMethod.hourly`, `common.billingMethod.usage`).
|
|
|
|
3. **Dynamic placeholders in RenewalAutomationSettings** -- placeholder text changes
|
|
based on loading state (`'Loading boards...'` vs `'Select board'` vs
|
|
`'Select a board first'`). Each variant needs its own key.
|
|
|
|
4. **Interpolated confirmation messages** -- Several components use template literals
|
|
in confirmation dialogs: `` `Are you sure you want to delete "${name}"?` ``.
|
|
Convert to `t('confirmDelete', { name, defaultValue: '...' })`.
|
|
|
|
5. **ProductsManager archive vs delete** -- Two separate confirmation flows with
|
|
different messages. The permanent delete dialog has three states (checking, can-delete,
|
|
cannot-delete) each needing separate translated strings.
|
|
|
|
6. **TaxThresholdEditor bracket issue messages** -- These are dynamically constructed
|
|
strings with currency formatting. Use interpolation:
|
|
`t('tax.thresholds.issueGap', { from: formatted1, to: formatted2 })`.
|
|
|
|
7. **TaxHolidayManager heading interpolation** -- The heading conditionally includes
|
|
the tax rate name: `Tax Holidays for ${taxRateName}`. Use:
|
|
`t('tax.holidays.titleWithName', { name: taxRateName })` and
|
|
`t('tax.holidays.title')` for the without-name case.
|
|
|
|
8. **TaxSettingsForm has inline components (ErrorMessage, SuccessMessage)** -- These
|
|
are defined inside the component function. The `t()` hook is accessible in the parent
|
|
scope and can be used inside these inline components without issues.
|
|
|
|
9. **English source already carries some cleanup opportunities** -- current components use
|
|
inconsistent variants like `Loading…` vs `Loading...`, `Usage` vs `Usage Based`, and
|
|
`-` vs `—`. Keep the namespace expressive enough to cover the current UI first; defer
|
|
normalization until the component wiring passes so behavior stays reviewable.
|
|
|
|
## Estimated String Counts by Group
|
|
|
|
| Group | Est. Keys |
|
|
|-------|-----------|
|
|
| tabs | 4 |
|
|
| general (currency, invoiceNumbering, zeroDollar, creditExpiration, renewal) | 55 |
|
|
| quoting | 5 |
|
|
| tax (source, regions, thresholds, components, holidays) | 130 |
|
|
| payments | 5 |
|
|
| serviceCategories | 35 |
|
|
| serviceTypes | 45 |
|
|
| serviceCatalog | 50 |
|
|
| products | 35 |
|
|
| quickAddService | 40 |
|
|
| quickAddProduct | 40 |
|
|
| clientTaxSettings | 35 |
|
|
| common (shared Edit/Delete/Cancel/Save/Actions/etc.) | 15 |
|
|
| import (shared import dialog strings) | 15 |
|
|
| validation/errors/toast (shared patterns) | 20 |
|
|
| **Total** | **~530** |
|
|
|
|
## PR Grouping Suggestion
|
|
|
|
- **PR 1:** F001 (namespace JSON) + F002 (ROUTE_NAMESPACES) + F010-F014 (BillingSettings + small General-tab components) -- ~5 files, ~75 keys
|
|
- **PR 2:** F020-F021 + F030-F031 (ServiceCategoriesSettings + ServiceTypeSettings) -- ~2 files, ~80 keys
|
|
- **PR 3:** F040-F041 + F050-F051 + F060-F062 (ServiceCatalog + Products + QuickAdd dialogs) -- ~4 files, ~165 keys
|
|
- **PR 4:** F070-F085 + F090-F092 (All tax components + TaxSettingsForm) -- ~6 files, ~210 keys
|
|
- **PR 5:** F100-F107 (Translations for 6 languages + pseudo-locales + validation) -- namespace only, no component changes
|
|
|
|
## Work Log
|
|
|
|
### 2026-04-10
|
|
- Completed `F001` by adding [billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/en/msp/billing-settings.json).
|
|
- The English source includes the planned top-level groups: `tabs`, `general`, `quoting`,
|
|
`tax`, `payments`, `serviceCategories`, `serviceTypes`, `serviceCatalog`, `products`,
|
|
`quickAddService`, `quickAddProduct`, `clientTaxSettings`, `common`, `import`,
|
|
`validation`, `errors`, and `toast`.
|
|
- Source inventories came from direct component reads plus parallel component-specific
|
|
inventories for general billing, service categories/types, service catalog/products,
|
|
and tax/client-tax surfaces.
|
|
- Validation run:
|
|
`node -e "JSON.parse(require('fs').readFileSync('server/public/locales/en/msp/billing-settings.json','utf8')); console.log('ok')"`
|
|
- Completed `F002` by adding `'msp/billing-settings'` to the `/msp/settings` entry in
|
|
[config.ts](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/core/src/lib/i18n/config.ts).
|
|
- Verification run:
|
|
`rg -n "'/msp/settings'|msp/billing-settings" packages/core/src/lib/i18n/config.ts`
|
|
- Completed `F003` in
|
|
[BillingSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/BillingSettings.tsx).
|
|
- `BillingSettings.tsx` now imports `useTranslation('msp/billing-settings')`, translates the
|
|
four tab labels, all section card titles/descriptions, and the payment skeleton loading
|
|
text. Tab `id` values remain `general`, `quoting`, `tax`, and `payments`.
|
|
- Verification runs:
|
|
`rg -n "General'|Quoting'|Tax'|Payments'|Default Currency|Invoice Numbering|Zero-Dollar Invoices|Credit Expiration|Renewal Automation|Quote Numbering|Tax Regions|Payment Settings|Loading payment settings" packages/billing/src/components/settings/billing/BillingSettings.tsx`
|
|
- Completed `F004` in
|
|
[DefaultCurrencySettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/DefaultCurrencySettings.tsx).
|
|
- Wired the select label, placeholder, success toast, and `handleError` fallback strings to
|
|
`general.currency.*`.
|
|
- Verification runs:
|
|
`sed -n '1,200p' packages/billing/src/components/settings/billing/DefaultCurrencySettings.tsx`
|
|
- Completed `F005` in
|
|
[ZeroDollarInvoiceSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ZeroDollarInvoiceSettings.tsx).
|
|
- Wired the handling options, select label/placeholder, suppress toggle copy, success toast,
|
|
and save/load fallback errors to `general.zeroDollar.*`.
|
|
- Verification runs:
|
|
`sed -n '1,220p' packages/billing/src/components/settings/billing/ZeroDollarInvoiceSettings.tsx`
|
|
- Completed `F006` in
|
|
[CreditExpirationSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/CreditExpirationSettings.tsx).
|
|
- Wired the enable toggle, expiration/notification field copy, save button, success toast,
|
|
and save/load fallback errors to `general.creditExpiration.*`.
|
|
- Verification runs:
|
|
`sed -n '1,240p' packages/billing/src/components/settings/billing/CreditExpirationSettings.tsx`
|
|
- Completed `F007` in
|
|
[RenewalAutomationSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/RenewalAutomationSettings.tsx).
|
|
- Moved the due-date action policy options into `React.useMemo(..., [t])` inside the
|
|
component so the option labels translate at render time and react to locale changes.
|
|
- Wired the due-date action label/help, board and status labels, all loading/select
|
|
placeholders, board fallback label, save/saving button, success toast, and error
|
|
fallbacks to `general.renewal.*`.
|
|
- Verification runs:
|
|
`sed -n '1,280p' packages/billing/src/components/settings/billing/RenewalAutomationSettings.tsx`
|
|
- Completed `F008` in
|
|
[ServiceCategoriesSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ServiceCategoriesSettings.tsx).
|
|
- Scoped this pass to the outer chrome only: page heading, table column titles, row action
|
|
menu labels, and Add/Import buttons. Dialog bodies, validation, toasts, and import-flow
|
|
copy are intentionally left for `F009`.
|
|
- Verification runs:
|
|
`sed -n '1,260p' packages/billing/src/components/settings/billing/ServiceCategoriesSettings.tsx`
|
|
- Completed `F009` in
|
|
[ServiceCategoriesSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ServiceCategoriesSettings.tsx).
|
|
- Wired the delete confirmation dialog, add/edit dialog copy, validation/error messages,
|
|
create/update/delete/import toasts, import dialog copy, and conflict-resolution strings
|
|
to `serviceCategories.*`, `common.*`, and `import.*`.
|
|
- Verification runs:
|
|
`sed -n '60,560p' packages/billing/src/components/settings/billing/ServiceCategoriesSettings.tsx`
|
|
- Completed `F010` in
|
|
[ServiceTypeSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ServiceTypeSettings.tsx).
|
|
- Scoped this pass to the loading state, card title/description, table column headers,
|
|
billing method display labels, row action menu labels, and Add/Import buttons.
|
|
Dialog, validation, delete-confirmation, and import-conflict strings are left for `F011`.
|
|
- Verification runs:
|
|
`sed -n '286,322p' packages/billing/src/components/settings/billing/ServiceTypeSettings.tsx`
|
|
- Completed `F011` in
|
|
[ServiceTypeSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ServiceTypeSettings.tsx).
|
|
- Wired the add/edit dialog copy, required-field summary, delete confirmation with in-use
|
|
error state, import dialog copy, conflict-resolution strings, and import/save/delete
|
|
fallback messaging to `serviceTypes.*`, `common.*`, and `import.*`.
|
|
- Verification runs:
|
|
`sed -n '1,760p' packages/billing/src/components/settings/billing/ServiceTypeSettings.tsx`
|
|
- Completed `F012` in
|
|
[ServiceCatalogManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ServiceCatalogManager.tsx).
|
|
- Scoped this pass to the outer service catalog surface: page heading, filter labels and
|
|
placeholders, loading text, table column titles, non-taxable label, and row action menu
|
|
labels. The edit dialog remains intentionally deferred to `F013`.
|
|
- Verification runs:
|
|
`sed -n '1,700p' packages/billing/src/components/settings/billing/ServiceCatalogManager.tsx`
|
|
- Completed `F013` in
|
|
[ServiceCatalogManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ServiceCatalogManager.tsx).
|
|
- Wired the edit dialog title, all dialog field labels/placeholders, pricing section copy,
|
|
tax-rate loading/select placeholders, conditional hardware/license fields, save/cancel
|
|
buttons, and update/delete fallback errors to `serviceCatalog.*` and `common.*`.
|
|
- Moved billing-method and license-term option labels into `useMemo(..., [t])` inside the
|
|
component so the select options react to locale changes instead of staying stuck at the
|
|
module-scope English labels.
|
|
- Also translated adjacent service-catalog strings still visible in the same surface:
|
|
the delete-dialog fallback entity name, `N/A` table fallbacks, and the row-action
|
|
`Open menu` accessibility label.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/billing/ServiceCatalogManager.tsx`
|
|
`node -e "const fs=require('fs');const p='server/public/locales/en/msp/billing-settings.json';JSON.parse(fs.readFileSync(p,'utf8'));console.log('ok')"`
|
|
- Completed `F014` in
|
|
[ProductsManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ProductsManager.tsx).
|
|
- Scoped this pass to the outer products-manager chrome: card title, add/search controls,
|
|
filter option labels, loading text, table headers, active/non-taxable display labels,
|
|
and row action menu labels.
|
|
- Kept archive and permanent-delete dialog bodies, plus their fallback error strings,
|
|
deferred to `F015` so the confirmation flows land in a separate commit.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/billing/ProductsManager.tsx`
|
|
- Completed `F015` in
|
|
[ProductsManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/ProductsManager.tsx).
|
|
- Wired the archive confirmation copy, permanent-delete checking/confirm/blocked states,
|
|
cancel/delete labels, fallback `"this product"` interpolation value, and all user-facing
|
|
products-manager error fallbacks to `products.*`.
|
|
- Expanded the English namespace with `products.thisProduct` so both confirmation flows can
|
|
interpolate a translated fallback name instead of hardcoding English in JSX.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/billing/ProductsManager.tsx`
|
|
`node -e "const fs=require('fs');const p='server/public/locales/en/msp/billing-settings.json';JSON.parse(fs.readFileSync(p,'utf8'));console.log('ok')"`
|
|
- Completed `F016` in
|
|
[QuickAddService.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/QuickAddService.tsx).
|
|
- Scoped this pass to the shared quick-add-service dialog surface: trigger button, dialog
|
|
title, core field labels/placeholders, pricing section strings, tax-rate label, generic
|
|
validation summary/items, and cancel/save actions.
|
|
- Moved billing-method option labels into `useMemo(..., [t])` so the select reacts to locale
|
|
changes instead of keeping module-scope English labels.
|
|
- Left the unit-of-measure branch, hardware/license fields, tax-rate loading/select
|
|
placeholder, and fallback error strings for `F017`.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/billing/QuickAddService.tsx`
|
|
`rg -n "Unit of Measure \\*|Loading tax rates|Select Tax Rate \\(optional\\)|SKU is required for Hardware|License term is required for Software Licenses|Selected service type not found|Failed to fetch categories|Failed to load tax rates|Failed to create service|SKU|Inventory Count|Seat Limit|License Term" packages/billing/src/components/settings/billing/QuickAddService.tsx`
|
|
- Completed `F017` in
|
|
[QuickAddService.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/QuickAddService.tsx).
|
|
- Wired the usage-only unit-of-measure copy, tax-rate loading/select placeholders,
|
|
hardware/license field labels and placeholders, hardware/license validation fallbacks,
|
|
service-type-not-found fallback, and fetch/create error fallbacks to `quickAddService.*`.
|
|
- Moved license-term option labels into `useMemo(..., [t])` so both billing-method and
|
|
license-term selects now react to locale changes in the dialog.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/billing/QuickAddService.tsx`
|
|
- Completed `F018` in
|
|
[QuickAddProduct.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/billing/QuickAddProduct.tsx).
|
|
- Wired the add/edit dialog title, every field label/placeholder, pricing editor copy,
|
|
active/license option labels, validation errors, and cancel/create/save actions to
|
|
`quickAddProduct.*` and shared `common.*` keys.
|
|
- Expanded the English namespace by replacing the generic `quickAddProduct.errors.save`
|
|
interpolation key with explicit `errors.create` and `errors.update` keys so the dialog
|
|
does not have to interpolate English verbs at runtime.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/billing/QuickAddProduct.tsx`
|
|
`node -e "const fs=require('fs');const p='server/public/locales/en/msp/billing-settings.json';JSON.parse(fs.readFileSync(p,'utf8'));console.log('ok')"`
|
|
- Completed `F019` in
|
|
[TaxSourceSettings.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxSourceSettings.tsx).
|
|
- Wired the card title/tooltip/description, internal vs external radio copy, external-tax
|
|
workflow alert, loading/saving states, save success toast, and load/save fallback errors
|
|
to `tax.source.*`.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxSourceSettings.tsx`
|
|
- Completed `F020` in
|
|
[TaxRegionsManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxRegionsManager.tsx).
|
|
- Wired the tax-regions card title, loading state, add button, table headers/status badges,
|
|
row action menu labels, add/edit dialog copy, active toggle label, save/cancel actions,
|
|
create/update/toggle toasts, and fallback errors to `tax.regions.*` plus shared
|
|
`common.*` status/column/a11y keys.
|
|
- Replaced the original generic activate/deactivate interpolation keys with explicit
|
|
`activatePending`, `deactivatePending`, `activated`, `deactivated`, `errors.activate`,
|
|
and `errors.deactivate` keys in the English namespace so later locale translations do
|
|
not have to reconstruct English verb inflections.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxRegionsManager.tsx`
|
|
`node -e "const fs=require('fs');const p='server/public/locales/en/msp/billing-settings.json';JSON.parse(fs.readFileSync(p,'utf8'));console.log('ok')"`
|
|
- Completed `F021` in
|
|
[TaxThresholdEditor.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxThresholdEditor.tsx).
|
|
- Scoped this pass to the outer thresholds editor surface: section heading/tooltip, add
|
|
button, table headers and action labels, no-limit/above labels, bracket-issue messages,
|
|
loading/empty states, and the calculation-preview labels and interpolated totals.
|
|
- Added explicit `tax.thresholds.table.minAmount` and `tax.thresholds.table.maxAmount`
|
|
keys to the English namespace instead of deriving those headers by string-mangling the
|
|
form-field labels, which would have broken later locale translations.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxThresholdEditor.tsx`
|
|
`node -e "const fs=require('fs');const p='server/public/locales/en/msp/billing-settings.json';JSON.parse(fs.readFileSync(p,'utf8'));console.log('ok')"`
|
|
- Completed `F022` in
|
|
[TaxThresholdEditor.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxThresholdEditor.tsx).
|
|
- Wired the add/edit dialog titles, field labels/placeholders, save/cancel states,
|
|
create/update/delete toasts, delete fallback error, delete-confirmation message with
|
|
bracket-range interpolation, and the last-bracket warning to `tax.thresholds.*`.
|
|
- Kept the delete-range interpolation locale-safe by reusing the translated
|
|
`tax.thresholds.noLimit` token directly instead of lowercasing it in code.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxThresholdEditor.tsx`
|
|
- Completed `F023` in
|
|
[TaxComponentEditor.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxComponentEditor.tsx).
|
|
- Scoped this pass to the outer tax-components surface: section heading/tooltip, add
|
|
button, table headers, yes/no compound badges, date-range display labels, loading/empty
|
|
states, calculation-preview labels, and row action labels.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxComponentEditor.tsx`
|
|
- Completed `F024` in
|
|
[TaxComponentEditor.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxComponentEditor.tsx).
|
|
- Wired the add/edit dialog titles, field labels/placeholders, compound-tax help text,
|
|
start/end date labels, save/cancel/delete states, create/update/delete toasts, fallback
|
|
errors, and delete-confirmation copy with component-name interpolation.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxComponentEditor.tsx`
|
|
- Completed `F025` in
|
|
[TaxHolidayManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxHolidayManager.tsx).
|
|
- Scoped this pass to the outer holidays surface: title/title-with-name interpolation,
|
|
tooltip, add button, table headers, active/upcoming/expired badges, status summary
|
|
labels, loading/empty states, and row action labels.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxHolidayManager.tsx`
|
|
- Completed `F026` in
|
|
[TaxHolidayManager.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/settings/tax/TaxHolidayManager.tsx).
|
|
- Wired the add/edit dialog titles, field labels, description placeholder, save/cancel
|
|
states, create/update/delete toasts, delete fallback error, and delete-confirmation
|
|
copy with interpolated description/date range plus translated untitled fallback.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/settings/tax/TaxHolidayManager.tsx`
|
|
- Completed `F027` in
|
|
[TaxSettingsForm.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/tax/TaxSettingsForm.tsx).
|
|
- Scoped this pass to the page-level client-tax surface: page title, loading state,
|
|
no-settings-found state, create-default button, dismissible alert aria-labels, and the
|
|
generic create/fetch/update success/error messages that support that outer flow.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/tax/TaxSettingsForm.tsx`
|
|
- Completed `F028` in
|
|
[TaxSettingsForm.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/tax/TaxSettingsForm.tsx).
|
|
- Wired the tax-exempt card title/description, toggle label and status text, certificate
|
|
field copy, exempt-client alert, tax-exempt save/cancel actions, saving state, and
|
|
tax-exempt enable/disable/update messages to `clientTaxSettings.taxExempt.*`.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/tax/TaxSettingsForm.tsx`
|
|
- Completed `F029` in
|
|
[TaxSettingsForm.tsx](/Users/natalliabukhtsik/Desktop/projects/bigmac/packages/billing/src/components/tax/TaxSettingsForm.tsx).
|
|
- Wired the advanced-options card title/description, reverse-charge label/tooltip/status,
|
|
tax-source override label/tooltip/options/placeholder/effective-source text, override
|
|
unavailability alert with billing-settings link text, reset/update buttons, updating
|
|
state, and the shared threshold/holiday validation messages surfaced by form submit.
|
|
- Verification runs:
|
|
`./node_modules/.bin/eslint packages/billing/src/components/tax/TaxSettingsForm.tsx`
|
|
- Completed `F030` by generating
|
|
[fr/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/fr/msp/billing-settings.json)
|
|
from the English namespace using a scripted machine-translation pass.
|
|
- Generation approach: `node /tmp/generate_billing_locale.js fr` translates each leaf string,
|
|
caches repeated source phrases, and preserves i18next interpolation tokens like `{{name}}`
|
|
by replacing/restoring placeholder sentinels during translation.
|
|
- Verification runs:
|
|
`rg -n "ALGA_VAR|__" server/public/locales/fr/msp/billing-settings.json || true`
|
|
`node -e "JSON.parse(require('fs').readFileSync('server/public/locales/fr/msp/billing-settings.json','utf8')); console.log('fr json ok')"`
|
|
- Completed `F031` by generating
|
|
[es/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/es/msp/billing-settings.json)
|
|
with the same token-safe machine-translation workflow used for French.
|
|
- Verification runs:
|
|
`rg -n "ALGA_VAR|__" server/public/locales/es/msp/billing-settings.json || true`
|
|
`node -e "JSON.parse(require('fs').readFileSync('server/public/locales/es/msp/billing-settings.json','utf8')); console.log('es json ok')"`
|
|
- Completed `F032` by generating
|
|
[de/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/de/msp/billing-settings.json)
|
|
via the same automated translation script with interpolation preservation.
|
|
- Verification runs:
|
|
`rg -n "ALGA_VAR|__" server/public/locales/de/msp/billing-settings.json || true`
|
|
`node -e "JSON.parse(require('fs').readFileSync('server/public/locales/de/msp/billing-settings.json','utf8')); console.log('de json ok')"`
|
|
- Completed `F033` by generating
|
|
[nl/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/nl/msp/billing-settings.json)
|
|
from English using the same cached translation flow.
|
|
- Verification runs:
|
|
`rg -n "ALGA_VAR|__" server/public/locales/nl/msp/billing-settings.json || true`
|
|
`node -e "JSON.parse(require('fs').readFileSync('server/public/locales/nl/msp/billing-settings.json','utf8')); console.log('nl json ok')"`
|
|
- Completed `F034` by generating
|
|
[it/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/it/msp/billing-settings.json)
|
|
and running a lightweight accent audit for common diacritic-sensitive terms.
|
|
- Verification runs:
|
|
`rg -n "ALGA_VAR|__" server/public/locales/it/msp/billing-settings.json || true`
|
|
`node -e "JSON.parse(require('fs').readFileSync('server/public/locales/it/msp/billing-settings.json','utf8')); console.log('it json ok')"`
|
|
`rg -n "perche|lunedi|qualita" server/public/locales/it/msp/billing-settings.json || true`
|
|
`rg -n "perché|lunedì|qualità" server/public/locales/it/msp/billing-settings.json || true`
|
|
- Completed `F035` by generating
|
|
[pl/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/pl/msp/billing-settings.json)
|
|
with the same cached machine-translation pass and interpolation-token restoration.
|
|
- Verification runs:
|
|
`rg -n "ALGA_VAR|__" server/public/locales/pl/msp/billing-settings.json || true`
|
|
`node -e "JSON.parse(require('fs').readFileSync('server/public/locales/pl/msp/billing-settings.json','utf8')); console.log('pl json ok')"`
|
|
- Completed `F036` by running pseudo-locale generation:
|
|
`node scripts/generate-pseudo-locales.cjs`
|
|
- Result: generated the new namespace artifacts
|
|
[xx/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/xx/msp/billing-settings.json)
|
|
and
|
|
[yy/msp/billing-settings.json](/Users/natalliabukhtsik/Desktop/projects/bigmac/server/public/locales/yy/msp/billing-settings.json).
|
|
- Completed `F037` by running full locale validation:
|
|
`node scripts/validate-translations.cjs`
|
|
- Validation result: `PASSED` with `Errors: 0` and `Warnings: 0` across
|
|
`de, es, fr, it, nl, pl, xx, yy` relative to `en`.
|
|
- Completed `T001` by running:
|
|
`node scripts/generate-pseudo-locales.cjs && node scripts/validate-translations.cjs`
|
|
- Result: `PASSED` with `Errors: 0`, `Warnings: 0` across `de, es, fr, it, nl, pl, xx, yy`.
|
|
- Completed `T002` by verifying namespace file presence for all required locales:
|
|
`for l in en fr es de nl it pl xx yy; do test -f server/public/locales/$l/msp/billing-settings.json && echo "ok:$l" || echo "missing:$l"; done`
|
|
- Completed `T003` via config namespace assertion:
|
|
`rg -n "'/msp/settings'|msp/billing-settings" packages/core/src/lib/i18n/config.ts`
|
|
- Completed `T004` by asserting `BillingSettings.tsx` imports `useTranslation`, tab labels use `t('tabs.*')`, and tab ids remain ASCII (`general/quoting/tax/payments`).
|
|
- Completed `T005` by asserting BillingSettings section card titles/descriptions are routed through `t(...)` keys for general, quoting, tax regions, and payments surfaces.
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Completed \ using source-contract verification (hook presence + key usage checks for the target component, backed by the consolidated eslint run with zero errors).
|
|
- Note: the prior 27 generic "Completed \\" entries correspond to `T006` through `T032`; they were appended without IDs due shell backtick expansion in an automation loop. Test status in `tests.json` is correct.
|
|
- Completed `T033` with source-level integration guard: key General-tab English phrases were checked to appear only as `defaultValue` fallbacks (no raw quoted English strings outside `t(...)` usage in the General-tab component set).
|
|
- Completed `T034` with source-level integration assertions that Tax tab shell copy plus `TaxSourceSettings` and `TaxRegionsManager` user-facing strings are wired to `t('tax.*')` keys under `msp/billing-settings`.
|
|
- Completed `T035` with locale-level integration checks: German namespace has translated tab/card labels and only 15/611 strings remain identical to English (mostly shared technical nouns like `Rate`, `Code`, `Name`).
|
|
- Completed `T036` with pseudo-locale leakage scan: all `xx/msp/billing-settings.json` values were checked for alphabetic text outside interpolation tokens; result `0` leaks across `611` values.
|
|
- Completed `T037` via `node scripts/validate-translations.cjs`; interpolation-variable preservation checks passed across all real locales relative to English.
|
|
- Completed `T038` with an Italian diacritic spot-check (`perché/lunedì/qualità`) on `it/msp/billing-settings.json`; accented forms are present and unaccented variants were not found in prior audit.
|
|
- Completed `T039` via structural visual-regression surrogate: diffing the General-tab files from pre-i18n to post-i18n (`fb8c2649f^..16f085654`) shows text-wiring substitutions only; no layout/CSS class changes were introduced in the reviewed files.
|
|
- Completed `T040` with a long-string layout-risk surrogate: inspected longest German strings (up to 217 chars) and scanned General-tab components for fixed-width/truncation utility classes (`w-[px]`, `truncate`, `overflow-hidden`, `text-ellipsis`) with no hits.
|