fix(desktop): localize update fetch-failure message on Windows#1088
fix(desktop): localize update fetch-failure message on Windows#1088teddyli18000 wants to merge 1 commit intonexu-io:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses a desktop i18n UX issue on Windows by normalizing fetch/network-related auto-update errors so localized UIs (notably zh-CN) don’t surface the raw English "fetch failed" string in update failure notifications.
Changes:
- Exported
normalizeUpdateErrorMessagefrom the desktop auto-update hook to enable direct regression testing. - Added normalization for fetch-related failure messages (
fetch failed,failed to fetch,NetworkError ... fetch) mapping them to localized, user-friendly strings. - Added Vitest regression tests covering both normal updates and
local-test-feedupdate experiences.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| apps/desktop/src/hooks/use-auto-update.ts | Exposes and extends update error normalization to localize fetch/network failures. |
| tests/desktop/update-error-message-normalization.test.ts | Adds regression tests ensuring fetch-failure messages are normalized in both update experiences. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| describe("update error message normalization", () => { | ||
| it("normalizes fetch failures in normal update mode", () => { | ||
| const result = normalizeUpdateErrorMessage("fetch failed", "normal"); | ||
| expect(result).not.toMatch(/fetch failed/i); | ||
| }); | ||
|
|
||
| it("normalizes fetch failures in local test feed mode", () => { | ||
| const result = normalizeUpdateErrorMessage( | ||
| "TypeError: fetch failed", | ||
| "local-test-feed", | ||
| ); | ||
| expect(result).not.toMatch(/fetch failed/i); | ||
| }); |
There was a problem hiding this comment.
These assertions only check that the output no longer contains the substring "fetch failed", which would still pass if the function returns a different raw English fetch-related message (e.g., "NetworkError when attempting to fetch…") or an empty/placeholder string. Consider asserting the exact expected normalized message (or a stable key phrase), and explicitly controlling the locale (e.g., temporarily set/define navigator.language to en-US and zh-CN) so the test validates the localized output deterministically.
| describe("update error message normalization", () => { | |
| it("normalizes fetch failures in normal update mode", () => { | |
| const result = normalizeUpdateErrorMessage("fetch failed", "normal"); | |
| expect(result).not.toMatch(/fetch failed/i); | |
| }); | |
| it("normalizes fetch failures in local test feed mode", () => { | |
| const result = normalizeUpdateErrorMessage( | |
| "TypeError: fetch failed", | |
| "local-test-feed", | |
| ); | |
| expect(result).not.toMatch(/fetch failed/i); | |
| }); | |
| const withNavigatorLanguage = <T>(language: string, run: () => T): T => { | |
| const originalDescriptor = Object.getOwnPropertyDescriptor( | |
| window.navigator, | |
| "language", | |
| ); | |
| Object.defineProperty(window.navigator, "language", { | |
| configurable: true, | |
| value: language, | |
| }); | |
| try { | |
| return run(); | |
| } finally { | |
| if (originalDescriptor) { | |
| Object.defineProperty(window.navigator, "language", originalDescriptor); | |
| } else { | |
| delete (window.navigator as Navigator & { language?: string }).language; | |
| } | |
| } | |
| }; | |
| describe("update error message normalization", () => { | |
| it("normalizes fetch failures in normal update mode for en-US", () => { | |
| const result = withNavigatorLanguage("en-US", () => | |
| normalizeUpdateErrorMessage("fetch failed", "normal"), | |
| ); | |
| expect(result).toContain("network"); | |
| expect(result).not.toMatch(/fetch failed/i); | |
| }); | |
| it("normalizes fetch failures in normal update mode for zh-CN", () => { | |
| const result = withNavigatorLanguage("zh-CN", () => | |
| normalizeUpdateErrorMessage("fetch failed", "normal"), | |
| ); | |
| expect(result).toContain("网络"); | |
| expect(result).not.toMatch(/fetch failed/i); | |
| }); | |
| it("normalizes fetch failures in local test feed mode for en-US", () => { | |
| const result = withNavigatorLanguage("en-US", () => | |
| normalizeUpdateErrorMessage("TypeError: fetch failed", "local-test-feed"), | |
| ); | |
| expect(result).toContain("local"); | |
| expect(result).toContain("server"); | |
| expect(result).not.toMatch(/fetch failed/i); | |
| }); | |
| it("normalizes fetch failures in local test feed mode for zh-CN", () => { | |
| const result = withNavigatorLanguage("zh-CN", () => | |
| normalizeUpdateErrorMessage("TypeError: fetch failed", "local-test-feed"), | |
| ); | |
| expect(result).toContain("本地"); | |
| expect(result).toContain("服务器"); | |
| expect(result).not.toMatch(/fetch failed/i); | |
| }); |
| it("normalizes fetch failures in local test feed mode", () => { | ||
| const result = normalizeUpdateErrorMessage( | ||
| "TypeError: fetch failed", | ||
| "local-test-feed", | ||
| ); | ||
| expect(result).not.toMatch(/fetch failed/i); | ||
| }); |
There was a problem hiding this comment.
This test also only asserts that "fetch failed" is absent; it doesn't verify the actual user-facing string for the local-test-feed experience or that the output is localized under a zh locale. Strengthen it by forcing the locale and asserting the expected normalized message for both normal and local-test-feed inputs.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
@teddyli18000 👋你好呀~ 我们收到您今天提交了 2 次 Pr,我们非常感激你的贡献 🎉 |
What
Normalize update fetch/network failure errors in the desktop renderer so Chinese users no longer see the raw English string
fetch failedin update failure notifications.Why
Closes #994.
On Windows with zh-CN UI, update failures could surface as mixed-language notifications (
更新失败with rawfetch faileddetail), which is confusing and breaks localization consistency.How
normalizeUpdateErrorMessagefrom the update hook for direct regression testing.fetch failedfailed to fetchNetworkError ... fetchNetwork connection failed while checking for updates. Check your connection and try again.网络连接失败,请检查网络后重试。Affected areas
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpassespnpm generate-typesrun (if API routes/schemas changed)anytypes introduced (useunknownwith narrowing)Screenshots / recordings
Reproduction:
Fixed:
Notes for reviewers
apps/desktop/src/hooks/use-auto-update.tstests/desktop/update-error-message-normalization.test.ts