Skip to content

Hardcoded text i18n audit (baseline) โ€‹

Generated during the hardcoded-text remediation pass.

Phase 1 โ€” Existing audit tools โ€‹

ToolResult
dart run tool/audit_i18n_keys.dart2408 keys scanned; 1 false-positive dynamic prefix (valuation.workflowStages.$uiKey)
audit_missing_i18n_test0 missing / 0 self-referential (ar + en)
audit_areas_i18n_test0 missing per feature area
audit_isAr_hardcoded_testPass (6 allowlisted screen files)
audit_choice_field_coverage_testPass

Phase 2 โ€” Pattern grep (lib/) โ€‹

PatternApprox. hits
tOrNull(...) ?? 'English'39 across 10 files
SnackBar(content: Text(e.toString()27 across 18 files
isAr ? in /screens/62 (6 allowlisted files)
Hardcoded Text('English') in features~15 high-priority files

Allowlisted isAr screens (P2 debt): comparables_screen, site_inspection_screen, 3ร— AI screens, add_property_screen.

Fix priority โ€‹

See plan: P0 broker/public โ†’ P1 mailbox/admin โ†’ P2 isAr screens โ†’ P3 dev tools โ†’ P4 error SnackBars โ†’ CI hardening.


Round 2 baseline (2026-06-10) โ€‹

ToolResult
dart run tool/audit_i18n_keys.dart2591 keys; ar/en ok
audit_missing_i18n_testPass
audit_areas_i18n_testPass
audit_isAr_hardcoded_testPass
audit_hardcoded_literals_testPass (bare Text('โ€ฆ') clean in features)
audit_choice_field_coverage_testPass

Round 2 grep targets (pre-fix) โ€‹

PatternCount
suffixText: 'KWD'12 file hits
suffixText: 'mยฒ'5 file hits
tOrNull(...) ?? slug~10 files
'B ${block}' / 'ู‚ ${block}'8+ screens

Round 2 focus: stored-value chip labels, unit suffixes, block/plot prefixes, tOrNull slug fallbacks, shared-widget defaults.


Round 2 completion (2026-06-10) โ€‹

ToolResult
dart run tool/audit_i18n_keys.dart2594 keys; ar/en ok
test/tool/* (14 tests)All pass
audit_hardcoded_literals_test+ shared-widgets scan; + unit suffix scan
audit_isAr_hardcoded_testMultiline continuation join
audit_tOrNull_fallback_testNew โ€” blocks raw slug fallbacks
flutter analyze --no-fatal-infos0 errors

Round 2 grep targets (post-fix) โ€‹

PatternCount
suffixText: 'KWD' / 'mยฒ' / '%'0
tOrNull(...) ?? rawSlug in features0
'B ${block}' / 'ู‚ ${block}' in screens0 (via formatBlockLabel / formatPlotLabel)

New / updated helpers โ€‹

  • lib/core/formatting/location_labels.dart โ€” block/plot prefixes
  • lib/features/properties/widgets/building_composition_labels.dart โ€” apt comp room/facility labels
  • Translation keys: common.plotPrefix, common.percent, property.values.apt_comp_*, aiMarketing.captionType.*, hermes.dashboard.runsChartSemantics

Round 3 baseline (2026-07-01) โ€” cross-surface alignment โ€‹

ToolResult
dart run tool/audit_i18n_keys.dart3241 keys; ar/en ok
npm run i18n-check (aldilaijanre)14716 keys; ar/en parity ok
audit_missing_i18n_testPass
audit_hardcoded_literals_testPass
audit_isAr_hardcoded_testPass
audit_data_layer_i18n_testPass (ai_content_repository allowlisted)
taxonomy_registry_lock_testPass after al_maktab โ†’ free-text
cross_repo_governorate_lock_testFlutter โ†” registry โ†” React
cross_repo_label_parity_testdeal_type EN labels match
codegen_kuwait_area_labels.dart --check221 areas in sync

Domain consolidation (this pass) โ€‹

DomainChange
GovernoratespropertyGovernorateOptions / kPublicToolGovernorates / kMojGovernorateOptions โ†’ kCanonicalGovernorates
Property typespropertyTypeOptions โ†’ schema; valuationPropertyTypes derived from canonical subset
Deals / requestsStoredChoiceOption inline labels removed; i18n-only display
Voice notesvoiceNoteContextLabel / relative time โ†’ voiceNotes.* + common.* keys
Comparables subjectValuationSubject.title uses formatBlockLabel
Areasexport/paci_areas_catalog.json + codegen drift check

Remaining grep debt (P2) โ€‹

PatternLocation
isAr ? wire prefixesai_content_repository.dart (server parity)
kPublicToolPropertyTypesArabic MoJ/hedonic consumers โ€” intentional separate vocab
Arabic price-group stored valuesrequests/constants.dart (al_majmua legacy)
Dual i18n namespacesFlutter *.values.* vs React enums.* โ€” spot-checked for deals

Manual QA checklist (Round 3) โ€‹

  • [x] Flutter Web 375px + 1280px โ€” ar/en governorate chips on registry, client browse, transactions
  • [x] Flutter mobile โ€” voice notes relative time ar/en (bundle keys verified; device spot-check deferred)
  • [x] React SPA โ€” deal type labels on deal form match Flutter (cross_repo_label_parity_test)
  • [x] RTL โ€” governorate filter chips truncate cleanly (web layout smoke at 375px)

Round 4 baseline (2026-07-01) โ€” backlog closure โ€‹

ToolResult
dart run tool/promote_locale_namespaces.dart --checkCanonical ar/en namespace parity for individuals, individualForm, partyRegistry, duplicateReview
dart run tool/sync_i18n.dart --checkCanonical Flutter bundle structure and bilingual key parity
dart run tool/export_taxonomy_registry.dart + sync_export_edge_bundle.dartFlutter-owned taxonomy and deployable export bundle
cross_repo_label_parity_testLocal deal_type, governorates, built_or_land, MoJ transactions.values.* coverage (ar+en)
valuation_workflow_stages_lock_test7 UI stages โІ 11 schema keys via valuationWorkflowUiKey
React eslint i18next/no-literal-stringwarn on src/pages/** only
MoJ facetstransactions.values.category.ุฎุงุต + publicTransactions.dealSubtitle in both bundles

Still intentional P2 โ€‹

PatternLocation
~2k mobile-only keysParty 360 / individuals until React screens ship
Dual namespacesFlutter *.values.* vs React enums.* beyond spot-checked catalogs
kPublicToolPropertyTypesArabic MoJ/hedonic vocab
ai_content_repositoryServer parity wire prefixes

Round 5 baseline (2026-07-01) โ€” P2 Party 360 + create/edit โ€‹

DeliverableStatus
React usePartyActivityMirrors Flutter party_activity_repository (deals, requests, properties, valuations, invoices, tahdeed)
PartyDetail tabsBrokerage / valuation / financial / activity bodies wired with deep links
partyDetailVisibilityData-gated tabs via partyActivityFlags (Vitest lock)
ContactsListDebounced search, people classification chips, entity sector/category chips, i18n AK/KH badges
IndividualForm/clients/new, /clients/:id/edit โ€” core fields (name, phone, civil ID, classification)
AddPartyDialogEntities FAB quick-add via find_or_create_party RPC
PartyOrganizationProfileOrg profile tab โ€” people linked via primary_contact_id
usePartyRegistrycreate/update individual, org quick-add, duplicate detection
Routescontacts.new, contacts.edit(id) registered before :id detail
promote_locale_namespaces+ duplicateReview namespace
cross_repo_label_parity_test+ enums.propertyCategory valuation subset; built_or_land EN aligned
React localesRestored nested contacts.* + tahdeed.section.letters

Verification (Round 5) โ€‹

ToolResult
React npm run i18n-check14784 static keys; AR/EN 24164 each
React vitestindividualParty, partyDetailVisibility
React tsc --noEmit -p tsconfig.app.jsonClean after phase 2

Manual QA checklist (Round 5) โ€‹

  • [ ] /clients/new โ€” create individual, duplicate phone toast
  • [ ] /clients/:id/edit โ€” hydrate + save
  • [ ] Entities FAB โ†’ AddPartyDialog org create
  • [ ] Org detail profile โ†’ people-at-org list
  • [ ] Entity list sector + category filter chips
  • [ ] Party 360 tabs show/hide per linked data (ar/en)

Still intentional P2 โ€‹

ItemNotes
Full *.values.* โ†’ enums.* migrationMoJ coarse categories migrated on PredictiveAnalytics; remaining domains TBD
al_majmua / kPublicToolPropertyTypesDB migration or intentional vocab
Admin convergence health detail panelโœ… Admin contacts list + duplicate review (Round 8)
ESLint i18n error on all pagessrc/pages/contacts/** ratcheted to error (Round 6)

Round 6 baseline (2026-07-01) โ€” deferred closure โ€‹

DeliverableStatus
IndividualForm nickname + professionSectioned form matching Flutter
IndividualPaciAddressFieldGovernorate/area/block/street/building/PACI serial
CivilIdDocumentField + uploadCivilIdDocentity-documents bucket, post-save upload
PartyRegistrySummaryBarAdmin KPI strip (total / orgs / linked properties)
useConvergenceHealthDuplicate-party badge on review button
mojCategoryTaxonomyEnglish UI keys + bilingual .in('category', โ€ฆ)
ESLinti18next/no-literal-string error on src/pages/contacts/**

Round 7 baseline (2026-07-01) โ€” optional polish โ€‹

DeliverableStatus
ClassificationFieldClient buyer/seller chips; investor subtype + area-of-interest multi-select
classificationField.tscomposeClassificationSubtype / composeAreasOfInterest (Flutter parity)
OrganizationForm + PartyEditPage/clients/:id/edit routes to individual or org editor
partyPersonsSchema.tsTyped partyPersonsTable() โ€” replaces scattered as any on registry writes
Localescontacts.entities.editTitle (ar/en)

Round 8 baseline (2026-07-01) โ€” deferred closure โ€‹

DeliverableStatus
React price_groups[]Form write + list filter on price_groups; PRICE_GROUP_OPTIONS English keys
enums.priceGroup.*9 keys + legacy Arabic aliases in enumMaps.priceGroup
cross_repo_label_parity_test+ request.values.price_groups โ†” enums.priceGroup
Flutter requestPriceGroupOptionsValue-only StoredChoiceOption (no inline labelAr/En)
Identity drift panelDuplicateReview drift tab + useIdentityDriftWatch
ESLint ratcheterror on src/pages/admin/AdminDuplicateReviewPage.tsx

Round 9 baseline (2026-07-01) โ€” admin ESLint ratchet โ€‹

DeliverableStatus
WhatsAppShadowReview.tsxEntity filter, skip badges, run id via shadowReview.* keys
ESLinti18next/no-literal-string error on all src/pages/admin/**
LocalesshadowReview.entities.*, skippedWithReason, runId (ar/en)
Intentional freeze (documented)kPublicToolPropertyTypes, ai_content_repository wire prefixes

Manual QA checklist (Round 5โ€“8) โ€‹

  • [x] Automated: i18n-check, vitest, tsc, ESLint contacts + admin
  • [x] Automated: cross-repo price_group + party registry parity tests
  • [ ] /clients/new โ€” create individual, duplicate phone toast (device)
  • [ ] /clients/:id/edit โ€” hydrate + save (device)
  • [ ] Request form โ€” price-band chips persist to price_groups (device)
  • [ ] Duplicate review drift tab โ€” snapshot vs CRM name rows (device)

Closed deferrals โ€‹

ItemResolution
al_majmua price bandsReact uses price_groups; al_majmua reserved for area groups
Admin drift panelFull table in DuplicateReview
ESLint beyond contactsAdmin pages ratcheted
*.values.* โ†’ enums.*Price groups domain locked; domain-by-domain continues in CI

Still intentional (no change) โ€‹

ItemNotes
kPublicToolPropertyTypesArabic MoJ/hedonic stored vocab โ€” query boundary
ai_content_repository wire prefixesServer parity tokens, not UI copy
Full enum namespace mergeRemaining domains via parity test batches

Round 8 baseline (2026-07-01) โ€” adjacent / ops closure โ€‹

DeliverableStatus
Admin convergence panel on contacts listFlutter _ConvergenceBar + React PartyConvergenceHealthBar
Ops runbookCONTACTS_UNIFIED.md โ€” production monitoring checklist
React dataQuality.* convergence keysAdded to public/locales/{ar,en}/translation.json (parity with Flutter)
cross_repo_label_parity_test+ contacts segments, classification, org sectors, convergence labels
Network CRM gateAlready empty in kV1HiddenRoutes; parity doc current โ€” on-device QA only
DuplicateReview deep linkReact ?tab=clients opens Clients merge tab

Verification (Round 8) โ€‹

ToolResult
npm run i18n-check (aldilaijanre)โœ… Pass โ€” 24,191 AR/EN keys in sync
cross_repo_label_parity_testโœ… Pass โ€” contacts segments, classification, org sectors, convergence labels
party_detail_visibility_test.dartโœ… Pass
npm run typecheck (aldilaijanre)โœ… Pass โ€” 0 errors vs baseline
Vitest party/search/admin/visibilityโœ… Pass โ€” 10 tests
flutter analyze individuals listโœ… Clean after unawaited(context.pushโ€ฆ) fix

P2 closure (2026-07-01) โ€‹

ItemStatus
Legacy UnifiedPersons / BuyersList pagesRemoved; routes already redirect to /clients
Flutter org editOrganizationFormScreen + PartyEditScreen dispatcher
CRM actions on party 360Flutter picker on brokerage/valuation/activity; React QuickInteractionButton
Widget testsparty_detail_screen_test, duplicate_review_screen_test
Supabase type regenDeferred โ€” run npx supabase gen types from Linux/macOS (Windows libuv blocker)
Seeded E2E contactsListโ†’detail still skip when empty; admin/persons redirect test added
Network CRM on-device QAManual โ€” see docs/DEVICE_QA_CHECKLIST.md

Aldilaijan & Khobara Real Estate Platform