i18n Coverage Audit — Ideony Monorepo
i18n Coverage Audit — Ideony Monorepo
Section titled “i18n Coverage Audit — Ideony Monorepo”Date: 2026-04-20
Scope: apps/mobile/ (Expo/React Native, i18next) + apps/api/src/ (NestJS, nestjs-i18n)
Locales: IT (default) + EN
1. Mobile — Missing t() Wraps
Section titled “1. Mobile — Missing t() Wraps”Raw user-visible strings not wrapped in t(). Fallback strings (2nd arg to t()) are excluded — those are acceptable defaults.
| File | Line | Raw String | Suggested Key |
|---|---|---|---|
app/(welcome)/continue.tsx | 80 | "oppure" (Italian divider) | common.or_divider |
app/(welcome)/continue.tsx | 87 | placeholder="Email" | auth.email_placeholder |
app/(welcome)/continue.tsx | 100 | accessibilityLabel="Email" | auth.email_placeholder |
app/(welcome)/continue.tsx | 157 | placeholder="000000" | auth.otp_placeholder |
app/(welcome)/continue.tsx | 169 | accessibilityLabel="OTP code" | auth.otp_accessibility |
components/chrome/Header.tsx | 28 | accessibilityLabel="Notifications" | common.notifications |
components/chrome/Header.tsx | 38 | accessibilityLabel="Profile avatar" | common.profile_avatar |
components/professional/HeroCarousel.tsx | 84 | accessibilityLabel="Indietro" (Italian!) | common.go_back |
components/professional/HeroCarousel.tsx | 95 | accessibilityLabel="Condividi" (Italian!) | common.share |
components/AvailabilityEditor.tsx | 169 | placeholder="09:00" | calendar.time_start_placeholder |
components/AvailabilityEditor.tsx | 180 | placeholder="18:00" | calendar.time_end_placeholder |
app/(professional)/onboarding/profile.tsx | 163 | placeholder="0" | (numeric — low priority) |
app/(professional)/onboarding/pricing.tsx | 238 | placeholder="25" | (numeric — low priority) |
app/(professional)/onboarding/pricing.tsx | 278 | placeholder="80" | (numeric — low priority) |
Critical: HeroCarousel.tsx hardcodes Italian strings — will always display Italian regardless of user locale.
2. Mobile — Dead Keys (defined but never referenced)
Section titled “2. Mobile — Dead Keys (defined but never referenced)”Keys present in lib/i18n/en.json with no t("ns.key") usage found in source.
Note: a thorough dead-key scan requires exhaustive grep of all key paths. The following are confirmed dead after cross-referencing all
t()call sites found inapp/**/*.tsxandcomponents/**/*.tsx.
| Namespace | Key(s) | Notes |
|---|---|---|
bookings | empty_title, empty_subtitle | Code calls bookings.emptyTitle / bookings.emptySubtitle (camelCase) — snake_case versions unreachable |
sos | button_label | No component calls t("sos.button_label") |
home | greeting_anonymous | No call site found |
professional_card | entire section | No t("professional_card.*") calls found in scanned files — verify if used elsewhere |
3. Mobile — Undefined Keys Referenced
Section titled “3. Mobile — Undefined Keys Referenced”Keys called via t() that do not exist in lib/i18n/en.json. These silently render the key string at runtime.
SOS module (7 keys)
Section titled “SOS module (7 keys)”| File | Key |
|---|---|
app/sos/index.tsx | sos.describe_problem_placeholder |
app/sos/[id]/cancelled.tsx | sos.no_candidates_title |
app/sos/[id]/cancelled.tsx | common.go_home |
app/sos/[id]/complete.tsx | common.go_home |
components/sos/CandidateCard.tsx | sos.etaMinutes |
components/sos/CandidateCard.tsx | sos.selectCandidate |
components/sos/CandidateCard.tsx | sos.min |
SOS DispatchStatusBar (5 keys)
Section titled “SOS DispatchStatusBar (5 keys)”| File | Key |
|---|---|
components/sos/DispatchStatusBar.tsx | sos.statusSearching |
components/sos/DispatchStatusBar.tsx | sos.statusDispatching |
components/sos/DispatchStatusBar.tsx | sos.statusDispatchingWait |
components/sos/DispatchStatusBar.tsx | sos.statusWaitingAccept |
components/sos/DispatchStatusBar.tsx | sos.statusTracking |
Bookings (naming mismatch — 3 keys)
Section titled “Bookings (naming mismatch — 3 keys)”| File | Key (called) | Key (in JSON) |
|---|---|---|
components/empty/BookingsEmpty.tsx | bookings.emptyTitle | bookings.empty_title |
components/empty/BookingsEmpty.tsx | bookings.emptySubtitle | bookings.empty_subtitle |
components/empty/BookingsEmpty.tsx | bookings.emptyCta | (absent — no snake_case either) |
Professional profile (5 keys)
Section titled “Professional profile (5 keys)”| File | Key |
|---|---|
components/professional/StickyBookBar.tsx | professional_profile.starting_price |
components/professional/StickyBookBar.tsx | professional_profile.book_cta |
components/professional/SectionTabs.tsx | professional_profile.tab_reviews |
components/professional/SectionTabs.tsx | professional_profile.tab_certifications |
components/professional/SectionTabs.tsx | professional_profile.tab_area |
Review screen (2 keys)
Section titled “Review screen (2 keys)”| File | Key |
|---|---|
app/review/[bookingId].tsx | review.hero_subtitle |
app/review/[bookingId].tsx | review.comment_placeholder_detail |
Consumer home (4 keys)
Section titled “Consumer home (4 keys)”| File | Key |
|---|---|
app/(consumer)/index.tsx | home.heroTitle |
app/(consumer)/index.tsx | home.heroSubtitle |
app/(consumer)/index.tsx | home.categoriesTitle |
app/(consumer)/index.tsx | home.searchPlaceholder |
Total mobile undefined keys: 26
4. API — Missing t() Wraps
Section titled “4. API — Missing t() Wraps”All user-facing error messages in apps/api/src/ should use t(key, fallback) via src/common/i18n.helper.ts. The following modules had hardcoded English strings thrown directly without t():
Scan found all error throws use
t()via the helper — no bare hardcoded error strings identified in scanned modules. This section passes.
5. API — Dead Keys
Section titled “5. API — Dead Keys”Keys in apps/api/src/i18n/en/common.json with no t("key") call site found.
| Section | Key | Notes |
|---|---|---|
notification | entire section (6 keys) | sos_request, booking_confirmed, booking_cancelled, payment_received, review_prompt, service_reminder — no t("notification.*") calls found in API source |
booking | profile_exists | No t("booking.profile_exists") call found |
onboarding | p_iva_required | No t("onboarding.p_iva_required") call found (may be used — verify) |
6. API — Undefined Keys Referenced
Section titled “6. API — Undefined Keys Referenced”The t() helper in src/common/i18n.helper.ts prepends common. to keys. JSON uses snake_case; some call sites use camelCase → always falls back to English.
camelCase / snake_case mismatches (key exists in JSON but under different casing)
Section titled “camelCase / snake_case mismatches (key exists in JSON but under different casing)”| File | Key called | Key in JSON | Effect |
|---|---|---|---|
modules/credentials/credentials.service.ts | credential.notFound | credential.not_found | Always English fallback |
Keys entirely absent from JSON (missing sections)
Section titled “Keys entirely absent from JSON (missing sections)”| File | Key(s) called | Missing section |
|---|---|---|
modules/quotes/quotes.service.ts | quotes.not_found, quotes.forbidden, quotes.accepted_only, quotes.already_responded, quotes.professional_mismatch, quotes.invalid_status, quotes.consumer_only, quotes.booking_not_found | quotes section absent |
modules/verification/verification.service.ts | verification.profile_not_found, verification.not_found, verification.already_reviewed | verification section absent |
modules/sos/sos.service.ts | sos.no_pricing | Key absent from sos section |
modules/onboarding/onboarding.service.ts | onboarding.user_not_found | Key absent from onboarding section |
modules/onboarding/onboarding.service.ts | onboarding.portfolio_image_not_found | Key absent |
modules/onboarding/onboarding.service.ts | onboarding.portfolio_image_forbidden | Key absent |
modules/credentials/credentials.service.ts | credential.notPending | Key absent |
Total API undefined keys: 15 keys across 4 modules
Critical: entire quotes (8 keys) and verification (3 keys) sections missing — all errors in these modules display English only regardless of user locale.
7. Parity Gaps — EN ↔ IT
Section titled “7. Parity Gaps — EN ↔ IT”Mobile (lib/i18n/en.json vs lib/i18n/it.json)
Section titled “Mobile (lib/i18n/en.json vs lib/i18n/it.json)”Keys present in EN but missing from IT:
| Namespace | Missing Keys |
|---|---|
auth | welcome_heading, continue_cta, continue_with_apple, continue_with_google, continue_with_facebook, otp_title, verify_cta, new_user_prompt, register_link |
9 keys missing from IT mobile JSON. The entire authentication flow will display English strings when the device is set to Italian.
Keys present in IT but missing from EN: none identified.
API (src/i18n/en/common.json vs src/i18n/it/common.json)
Section titled “API (src/i18n/en/common.json vs src/i18n/it/common.json)”IT and EN API files are fully parified — identical key sets. No gaps.
8. Coverage Summary
Section titled “8. Coverage Summary”Mobile
Section titled “Mobile”| Category | Count | Notes |
|---|---|---|
| Undefined keys (silent fallback to key string) | 26 | SOS, home, review, professional_profile, bookings |
Missing t() wraps (raw strings) | 14 | 2 critical Italian hardcodes |
| IT parity gaps | 9 | Entire auth section missing from IT |
| Dead keys (defined, unreferenced) | ~6 | bookings snake_case, sos.button_label |
| Mobile i18n health | Poor | SOS feature and professional profile ~0% translated at runtime |
| Category | Count | Notes |
|---|---|---|
| Undefined keys | 15 | quotes + verification sections entirely absent |
| camelCase mismatches | 1 | credential.notFound |
| Dead keys | ~7 | notification section + isolated keys |
| IT parity gaps | 0 | Fully parified |
| API i18n health | Partial | Core booking/auth/review errors translate correctly; quotes + verification always English |
Priority Order for Fixes
Section titled “Priority Order for Fixes”- [P0] Add
quotesandverificationsections to API JSON (all errors in these modules are untranslated) - [P0] Add 12 missing SOS keys to mobile EN+IT JSON (
statusXxx,etaMinutes,selectCandidate,min,no_candidates_title,describe_problem_placeholder) - [P0] Add
common.go_hometo mobile EN+IT JSON - [P1] Fix
bookings.emptyTitle/Subtitle/Cta— either rename JSON keys to camelCase or update component to use snake_case; addemptyCta - [P1] Add 5 missing
professional_profilekeys (starting_price,book_cta,tab_*) - [P1] Add 9 missing
authkeys to IT JSON (parity gap) - [P1] Add
review.hero_subtitleandreview.comment_placeholder_detailto EN+IT JSON - [P1] Add 4 missing
homecamelCase keys (heroTitle, etc.) to EN+IT JSON — or rename existing snake_case keys - [P2] Fix
credential.notFound→credential.not_foundin API service call - [P2] Add missing API onboarding keys (
user_not_found,portfolio_image_not_found,portfolio_image_forbidden) andsos.no_pricing - [P2] Wrap raw strings in
continue.tsx,Header.tsx,AvailabilityEditor.tsx - [P3] Replace hardcoded Italian
accessibilityLabelinHeroCarousel.tsx