Skip to content

fix(desktop): onboarding i18n audit + locale-reactive switching#39

Merged
hqhq1025 merged 2 commits intomainfrom
wt/fix-i18n-onboarding
Apr 18, 2026
Merged

fix(desktop): onboarding i18n audit + locale-reactive switching#39
hqhq1025 merged 2 commits intomainfrom
wt/fix-i18n-onboarding

Conversation

@hqhq1025
Copy link
Copy Markdown
Collaborator

Summary

  • All three onboarding screens (Welcome / PasteKey / ChooseModel) now use useT() — they were previously 100% hardcoded English with no i18n wiring at all
  • All user-visible strings have correct i18n keys in both en and zh-CN locales (~30 net-new keys added, old placeholder stubs replaced with accurate copy)
  • getErrorHint and getValidationErrorMessage in PasteKey now accept t() so translated error messages are returned at render time, not at module load
  • Onboarding re-renders immediately when the LanguageToggle (already present in the onboarding header) is clicked

Compatibility, upgradeability, no bloat, elegance

  • Compatibility ✅ — no API or storage schema changes
  • Upgradeability ✅ — only additive JSON key additions; no renames
  • No bloat ✅ — zero new dependencies
  • Elegance ✅ — follows the exact same useT() hook pattern used in every other component

i18n audit findings

Hardcoded strings fixed in this PR:

  • Welcome.tsx: title, subtitle, 3x PathButton title+subtitle pairs, "where to get a key" label
  • PasteKey.tsx: title, description, preset label/placeholder/hint, API key label, base URL label, advanced toggle/description, all status messages (idle/detecting/validating/ok), all error messages, connection-test button/states, back/continue buttons
  • ChooseModel.tsx: title, description, primary/fast model picker labels and hints (both standard and free-tier variants), custom base URL note, cost notes, back/saving/finish buttons

Out of scope (pre-existing, no change): Settings.tsx has hardcoded <SectionTitle> strings but no useT() at all — tracked separately.

Test plan

  • Launch app → onboarding shows English by default
  • Click the language toggle (EN / ZH globe icon in onboarding header) → all visible text switches to Chinese immediately (no page reload)
  • Click toggle back → reverts to English
  • Complete onboarding → app opens normally
  • pnpm -r test → all 11 i18n tests pass, including 2 new onboarding locale-switching tests

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Findings

  • [Major] Validation effect re-runs on every render due to unstable t dependency — this can repeatedly call provider detection/key validation and thrash UI state, causing unnecessary network load and racey UX. Evidence: apps/desktop/src/renderer/src/onboarding/PasteKey.tsx:158 adds t to the dependency list, while useT() currently returns a new function each render.
    Suggested fix:
    // packages/i18n/src/index.ts
    import { useCallback } from 'react';
    
    export function useT(): (key: string, options?: Record<string, unknown>) => string {
      const { t } = useTranslation();
      return useCallback((key, options) => t(key, options ?? {}) as string, [t]);
    }

Summary

  • Review mode: initial
  • 1 issue found (Major): onboarding validation effect dependency now causes repeated effect execution.
  • Context docs check: docs/VISION.md and docs/PRINCIPLES.md are Not found in repo/docs in this checkout.
  • Residual testing gap: no component-level test proving onboarding validation requests are not retriggered on no-op re-renders.

Testing

  • Not run (automation): pnpm is unavailable in this runner, so Vitest/Playwright could not be executed here.

open-codesign Bot


return () => window.clearTimeout(handle);
}, [trimmed, trimmedBaseUrl]);
}, [trimmed, trimmedBaseUrl, t]);
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.

is included in this effect dependency list, but currently returns a new function each render. That makes this effect fire repeatedly even when / are unchanged, which can re-trigger provider detection + key validation in a loop. Please stabilize (e.g., ) or remove this function dependency and depend on a stable locale signal instead.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Findings

  • No actionable issues found in added/modified lines.

Summary

  • Review mode: follow-up after new commits
  • No new issues found in the latest head diff.
  • Residual risk/testing gap: changes are covered at i18n-key level, but no component-level test verifies onboarding validation behavior on locale switch/re-render.
  • Context note: docs/VISION.md and docs/PRINCIPLES.md are Not found in repo/docs in this checkout.

Testing

  • Not run (automation)

open-codesign Bot

All three onboarding screens (Welcome, PasteKey, ChooseModel) now use
useT() so they re-render immediately when the user toggles the language
toggle in the onboarding header.

- Welcome.tsx: title, subtitle, path-button labels/subtitles, "where to
  get a key" label all go through t()
- PasteKey.tsx: title, description, all field labels, preset hint,
  connection-test button/status, error messages, back/continue buttons
  all go through t(); getErrorHint and getValidationErrorMessage now
  accept t() so they can return translated strings at call time
- ChooseModel.tsx: title, description, model-picker labels/hints,
  cost notes, custom base URL note, back/saving/finish buttons all
  go through t()
- en.json / zh-CN.json: replaced the placeholder stubs with full,
  accurate keys matching the actual UI copy; added ~30 new keys
  (statusIdle, statusDetecting, statusValidating, statusOk, error codes,
  advanced toggle, preset placeholder, apiKey label, baseUrl label, etc.)
- packages/i18n/src/i18n.test.ts: added two new describe blocks that
  assert onboarding keys return correct English and Chinese strings
  after setLocale() — covers Welcome, PasteKey, and ChooseModel

Signed-off-by: hqhq1025 <[email protected]>
react-i18next's t identity is not stable across renders. When useT()'s
returned function was used in useEffect deps (e.g. PasteKey validation
effect), the effect re-ran every render — repeatedly triggering provider
detection and key validation. Wrap the return in useCallback keyed on
i18n.language so identity stays stable until the locale changes.

Signed-off-by: hqhq1025 <[email protected]>
@hqhq1025 hqhq1025 force-pushed the wt/fix-i18n-onboarding branch from 58bdfa5 to 0f25bc3 Compare April 18, 2026 18:12
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Findings

  • No actionable issues found in added/modified lines.

Summary

  • Review mode: follow-up after new commits
  • No new issues found in the latest head diff.
  • Constraint checks on changed lines: no direct provider SDK imports, no new dependencies/licenses, no new silent-fallback regression found, and no new hardcoded color/font-size literals were introduced.
  • Not found in repo/docs: docs/VISION.md, docs/PRINCIPLES.md, docs/RESEARCH_QUEUE.md.
  • Residual risk/testing gap: added tests validate locale keys/values, but there is still no component-level test covering onboarding locale-toggle behavior with connection-test status transitions.

Testing

  • Not run (automation)

open-codesign Bot

@hqhq1025 hqhq1025 merged commit 8f53dcb into main Apr 18, 2026
6 checks passed
@hqhq1025 hqhq1025 deleted the wt/fix-i18n-onboarding branch April 18, 2026 18:19
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