Skip to content

refactor(i18n): harden locale audit guardrails#957

Merged
limityan merged 2 commits into
GCWing:mainfrom
limityan:yanzhn/i18n-p0-hardening
May 30, 2026
Merged

refactor(i18n): harden locale audit guardrails#957
limityan merged 2 commits into
GCWing:mainfrom
limityan:yanzhn/i18n-p0-hardening

Conversation

@limityan
Copy link
Copy Markdown
Collaborator

@limityan limityan commented May 30, 2026

Summary

  • add AST-backed i18n audit coverage for Web UI hook-relative keys, array-namespace useI18n / useTranslation keys, and synchronous i18nService keys
  • make stale literal fallback baseline entries fail audit so removed fallback debt must be deleted from the checked-in budget
  • add an exact per-file/key allowlist for existing literal i18next defaultValue fallback debt and block new unbudgeted fallback copy
  • fix generated i18n contract --check to ignore CRLF/LF-only differences and make audit TypeScript dependency failures actionable
  • move newly detected missing Web UI keys into en-US, zh-CN, and zh-TW resources, then remove the corresponding literal defaultValue fallbacks
  • deep-clean confirmed unused i18n keys across Web UI, mobile-web, and installer resources after checking static references, namespace-relative usage, metadata indirection, dynamic key patterns, and backend/frontend bridge mappings
  • keep installer errors.installPath.* keys because Rust emits INSTALL_PATH::snake_case and the frontend maps those codes dynamically to errors.installPath.camelCase
  • document the updated i18n resource layering, override priority, key naming, shared-term usage, safe key-deletion rules, quality-governance categories, l10n review expectations, and no-checked-in execution-plan rule
  • refresh the Web UI i18n README entry points so they defer to the shared architecture/development docs and describe the current three-locale, lazy-namespace workflow
  • remove Windows absolute-path examples from installer locale copy so repository hygiene can scan committed i18n resources without false local-path violations

Verification

  • pnpm run check:repo-hygiene
  • pnpm run i18n:contract:test
  • pnpm run i18n:audit
  • pnpm --dir src/web-ui run test:run src/infrastructure/i18n/core/I18nService.test.ts
  • pnpm run type-check:web
  • pnpm --dir src/mobile-web run type-check
  • pnpm --dir BitFun-Installer run type-check
  • git diff --check gcwing/main...HEAD

Latest documentation-only update:

  • pnpm run i18n:audit
  • git diff --check gcwing/main...HEAD

Risk / behavior notes

  • Locale deletion risk is mainly dynamic-key usage. This PR keeps known dynamic bridge keys, especially installer install-path validation errors, and only removes keys that remained unreferenced after static, namespace-relative, metadata, relay/mobile/installer, and backend mapping checks.
  • Shared term consolidation is intentionally documented but not fully migrated here, because replacing repeated product and feature labels across call sites has a wider review surface than unused-key deletion.
  • The literal fallback baseline intentionally preserves existing debt as an exact allowlist; new static fallback copy must either move into locale resources or deliberately update the allowlist with justification. Stale baseline reductions now fail the audit and must be removed in the same change.
  • The hook static-key audit is a lightweight AST pass, not a full type-aware scope analyzer. It covers current useI18n/useTranslation/i18nService patterns, including array namespace aliases, and is locked by contract behavior tests.
  • Documentation updates intentionally avoid committing process-only execution plans; durable rules are kept in architecture/development docs only.

Follow-up items

  1. P0: add a machine-readable unused-key report that distinguishes confirmed unused keys from dynamic-key candidates, with explicit allowlist entries for sanctioned key factories such as installer error-code mapping.
  2. P1: migrate stable product and feature names to shared authoritative terms, then replace repeated literals or duplicated locale values with direct shared-key reads or interpolation parameters.
  3. P1: consolidate generic actions, statuses, and common labels into the smallest appropriate surface common namespace while keeping feature-specific copy in owner namespaces when the wording has different product meaning.
  4. P1: add namespace ownership guidance for large feature areas and split large lazy namespaces when one feature file starts mixing unrelated pages or workflows.
  5. P2: continue reducing hardcoded source-copy and literal-fallback budgets across Web UI, mobile-web, and installer without increasing bootstrap i18n payloads.
  6. P2: strengthen dynamic-key coverage by registering approved key factories in the audit contract instead of relying on ad hoc scanner behavior.
  7. P2: consider development-only missing-key telemetry or stricter runtime diagnostics for dynamic paths that cannot be proven statically.

@limityan limityan force-pushed the yanzhn/i18n-p0-hardening branch 2 times, most recently from 9cb286e to 10a3397 Compare May 30, 2026 02:48
@limityan limityan force-pushed the yanzhn/i18n-p0-hardening branch from 10a3397 to 45a7ccb Compare May 30, 2026 03:21
@limityan
Copy link
Copy Markdown
Collaborator Author

Related tracking issue: #959. This link is for i18n/l10n module context only and should not close the issue when this PR is merged or closed.

@limityan limityan merged commit 8a2f3c6 into GCWing:main May 30, 2026
4 checks passed
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.

1 participant