Skip to content

CP-14851: i18n extraction tooling (i18next-cli + ast-grep fallback) - #4009

Open
ruijia1in wants to merge 11 commits into
mainfrom
cp-14851
Open

CP-14851: i18n extraction tooling (i18next-cli + ast-grep fallback)#4009
ruijia1in wants to merge 11 commits into
mainfrom
cp-14851

Conversation

@ruijia1in

@ruijia1in ruijia1in commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

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 main via #3999).

What this adds (tooling-only — no product strings externalized here; that's the later sweep ticket):

  • i18next.config.tsi18next-cli 1.66.2 config aligned to the runtime (app/i18n/index.ts): single translation namespace, flat natural-English keys, keySeparator/nsSeparator: false. extract scans app/** and maintains the EN catalog; types generates TS definitions. removeUnusedKeys: false so the manually-seeded catalog isn't wiped while there are ~zero t() consumers yet.
  • npm scriptsi18n:extract, i18n:types, i18n:instrument, i18n:check (CI staleness gate via extract --ci).
  • TS type-safety — generated app/i18n/@types/resources.d.ts + a declare module 'i18next' augmentation, so t() keys are compile-checked (unknown keys are a type error).
  • ast-grep fallback rules (sgconfig.yml + scripts/i18n/rules/) — report-only flags for the patterns i18next-cli instrument structurally misses: string-valued JSX props (title/label/placeholder/message/description), showSnackbar/showAlert args, and accessibilityLabel/accessibilityHint.
  • Runtime fixreturnEmptyString: false in app/i18n/index.ts so 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 Lavamoat allowScripts: false (they work without them).

Validation gate (this ticket's core deliverable): ran instrument on pilot areas receive + 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 for extract + 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 returnEmptyString fallback 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):

# 1. Install + setup must succeed (Lavamoat allow-scripts policy for the new devDeps)
yarn install && yarn setup
#    -> no "@lavamoat/allow-scripts has detected dependencies without configuration"

# 2. Lockfile consistent
yarn install --immutable            # -> no YN0028

# 3. Extraction is non-destructive (seed keys preserved)
yarn core i18n:extract
node -e "const j=require('./packages/core-mobile/app/i18n/locales/en-US/translation.json'); console.log(Object.keys(j).length, ['Settings','Send','Receive','Account'].every(k=>k in j))"
#    -> 4 true

# 4. Types generate + compile; key typing enforced (t('Settings') ok, t('nope') is a compile error)
yarn core i18n:types && yarn core tsc

# 5. CI staleness gate: exits 0 when current; add a t('New') call and re-run -> non-zero
yarn core i18n:check

# 6. ast-grep rules flag missed patterns, report-only (no file edits)
cd packages/core-mobile && ./node_modules/.bin/ast-grep scan -c sgconfig.yml app/new/features/notifications

# 7. i18n unit tests still pass (returnEmptyString change)
yarn core test app/i18n

Jira ticket moved to Testing.

Build Numbers

Checklist

  • I have performed a self-review of my code
  • I have verified the code works
  • I have included screenshots / videos of android and ios (N/A — no UI)
  • I have added testing steps
  • I have added/updated necessary unit tests (i18n foundation tests pass with the runtime change)
  • I have updated the documentation (design doc + report in Obsidian; Jira comment)

Copilot AI review requested due to automatic review settings July 23, 2026 15:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-cli config + workspace scripts for extract, types, and CI staleness checks.
  • Adds ast-grep configuration 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.

Comment thread packages/core-mobile/package.json
Comment thread packages/core-mobile/package.json Outdated
Comment thread packages/core-mobile/app/i18n/index.ts
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

Coverage report ✅

2/2 packages passed thresholds
Thresholds are shown inline against each package baseline.

🟢 @avalabs/core-mobile

St. Category Percentage Covered / Total
🟢 Statements 27.86% (+9.86% vs 18% ▲) 12318/44213
🟢 Branches 23.48% (+11.48% vs 12% ▲) 6033/25687
🟢 Functions 22.13% (+9.13% vs 13% ▲) 2261/10216
🟢 Lines 27.94% (+9.94% vs 18% ▲) 11796/42219

🟢 @avalabs/k2-alpine

St. Category Percentage Covered / Total
🟢 Statements 8.49% (+6.49% vs 2% ▲) 304/3578
🟢 Branches 7.90% (+6.90% vs 1% ▲) 172/2177
🟢 Functions 4.99% (+3.99% vs 1% ▲) 41/821
🟢 Lines 7.82% (+5.82% vs 2% ▲) 257/3283
Artifacts and threshold sources
  • @avalabs/core-mobile: summary core-mobile/coverage/coverage-summary.json, thresholds core-mobile/coverage-thresholds.json
  • @avalabs/k2-alpine: summary k2-alpine/coverage/coverage-summary.json, thresholds k2-alpine/coverage-thresholds.json

Source run: Mobile PR

Copilot AI review requested due to automatic review settings July 23, 2026 16:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 22 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 23, 2026 16:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 23 changed files in this pull request and generated 2 comments.

Comment thread packages/core-mobile/app/i18n/index.test.ts Outdated
Comment thread packages/core-mobile/i18next.config.ts Outdated

@B0Y3R-AVA B0Y3R-AVA left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-prop rule will flag non-user-facing title/label/message/description strings too (analytics payloads, dev-only props) — acceptable noise for report-only, just calibrating expectations for the sweep.
  • Verified @swc/core genuinely arrives via i18next-cli / i18next-resources-for-ts in 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.

Comment thread packages/core-mobile/scripts/i18n/rules/snackbar-alert-args.yml
Comment thread packages/core-mobile/app/i18n/@types/i18next.d.ts
Comment thread packages/core-mobile/i18next.config.ts Outdated
Comment thread packages/core-mobile/package.json Outdated
Comment thread packages/core-mobile/package.json
Copilot AI review requested due to automatic review settings July 23, 2026 18:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 24 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 23, 2026 18:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 24 changed files in this pull request and generated 1 comment.

Comment on lines +42 to +46
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__')
@ruijia1in
ruijia1in requested a review from B0Y3R-AVA July 23, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants