Conversation
…mptyString:false)
There was a problem hiding this comment.
Pull request overview
Adds the initial i18n string-extraction/tooling pipeline for @avalabs/core-mobile, centered on i18next-cli (extract + type generation) with an ast-grep ruleset to report hardcoded user-facing strings that automated instrumentation may miss. Also adjusts the i18n runtime to treat empty-string translations as missing so non-EN catalogs seeded with "" fall back to English.
Changes:
- Introduces
i18next-cliconfig + workspace scripts forextract,types, and CI staleness checks. - Adds
ast-grepconfiguration and rules for reporting likely user-facing hardcoded strings (JSX props, snackbar/alert args, accessibility labels). - Updates i18n runtime behavior (
returnEmptyString: false) and commits updated locale catalogs + generated TS resource typings.
Reviewed changes
Copilot reviewed 18 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Adds lockfile entries for i18next-cli, @ast-grep/cli, and their transitive deps. |
| packages/core-mobile/package.json | Adds i18n scripts and devDependencies (i18next-cli, @ast-grep/cli), plus Lavamoat allow-scripts entries. |
| packages/core-mobile/i18next.config.ts | New i18next-cli configuration (locales, extract/output behavior, types output). |
| packages/core-mobile/sgconfig.yml | New ast-grep config pointing to rule directory. |
| packages/core-mobile/scripts/i18n/rules/snackbar-alert-args.yml | New ast-grep rule flagging hardcoded strings in showSnackbar/showAlert calls. |
| packages/core-mobile/scripts/i18n/rules/jsx-string-props.yml | New ast-grep rule flagging hardcoded strings in common JSX props. |
| packages/core-mobile/scripts/i18n/rules/accessibility-labels.yml | New ast-grep rule flagging hardcoded accessibilityLabel/accessibilityHint. |
| packages/core-mobile/app/i18n/index.ts | Runtime change: treat "" as missing via returnEmptyString: false. |
| packages/core-mobile/app/i18n/@types/resources.d.ts | Generated TS resource types from the EN catalog. |
| packages/core-mobile/app/i18n/@types/i18next.d.ts | Module augmentation to bind generated resources to i18next typing. |
| packages/core-mobile/app/i18n/locales/en-US/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/zh-CN/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/zh-TW/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/fr-FR/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/de-DE/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/hi-IN/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/ja-JP/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/ko-KR/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/ru-RU/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/es-ES/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
| packages/core-mobile/app/i18n/locales/tr-TR/translation.json | Updates/extends seed translation catalog (adds Account, reorders keys). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Coverage report ✅2/2 packages passed thresholds 🟢 @avalabs/core-mobile
🟢 @avalabs/k2-alpine
Artifacts and threshold sources
Source run: Mobile PR |
B0Y3R-AVA
left a comment
There was a problem hiding this comment.
Adversarial review (two independent passes, findings verified against i18next-cli v1.66.2 source, this branch, and the yarn.lock diff). No blockers for a tooling-only PR — overall this is in good shape and the config comments match upstream behavior (defaultValue arg order, extract --ci, instrument --dry-run, sorted/idempotent extraction all check out). Four substantive comments inline (.ts files invisible to the snackbar rule, missing nsSeparator in the type augmentation, types.output collision quirk, CI gate coverage/wiring), plus a couple of minor notes.
Minor (no inline anchor):
- The
i18n-jsx-string-proprule will flag non-user-facingtitle/label/message/descriptionstrings too (analytics payloads, dev-only props) — acceptable noise for report-only, just calibrating expectations for the sweep. - Verified
@swc/coregenuinely arrives viai18next-cli/i18next-resources-for-tsin the lockfile (real new transitive dep, and it does ship a postinstall), so an allowScripts entry is needed — see inline note on the path naming.
| i18n.addResource('en-US', 'translation', 'Send', '__EN_FALLBACK__') | ||
| i18n.addResource('es-ES', 'translation', 'Send', '') | ||
| // returnEmptyString:false → the empty es-ES value is treated as missing and | ||
| // falls back to the en-US value instead of rendering blank. | ||
| expect(i18n.t('Send')).toBe('__EN_FALLBACK__') |
Description
Ticket: CP-14851 (part of epic CP-14646; discovery CP-14647)
Establishes the automated string-extraction tooling for the i18n sweep, staying inside the i18next/Crowdin ecosystem (parity-safe). Builds on the runtime foundation from CP-14849 (now on
mainvia #3999).What this adds (tooling-only — no product strings externalized here; that's the later sweep ticket):
i18next.config.ts— i18next-cli 1.66.2 config aligned to the runtime (app/i18n/index.ts): singletranslationnamespace, flat natural-English keys,keySeparator/nsSeparator: false.extractscansapp/**and maintains the EN catalog;typesgenerates TS definitions.removeUnusedKeys: falseso the manually-seeded catalog isn't wiped while there are ~zerot()consumers yet.i18n:extract,i18n:types,i18n:instrument,i18n:check(CI staleness gate viaextract --ci).app/i18n/@types/resources.d.ts+ adeclare module 'i18next'augmentation, sot()keys are compile-checked (unknown keys are a type error).sgconfig.yml+scripts/i18n/rules/) — report-only flags for the patterns i18next-cliinstrumentstructurally misses: string-valued JSX props (title/label/placeholder/message/description),showSnackbar/showAlertargs, andaccessibilityLabel/accessibilityHint.returnEmptyString: falseinapp/i18n/index.tsso not-yet-translated keys (seeded as""for Crowdin) fall back to English instead of rendering blank.Dependencies introduced:
i18next-cli+@ast-grep/cli(both devDependencies, not shipped in the app bundle). Their install scripts are disabled via LavamoatallowScripts: false(they work without them).Validation gate (this ticket's core deliverable): ran
instrumenton pilot areasreceive+notifications(throwaway, reverted) → 59.3% hit-rate, 45.8% false-positive rate, plus behavior-breaking string corruption and foundation-duplicating scaffolding. Decision: fall back to ast-grep/ts-morph for the wrap; retain i18next-cli forextract+ types (identical JSON output → Crowdin parity holds). Full report in the ticket comment + design doc.Screenshots/Videos
N/A — tooling-only change with no UI/runtime surface (the only runtime touch is the
returnEmptyStringfallback config, which has no visible effect until the sweep adds translatable keys).Testing
Dev Testing — tooling-only, so no in-app QA. Verify from a clean checkout of this branch (monorepo root unless noted):
Jira ticket moved to Testing.
Build Numbers
Checklist