[ { "id": "F001", "description": "Add useOptionalI18n() hook to packages/ui/src/lib/i18n/client.tsx that returns null outside I18nProvider instead of throwing; locale falls back to LOCALE_CONFIG.defaultLocale", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F002", "description": "DatePicker.tsx renders display value with date-fns 'P' pattern and getDateFnsLocale(activeLocale) instead of hardcoded 'MM/dd/yyyy'", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F003", "description": "DatePicker accepts optional displayFormat prop as escape hatch for callers needing a fixed pattern", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F004", "description": "Audit all DatePicker call sites (37+) and confirm none rely on MM/dd/yyyy display output for parsing/serialization; document results in SCRATCHPAD", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F005", "description": "DateTimePicker.tsx renders locale-aware: explicit timeFormat prop wins ('P hh:mm a'/'P HH:mm' with locale), unset uses locale-derived 'P p'", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F006", "description": "Calendar.tsx passes date-fns locale to DayPicker so weekday/month names localize", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F007", "description": "Calendar MonthYearSelect caption format() calls use the active date-fns locale", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F008", "description": "CurrencyInput formats display value with Intl.NumberFormat(activeLocale) instead of hardcoded en-US", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F009", "description": "CurrencyInput parses input locale-aware: derive group/decimal separators via formatToParts, strip group separators, normalize decimal separator to '.' before parseFloat", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F010", "description": "PrintOptionsDialog formatDefaultPrintValue uses active locale for Date values instead of bare toLocaleString()", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F011", "description": "ReportExecutionOptions gains locale?: string in packages/reporting ReportEngine; threaded through execute \u2192 formatValue \u2192 formatCurrency/formatNumber/formatPercentage/formatDate; defaults to 'en-US' when absent", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F012", "description": "Identical locale threading applied to the server/src/lib/reports/core/ReportEngine.ts copy; duplication noted in SCRATCHPAD for future dedup", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F013", "description": "executeReport server action (both copies) resolves viewer locale via getHierarchicalLocaleAction and passes it in options", "implemented": true, "prdRefs": [ "P1a" ] }, { "id": "F014", "description": "filterPseudoLocales() keeps xx/yy when process.env.NODE_ENV === 'development'; INCOMPLETE_LOCALES (pt) stays filtered in dev", "implemented": true, "prdRefs": [ "P1b" ] }, { "id": "F015", "description": "packages/core dist rebuilt; all 7 language pickers show Pseudo (xx)/Pseudo (yy) in dev and hide them in production builds", "implemented": true, "prdRefs": [ "P1b" ] }, { "id": "F016", "description": "Selecting xx in dev persists as user preference and renders pseudo-translated UI across MSP and client portals", "implemented": true, "prdRefs": [ "P1b" ] }, { "id": "F017", "description": "Backfill cross-namespace actions.print / actions.printOptions keys in en for all 7+ affected namespaces (assets, clients, contacts, jobs, schedule, user-activities, workflows)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F018", "description": "Backfill 131 missing en keys in msp/workflows (WorkflowRunList, WorkflowDesigner, RunStudioShell)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F019", "description": "Backfill 111 missing en keys in msp/email-providers (InboundEmailRuleForm)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F020", "description": "Backfill 81 missing en keys in msp/integrations (LevelIoIntegrationSettings, InboundEmailRulesManager)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F021", "description": "Backfill 81 missing en keys in features/tickets (TicketChecklistSection, TicketingDashboard, TicketDetails)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F022", "description": "Backfill 54 missing en keys in msp/clients (Clients.tsx, MeetingAttendeesPicker, InteractionDetails, ClientDetails, ClientContractAssignment)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F023", "description": "Backfill 40 missing en keys in msp/assets (AssetDashboardClient)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F024", "description": "Backfill 37 missing en keys in msp/user-activities (ActivitiesTableFilters, AdHocDetailPanel)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F025", "description": "Backfill remaining ~120 missing en keys across msp/settings, common, msp/invoicing, msp/keyboard-shortcuts, msp/quotes, msp/contracts, projects, msp/schedule, msp/knowledge-base, features/projects, features/documents, client-portal, msp/time-entry", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F026", "description": "Translate all backfilled keys into fr, es, de, nl, it, pl, pt", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F027", "description": "Regenerate xx/yy pseudo-locales covering all backfilled keys", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F028", "description": "find-missing-i18n-keys.cjs reports 0 missing keys (exit 0)", "implemented": true, "prdRefs": [ "P2" ] }, { "id": "F029", "description": "MspClientTickets.tsx (client page Tickets tab) wired with useTranslation using msp/clients namespace; all hardcoded strings keyed", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F030", "description": "MspClientAssets.tsx (client page Assets tab) wired with useTranslation using msp/clients namespace; all hardcoded strings keyed", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F031", "description": "MspContactTickets.tsx (contact page Tickets tab) wired with useTranslation using msp/contacts namespace; all hardcoded strings keyed", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F032", "description": "InteractionsFeed.tsx (client page Interactions tab) wired with useTranslation using msp/clients interactions.* keys", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F033", "description": "OverallInteractionsFeed.tsx wired with useTranslation using msp/clients interactions.* keys", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F034", "description": "SchedulingInteractionDetails.tsx wired with useTranslation using msp/schedule namespace", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F035", "description": "All P3 component keys added to en + 7 production locales + regenerated pseudo-locales", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F036", "description": "ROUTE_NAMESPACES verified to load msp/clients on /msp/clients, msp/contacts on /msp/contacts, and msp/schedule where SchedulingInteractionDetails renders", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F037", "description": "Remaining 16 msp-composition files swept and documented in SCRATCHPAD as having no user-visible strings (providers/wrappers)", "implemented": true, "prdRefs": [ "P3" ] }, { "id": "F038", "description": "Full inventory of legacy _plural keys across all locales recorded in SCRATCHPAD (known: teams.details.memberCount_plural, interaction-types imported_plural, security.sessions.subtitle_plural x2 files)", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F039", "description": "English legacy _plural keys migrated to i18next v4 _one/_other forms in msp/settings.json and msp/profile.json", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F040", "description": "Non-English locales migrated with correct CLDR plural category sets (Polish gets _one/_few/_many/_other)", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F041", "description": "AdminSessionManagement.tsx replaces manual subtitle/subtitle_plural selection with a single t() call passing count (sessionCount drives plural; both interpolation variables preserved)", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F042", "description": "All other consumers of migrated plural keys verified to pass count and resolve correct forms (TeamDetails.tsx memberCount, interaction-types import toast)", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F043", "description": "validate-translations.cjs is CLDR-aware via Intl.PluralRules: no false warnings for locale-required plural suffixes (pl _few/_many), and flags locales missing required plural categories for keys with English plural forms", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F044", "description": "generate-pseudo-locales.cjs verified to carry plural-suffixed keys through to xx/yy correctly", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F045", "description": "validate-translations.cjs passes with 0 errors and 0 warnings across all locales", "implemented": true, "prdRefs": [ "P4" ] }, { "id": "F046", "description": "find-missing-i18n-keys job added to .github/workflows/validate-translations.yml", "implemented": true, "prdRefs": [ "P5" ] }, { "id": "F047", "description": "Workflow paths triggers expanded to packages/**, server/src/**, ee/server/src/**, and the find-missing script so component changes trigger validation", "implemented": true, "prdRefs": [ "P5" ] }, { "id": "F048", "description": "CI green on a no-op PR after P5 lands (both scripts pass from clean main)", "implemented": true, "prdRefs": [ "P5" ] } ]