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

27 KiB
Raw Permalink Blame History

Scratchpad — MSP i18n: Billing Dashboard Sub-batch

  • Plan slug: 2026-04-09-msp-i18n-billing-dashboard
  • Created: 2026-04-09

What This Is

Create a new msp/billing namespace and wire 17 top-level billing dashboard components that currently have zero i18n coverage. These are the "shell" components -- the main dashboard container, overview, usage tracking, reconciliation, line items, contract line services, accounting exports, and template rendering. Sub-batches for contracts, quotes, invoicing, credits, and service catalog are handled in separate plans.

Decisions

  • (2026-04-09) New namespace msp/billing rather than extending features/billing. Rationale: features/billing is used by client-portal components and loaded on /client-portal/billing. MSP billing has a much larger surface area with different terminology (reconciliation, contract lines, accounting exports, etc.). Keeping them separate avoids loading ~475 MSP-only keys on the client portal.
  • (2026-04-09) Use t('key', { defaultValue: 'English fallback' }) pattern consistently across all components. This matches the established pattern in the codebase.
  • (2026-04-09) Import pattern: import { useTranslation } from '@alga-psa/ui/lib/i18n/client' and import { useFormatters } from '@alga-psa/ui/lib/i18n/client' for currency/date formatting.
  • (2026-04-09) billingTabsConfig.ts is a plain TypeScript file (not a React component), so it cannot call useTranslation() directly. Options: (a) store translation keys in the config and translate in the consuming component, or (b) convert to a hook that returns translated definitions. Option (a) is simpler and consistent with how the config is used. Decision: store labelKey alongside label in the config, translate in the tab rendering component using t(tab.labelKey, { defaultValue: tab.label }).
  • (2026-04-09) TemplateRendererCore.ts is a pure function (not a React component), so it cannot use hooks. The strings it outputs (N/A, Unknown value, No data for list, Uncategorized) appear in rendered invoice HTML, not in the dashboard UI chrome. These should be audited but likely marked as N/A for this batch -- invoice content localization is a separate concern.
  • (2026-04-09) TemplateRenderer.tsx has 3-4 small strings (loading, error, empty state) that are proper UI chrome and should be translated.

Discoveries / Constraints

  • (2026-04-09) Current ROUTE_NAMESPACES['/msp/billing'] loads ['common', 'msp/core', 'features/billing', 'msp/reports']. Adding 'msp/billing' to this array is the only config change needed.
  • (2026-04-10) server/public/locales/en/msp/billing.json was created as a broad foundational namespace with shared vocabulary across dashboard, overview, reconciliation, discrepancy, usage, line-item, services, exports, template designer, and quantity-dialog surfaces. It intentionally front-loads reusable labels so later component wiring can reference stable keys instead of inventing ad hoc per-file strings.
  • (2026-04-10) Locale generation can be bootstrapped from the English namespace using translate.googleapis.com while preserving {{interpolation}} tokens. This is good enough for parity work, but repeated billing vocabulary still needs spot-auditing because machine translation is not domain-aware (for example, quote/billing terminology can drift).
  • (2026-04-10) A temporary smoke-test invocation of the locale generator created an unintended server/public/locales/--help directory. This was removed before validation; no tracked files depended on it.
  • (2026-04-09) ReconciliationResolution.tsx (1129 LOC) is the largest file and has ~80 user-visible strings spanning 3 wizard steps, resolution options, four-eyes approval flow, and a confirmation dialog. Split into 3 features (F020-F022).
  • (2026-04-10) ReconciliationResolution.tsx can reuse the already-seeded reconciliation.steps.*, reconciliation.sections.resolutionOptions, and reconciliation.resolutionTypes.* keys without expanding the locale surface. That keeps the first reconciliation wiring pass focused and avoids immediate locale-file churn after F009 validation.
  • (2026-04-09) DiscrepancyDetail.tsx (921 LOC) has ~70 strings and shares many labels with ReconciliationResolution (balance comparison, issue types, recommended fix text). Key reuse within the namespace will reduce total key count. Split into 3 features (F030-F032).
  • (2026-04-10) DiscrepancyDetail.tsx can share a large chunk of terminology with the reconciliation wizard, but it also has its own discrepancy.* card/field/status groups. The first pass is mostly shell labeling; the tab-heavy table content is the riskier part and is better split into separate commits.
  • (2026-04-09) LineItem.tsx (514 LOC) has complex conditional rendering for regular items vs discounts (percentage vs fixed). The collapsed/expanded states have different label sets. ~40 strings total, split into 2 features (F050-F051).
  • (2026-04-09) FixedContractLineServicesList.tsx and FixedContractLinePresetServicesList.tsx share nearly identical table structures and add-services UI. Many keys can be shared under contractLineServices.* group. Preset-specific keys (unsaved changes, save/reset) go under presetServices.*.
  • (2026-04-09) AccountingExportsTab.tsx uses react-hot-toast (not useToast()) for toast messages. The toast.success('...') calls should be wrapped with t().
  • (2026-04-09) Overview.tsx metric cards use a MetricCard component that accepts title and subtitle props as strings. These need to become t() calls at the call site, not inside MetricCard itself (MetricCard is a generic presentational component).
  • (2026-04-10) UsageTracking.tsx already had a clean separation between list-shell strings and dialog/toast strings. That makes it safe to split the i18n pass into F017 (table/filter shell) and F018 (dialog, guidance, toasts) without touching locale structure in between.
  • (2026-04-10) LineItem.tsx can be split cleanly between content labels/summary strings and the remaining chrome-only strings. The existing lineItem.* locale group already covers both halves, so F019/F020 do not need additional locale keys unless a hidden string surfaces during test coverage.
  • (2026-04-10) FixedContractLineServicesList.tsx already has a complete contractLineServices.* locale group for both the table shell and add-services drawer copy. The only extra reuse needed is common.notAvailable / common.openMenu for fallback and accessibility labels, so F021/F022 can stay locale-neutral unless a new error state appears.
  • (2026-04-10) AccountingExportsTab.tsx already has enough accountingExports.* keys for the card shell and both dialogs, but it does not yet have explicit status-label keys for backend values like pending, delivered, and needs_attention. Those raw status codes are still visible after the first shell pass and need a follow-up before the PRD is truly done.
  • (2026-04-10) Added discovered follow-up items F024A / T020A for accounting-export status labels. Rationale: the PRD explicitly calls out status labels, but the original checklist only covered shell/dialog chrome and the namespace did not yet include accountingExports.status.* keys.
  • (2026-04-09) ContractsHub.tsx is small (77 LOC) but renders tab labels that should use msp/billing namespace for consistency with the billing dashboard.
  • (2026-04-09) PropertyEditor.tsx and ConditionalRuleManager.tsx are part of the invoice template designer. They have few strings (~7 and ~6 respectively) but are user-facing UI chrome that should be translated.

Gotchas

  • billingTabsConfig.ts tab labels -- these are consumed by BillingDashboard.tsx which renders them via Radix Tabs. The tab definitions are also used in sidebar navigation. Need to verify that all consumers of billingTabDefinitions handle the translation key pattern correctly.
  • FixedContractLineServicesList Default Rate tooltip -- uses <Tooltip> component with complex content. The tooltip text is a sentence about service rate allocation. Translate the full sentence as a single key rather than composing from fragments.
  • ReconciliationResolution STEPS constant -- defined at module scope outside the component. Either (a) convert to a function that accepts t, or (b) define translated labels inside the component and map from STEPS. Option (b) avoids changing the STEPS interface.
  • formatCurrency / formatDateTime -- these already use locale-aware formatting via @alga-psa/core. No need to translate their output; they handle locale internally.
  • Discount type options in LineItem.tsx -- discountTypeOptions is defined at module scope as a constant array. Same pattern as STEPS -- translate in-component.
  • BILLING_METHOD_OPTIONS in FixedContractLineServicesList and FixedContractLinePresetServicesList -- defined at module scope. Same pattern: translate labels in-component or use t() in the render callback.
  • (2026-04-10) The initial English namespace includes some forward-looking keys for later features/tests. As component wiring lands, keep locale parity by updating the real locales and pseudo-locales in lockstep rather than creating one-off English-only keys.

Key Count Estimate

Group Est. Keys
dashboard (title, beta, tabs) ~20
overview (metrics, features, catalog) ~40
reconciliation (stepper, resolution, approval, confirmation) ~55
discrepancy (status, tables, issue detail, dialog) ~50
recommendedFix (panels, dialogs, impact) ~30
usage (table, form, filters, toasts) ~40
lineItem (fields, discounts, summary) ~35
contractLineServices (table, add, actions) ~30
presetServices (table, unsaved, save/reset) ~20
accountingExports (table, dialogs) ~35
templateRenderer/Designer (loading, labels) ~15
contractsHub (heading, tabs) ~5
editQuantityDialog (title, validation, buttons) ~10
Total ~385

After key reuse (shared labels like Cancel, Save, Error, etc. from common namespace), the actual msp/billing.json key count will likely be ~350-380 unique keys.

Progress Log

  • (2026-04-10) F001 complete -- Added server/public/locales/en/msp/billing.json with 14 top-level groups (common, dashboard, overview, reconciliation, discrepancy, recommendedFix, usage, lineItem, contractLineServices, presetServices, accountingExports, templateRenderer, templateDesigner, contractsHub, editQuantityDialog, templateRendererCore). Verified the file parses with node -e "JSON.parse(...)". This gives the batch a stable namespace before locale generation and component wiring.
  • (2026-04-10) F002 complete -- Generated server/public/locales/fr/msp/billing.json from the English source with placeholder preservation and verified it parses. The first pass is machine-generated; keep an eye on MSP-specific wording during later UI smoke tests.
  • (2026-04-10) F003 complete -- Generated server/public/locales/es/msp/billing.json with the same placeholder-safe pipeline and verified it parses. Locale generation is now quick enough to finish the remaining real locales before component wiring.
  • (2026-04-10) F004 complete -- Generated server/public/locales/de/msp/billing.json and verified it parses. The machine pass works structurally; wording cleanup remains a later QA item, especially for action verbs and billing-domain nouns.
  • (2026-04-10) F005 complete -- Generated server/public/locales/nl/msp/billing.json and verified it parses. The translation endpoint threw one transient 500 during generation; resuming from the on-disk cache completed the locale without losing prior progress.
  • (2026-04-10) F006 complete -- Generated server/public/locales/it/msp/billing.json and verified it parses. The explicit Italian accent audit still needs the global validation pass, but the locale file is now present and structurally correct.
  • (2026-04-10) F007 complete -- Generated server/public/locales/pl/msp/billing.json and verified it parses. At this point all real-language locale files for msp/billing exist; pseudo-locales and parity validation are next.
  • (2026-04-10) F008 complete -- Ran node scripts/generate-pseudo-locales.cjs, which regenerated server/public/locales/xx/msp/billing.json and server/public/locales/yy/msp/billing.json from the English source. Verified both pseudo-locale files now exist.
  • (2026-04-10) F009 complete -- Ran node scripts/validate-translations.cjs after cleaning up the stray --help locale directory. Validation passed with 0 errors / 0 warnings across de, es, fr, it, nl, pl, xx, and yy.
  • (2026-04-10) F010 complete -- Updated packages/core/src/lib/i18n/config.ts so ROUTE_NAMESPACES['/msp/billing'] now loads msp/billing alongside common, msp/core, features/billing, and msp/reports. This is the only route-config change needed for this batch.
  • (2026-04-10) F011 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/ReconciliationResolution.tsx for the stepper labels and the three resolution-type options. The step array now derives labels from t() at render time instead of relying on the module-scope English constants.
  • (2026-04-10) F012 complete -- Continued the ReconciliationResolution.tsx pass by translating the discrepancy detail labels (Client, Status, Detected, Issue Type), the balance comparison labels, and the two issue-type titles. This kept the commit aligned with the existing reconciliation.fields.*, reconciliation.sections.*, reconciliation.status.*, and reconciliation.issueTypes.* key groups.
  • (2026-04-10) F013 complete -- Finished the main reconciliation wizard shell: four-eyes approval copy, approval verification UI, correction summary labels, confirmation-step summary text, completion dialog copy, and user-facing error messages now read from msp/billing. Reused existing namespace keys throughout, so no locale-file regeneration was needed after F009.
  • (2026-04-10) F014 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/DiscrepancyDetail.tsx for the back navigation text, status badges, discrepancy detail labels, issue-type labels, and balance comparison card labels.
  • (2026-04-10) F015 complete -- Continued DiscrepancyDetail.tsx by translating the transaction-history tab labels, expanded transaction metadata labels, the credit-tracking tab labels, and the credit-entry detail labels/status text. No new locale keys were needed because discrepancy.tabs.*, discrepancy.cards.*, discrepancy.fields.*, discrepancy.status.*, and discrepancy.empty.* were already seeded in F001.
  • (2026-04-10) F016 complete -- Finished DiscrepancyDetail.tsx by translating the issue-details tab, recommended-fix copy, credit-applications table headings, resolve-discrepancy dialog labels, and the remaining empty/error states. This closes out the discrepancy detail screen without expanding the locale schema beyond the keys already seeded in F001.
  • (2026-04-10) F017 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/UsageTracking.tsx for the bucket overview title, usage table headers, contract-line summary text, filter labels/placeholders, loading state, and row action menu labels.
  • (2026-04-10) F018 complete -- Finished UsageTracking.tsx by translating the add/edit dialog labels, contract-line selector guidance/placeholder copy, create-update-delete toasts, and the delete confirmation dialog. This closes out the usage-tracking screen without introducing new locale keys after the foundational namespace work.
  • (2026-04-10) F019 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/LineItem.tsx for the regular field labels, discount field labels, collapsed summary strings, subtotal/discount summaries, and the discount-description placeholder. The file reused the seeded lineItem.collapsed.*, lineItem.fields.*, lineItem.placeholders.*, and lineItem.summary.* keys, so locale regeneration was not needed.
  • (2026-04-10) F020 complete -- Finished LineItem.tsx by translating the expanded header labels (Discount, Item {{number}}, Marked for removal), action buttons, discount type select options, the Entire Invoice target option, and the percentage-discount “calculated on save” hint. This closes out the top-level line-item editor without expanding the lineItem.* locale group.
  • (2026-04-10) F021 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/FixedContractLineServicesList.tsx for the associated-services table headers, billing-method labels, Product/Service badges, default-rate tooltip, action-menu labels, missing-price cell text, and the small accessibility/fallback strings (Open menu, N/A, Unknown Service). No locale regeneration was needed because the seeded contractLineServices.* keys plus common.* already covered the table shell.
  • (2026-04-10) F022 complete -- Finished FixedContractLineServicesList.tsx by translating the load/add/remove error messages, loading/empty states, add-services section heading, service metadata rows, product custom-rate label, count-aware add button, and the Unknown Service fallback passed into the quantity dialog. This closes out the fixed contract-line services list without adding new locale keys beyond the original contractLineServices.* plan.
  • (2026-04-10) F023 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/accounting/AccountingExportsTab.tsx for the card title/description, batch table headers, outer action buttons, list loading/empty states, and the list-side execute/load-batches feedback messages. This leaves the create/detail dialogs plus status-label normalization for follow-up commits.
  • (2026-04-10) F024 complete -- Finished AccountingExportsTab.tsx by translating the new-export dialog labels/placeholders/buttons, the batch-detail dialog title/field labels/states, and the create/load-detail feedback messages. The remaining accounting-exports gap is the raw backend status-code display, which is now tracked explicitly as F024A.
  • (2026-04-10) F024A complete -- Added accountingExports.status.* keys to the English and six real-language locale files, regenerated pseudo-locales, and mapped AccountingExportsTab.tsx batch statuses (pending, validating, ready, delivered, posted, failed, cancelled, needs_attention) through t(). Re-ran node scripts/generate-pseudo-locales.cjs and node scripts/validate-translations.cjs; validation passed with 0 errors / 0 warnings.
  • (2026-04-10) F025 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/FixedContractLinePresetServicesList.tsx for the preset table headers, billing-method labels, default-rate tooltip, row action label, unsaved-changes warning, loading text, add-services section title/button, and save/reset button states. Reused presetServices.*, contractLineServices.billingMethods.*, and common.* without expanding the locale schema.
  • (2026-04-10) F026 complete -- Finished FixedContractLinePresetServicesList.tsx by translating the preset empty states, add-list service metadata row, and the navigate-away confirmation dialog. The preset save/load error alerts now flow through translated default messages introduced in the prior pass, so this closes out the preset services manager without new locale keys.
  • (2026-04-10) F027 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/RecommendedFixPanel.tsx for the card title, panel headings, issue-type-specific descriptions, per-fix button labels, and the field labels embedded in the recommended-fix summaries. Existing recommendedFix.*, reconciliation.fields.*, and discrepancy.fields.* keys were sufficient, so no locale-file update was needed.
  • (2026-04-10) F028 complete -- Finished RecommendedFixPanel.tsx by translating the fix-dialog titles/descriptions, adjustment amount and notes fields, impact-summary labels, resolved-state copy, and dialog/apply error states. This closes out the recommended-fix workflow without further locale changes because the seeded recommendedFix.dialog.*, recommendedFix.impactSummary.*, recommendedFix.resolved.*, and recommendedFix.errors.* groups already existed.
  • (2026-04-10) F029 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/Overview.tsx for the seven metric card titles/subtitles, the Monthly Activity section, and the Service Catalog Management quick-access card. This kept the first Overview pass aligned with the seeded overview.metrics.* and overview.sections.* keys.
  • (2026-04-10) F030 complete -- Finished Overview.tsx by translating the feature-card grid, the destructive load-error alert, the small metric fallback states (..., Error, 0, 0 hours), and the development-only debug labels. No locale updates were needed because the seeded overview.features.*, overview.errors.*, overview.states.*, and overview.debug.* groups already covered the remaining strings.
  • (2026-04-10) F031 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/BillingDashboard.tsx for the page title, beta banner, error prefix, quote-templates heading, and the back-to-preset navigation text. The component still does not render the tab labels from billingTabsConfig, so the separate F033 follow-up remains necessary.
  • (2026-04-10) F032 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/EditContractLineServiceQuantityDialog.tsx for the interpolated dialog title, quantity label, validation messages, save error fallback, cancel/save buttons, and saving indicator text. No locale changes were needed because editQuantityDialog.* already covered the entire dialog surface.
  • (2026-04-10) F033 complete -- Added labelKey to every entry in packages/billing/src/components/billing-dashboard/billingTabsConfig.ts and translated the config in BillingDashboard.tsx with t(tab.labelKey, { defaultValue: tab.label }). BillingDashboard still does not render a local Tabs.List, but the route now consumes a translated tab-definition model rather than raw English labels.
  • (2026-04-10) F034 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/TemplateRenderer.tsx for the loading text, destructive error prefix, and empty-state message shown before an invoice/template pair is selected. No locale updates were needed because templateRenderer.* already existed.
  • (2026-04-10) F035 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/PropertyEditor.tsx for the field labels, “Select a field” option, and the generated column/row size captions. The existing templateDesigner.propertyEditor.* keys covered the inspector without locale churn.
  • (2026-04-10) F036 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/ConditionalRuleManager.tsx for the heading, action select options, text-input placeholders, and add-rule button label. The existing templateDesigner.conditionalRules.* keys fully covered the component.
  • (2026-04-10) F037 complete -- Wired useTranslation('msp/billing') into packages/billing/src/components/billing-dashboard/ContractsHub.tsx for the hub heading and the two sub-tab labels. This closes out the contracts hub chrome with the existing contractsHub.* keys.
  • (2026-04-10) F038 complete -- Audited packages/billing/src/components/billing-dashboard/TemplateRendererCore.ts and confirmed its fallback strings (No data for list, Uncategorized, N/A, Unknown value) are emitted into generated invoice HTML rather than the billing dashboard shell. Added code comments documenting that boundary instead of forcing dashboard-namespace translation into the pure renderer.
  • (2026-04-10) T001 complete -- Re-ran node scripts/generate-pseudo-locales.cjs and node scripts/validate-translations.cjs after the later accounting-export status-key expansion and final feature wiring. Validation still passed with 0 errors / 0 warnings across de, es, fr, it, nl, pl, xx, and yy, so locale parity remains intact after the full feature set.
  • (2026-04-10) T002 complete -- Added packages/billing/tests/billing-dashboard/ReconciliationResolution.i18n.test.ts and verified, under packages/billings Vitest config, that the stepper labels are wired through msp/billing and backed by pseudo-locale keys. Command used: npm exec -- vitest --root packages/billing --config vitest.config.ts run tests/billing-dashboard/ReconciliationResolution.i18n.test.ts.
  • (2026-04-10) T003 complete -- Extended the same ReconciliationResolution audit test to cover the three resolution-option labels (Recommended Fix, Custom Correction, No Action Required) and verified the updated file passes under the billing package Vitest config.
  • (2026-04-10) T004 complete -- Extended the ReconciliationResolution audit to cover the translated balance-comparison labels and the four-eyes approval copy (requiredTitle, requiredDescription, approver fields, verification code, verified badge title). The billing-package Vitest run remained green.
  • (2026-04-10) T005 complete -- Extended the ReconciliationResolution audit to cover the confirmation-step copy (importantTitle, importantDescription, confirm/close buttons, thank-you title) and the key reconciliation error messages. The shared audit file still passed under the billing-package Vitest config.
  • (2026-04-10) T006 complete -- Added a pseudo-locale coverage assertion to the same ReconciliationResolution audit, verifying that representative step, resolution-type, four-eyes, and confirmation keys are present in server/public/locales/xx/msp/billing.json rather than falling back to raw English.

Runbook

  • node -e "JSON.parse(require('fs').readFileSync('server/public/locales/en/msp/billing.json','utf8')); console.log('ok')"
  • node - <<'NODE' ... generate translated locale from en/msp/billing.json via translate.googleapis.com while preserving {{placeholders}} ... NODE
  • node scripts/generate-pseudo-locales.cjs
  • rm -rf server/public/locales/--help && node scripts/validate-translations.cjs
  • npm exec eslint -- packages/billing/src/components/billing-dashboard/LineItem.tsx
  • npm exec eslint -- packages/billing/src/components/billing-dashboard/FixedContractLineServicesList.tsx
  • npm exec eslint -- packages/billing/src/components/billing-dashboard/accounting/AccountingExportsTab.tsx