[PR #1025] [MERGED] feat(i18n): add zh-TW locale and sync 74 missing keys in zh-CN (#1017) #1148

Closed
opened 2026-05-06 12:35:20 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/maziggy/bambuddy/pull/1025
Author: @Minidoracat
Created: 4/18/2026
Status: Merged
Merged: 4/19/2026
Merged by: @maziggy

Base: devHead: feature/i18n-zh-tw-and-zh-cn-sync


📝 Commits (5)

  • 4d12f10 fix(i18n): sync zh-CN to match en structure
  • 53fafef feat(i18n): add zh-TW locale and enforce 3-way parity
  • 969e035 Merge branch 'dev' into feature/i18n-zh-tw-and-zh-cn-sync
  • b378be8 Merge branch 'dev' into feature/i18n-zh-tw-and-zh-cn-sync
  • f17560c Merge branch 'dev' into feature/i18n-zh-tw-and-zh-cn-sync

📊 Changes

5 files changed (+5322 additions, -4 deletions)

View changed files

📝 frontend/package.json (+3 -2)
frontend/scripts/check-i18n-parity.mjs (+174 -0)
📝 frontend/src/i18n/index.ts (+4 -1)
📝 frontend/src/i18n/locales/zh-CN.ts (+80 -1)
frontend/src/i18n/locales/zh-TW.ts (+5061 -0)

📄 Description

Fixes #1017

Summary

  1. Adds frontend/src/i18n/locales/zh-TW.ts — full Traditional Chinese (Taiwan) locale, 4183 leaf keys aligned to en.ts. Uses Taiwan-standard IT terminology (印表機 / 佇列 / 儲存 / 網路 / 檔案 / 韌體 / 守護程式 / API 權杖 / NFC 讀卡機 / IP 位址 / 取消註冊 / 通知提供者).
  2. Syncs frontend/src/i18n/locales/zh-CN.ts with en.ts — 74 missing keys added (covering login.resetPassword, printers.firmwareModal badges, settings.spoolbuddy device management, settings.tabs.spoolbuddy, spoolbuddy.settings system config), plus 1 placeholder bug fix: fileManager.uploadFailed had a stray {{count}} copied from the adjacent zipFilesFailed key; corrected to '上传失败' matching en's 'Upload failed'.
  3. Registers zh-TW in frontend/src/i18n/index.ts — 4 sites: import, resources, supportedLngs, availableLanguages.
  4. Adds frontend/scripts/check-i18n-parity.mjs — TypeScript Compiler API-based 3-way parity gate:
    • leaf-key set equality across en / zh-CN / zh-TW
    • {{placeholder}} set equality per leaf
    • _plural / _one / _other suffix presence + reverse _one guard
    • fails loudly on malformed input (missing export default, parse errors, non-string leaves, unsupported property kinds) rather than silently passing.
  5. Wires check:i18n into test:run in frontend/package.json so the frontend-tests CI job (ci.yml:227 runs npm run test:run) gates future locale drift without any workflow changes.

Commit structure

Two focused commits (can be cherry-picked independently):

  • fix(i18n): sync zh-CN to match en structure — only touches zh-CN.ts
  • feat(i18n): add zh-TW locale and enforce 3-way parityzh-TW.ts + index.ts + check-i18n-parity.mjs + package.json

Verification

Check Result
npx tsc --noEmit 0 errors
npm run lint 0 errors
npm run test:run 97 files / 1407 tests passed + check:i18n green
npm run build exit 0; zh-TW bundle ~40–60 KB gzipped
node scripts/check-i18n-parity.mjs All locales in parity (en / zh-CN / zh-TW), 4183 leaves each
Playwright smoke en / zh-CN / zh-TW login page render correctly
Live Docker deploy smoke Language picker shows 繁體中文 (Chinese (Traditional)); UI renders with Taiwan usage

Screenshots

Settings page with 繁體中文 (Chinese (Traditional)) selected — shows the new option in the language picker and Taiwan-style terminology across navigation, field labels, and action buttons:

Settings page rendered in 繁體中文 Settings page language picker showing 繁體中文 (Chinese (Traditional)) option
  • Extending frontend/src/__tests__/i18n/locales.test.ts to all locales — current test only checks en↔de and uses .size comparison instead of set equality (pre-existing bug). Extending would require fixing drift in de/fr/ja/it/pt-BR first, which is beyond issue #1017.
  • Hardcoded English strings in ArchivesPage.tsx — noticed during smoke test that Archives title, All Printers / All Materials / All Files / Hide Failed / Export / Select / Upload 3MF (lines ~2966, 3147, 3164, 3179, 3206) are not wrapped in t(). Should be tracked as a separate i18n hardcoded-strings issue so they can be wired through all locales.
  • Parity script coverage expansion to de/fr/ja/it/pt-BR (intentionally kept to 3-way to avoid blocking this PR on drift in other locales).

Drift policy

This PR targets upstream/dev at the time of opening. If upstream/dev moves forward during review, I will not rebase this branch — upstream maintainer can merge normally, or I'll open a separate sync PR if conflicts arise. This keeps the diff stable and review-focused.

Documentation

No wiki PR required per CONTRIBUTING.md — adding a UI language is not a new feature, config key, URL, API, or install/upgrade flow change. The availableLanguages array in i18n/index.ts automatically drives the existing language picker in SettingsPage.tsx (two <select> consumers at lines 1339 and 3060) — no UI code changes needed.

Review history

Locale changes reviewed via three rounds of independent Codex review (APPROVED on round 3 after addressing backToLogin phrasing and unifying 提供者 terminology) and multi-agent PR review (code-reviewer / pr-test-analyzer / silent-failure-hunter / comment-analyzer) covering CLAUDE.md compliance, test coverage strategy, silent-failure hardening, and comment accuracy.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/maziggy/bambuddy/pull/1025 **Author:** [@Minidoracat](https://github.com/Minidoracat) **Created:** 4/18/2026 **Status:** ✅ Merged **Merged:** 4/19/2026 **Merged by:** [@maziggy](https://github.com/maziggy) **Base:** `dev` ← **Head:** `feature/i18n-zh-tw-and-zh-cn-sync` --- ### 📝 Commits (5) - [`4d12f10`](https://github.com/maziggy/bambuddy/commit/4d12f10573df96ef27c395b15f7a25f31746aec3) fix(i18n): sync zh-CN to match en structure - [`53fafef`](https://github.com/maziggy/bambuddy/commit/53fafef44906650ea960397141633935deb2a1a5) feat(i18n): add zh-TW locale and enforce 3-way parity - [`969e035`](https://github.com/maziggy/bambuddy/commit/969e035a3c1487c43b9a7ae6b5839932f1700632) Merge branch 'dev' into feature/i18n-zh-tw-and-zh-cn-sync - [`b378be8`](https://github.com/maziggy/bambuddy/commit/b378be82ce0194ccc625d77c195acc80639d1313) Merge branch 'dev' into feature/i18n-zh-tw-and-zh-cn-sync - [`f17560c`](https://github.com/maziggy/bambuddy/commit/f17560ce1ed1d0ad3640bf009ec5cbb2c54f8537) Merge branch 'dev' into feature/i18n-zh-tw-and-zh-cn-sync ### 📊 Changes **5 files changed** (+5322 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `frontend/package.json` (+3 -2) ➕ `frontend/scripts/check-i18n-parity.mjs` (+174 -0) 📝 `frontend/src/i18n/index.ts` (+4 -1) 📝 `frontend/src/i18n/locales/zh-CN.ts` (+80 -1) ➕ `frontend/src/i18n/locales/zh-TW.ts` (+5061 -0) </details> ### 📄 Description Fixes #1017 ## Summary 1. **Adds `frontend/src/i18n/locales/zh-TW.ts`** — full Traditional Chinese (Taiwan) locale, 4183 leaf keys aligned to `en.ts`. Uses Taiwan-standard IT terminology (印表機 / 佇列 / 儲存 / 網路 / 檔案 / 韌體 / 守護程式 / API 權杖 / NFC 讀卡機 / IP 位址 / 取消註冊 / 通知提供者). 2. **Syncs `frontend/src/i18n/locales/zh-CN.ts` with `en.ts`** — 74 missing keys added (covering `login.resetPassword`, `printers.firmwareModal` badges, `settings.spoolbuddy` device management, `settings.tabs.spoolbuddy`, `spoolbuddy.settings` system config), plus 1 placeholder bug fix: `fileManager.uploadFailed` had a stray `{{count}}` copied from the adjacent `zipFilesFailed` key; corrected to `'上传失败'` matching en's `'Upload failed'`. 3. **Registers `zh-TW` in `frontend/src/i18n/index.ts`** — 4 sites: `import`, `resources`, `supportedLngs`, `availableLanguages`. 4. **Adds `frontend/scripts/check-i18n-parity.mjs`** — TypeScript Compiler API-based 3-way parity gate: - leaf-key set equality across en / zh-CN / zh-TW - `{{placeholder}}` set equality per leaf - `_plural` / `_one` / `_other` suffix presence + reverse `_one` guard - fails loudly on malformed input (missing `export default`, parse errors, non-string leaves, unsupported property kinds) rather than silently passing. 5. **Wires `check:i18n` into `test:run`** in `frontend/package.json` so the `frontend-tests` CI job (`ci.yml:227` runs `npm run test:run`) gates future locale drift without any workflow changes. ## Commit structure Two focused commits (can be cherry-picked independently): - `fix(i18n): sync zh-CN to match en structure` — only touches `zh-CN.ts` - `feat(i18n): add zh-TW locale and enforce 3-way parity` — `zh-TW.ts` + `index.ts` + `check-i18n-parity.mjs` + `package.json` ## Verification | Check | Result | |---|---| | `npx tsc --noEmit` | 0 errors | | `npm run lint` | 0 errors | | `npm run test:run` | 97 files / **1407 tests passed** + `check:i18n` green | | `npm run build` | exit 0; zh-TW bundle ~40–60 KB gzipped | | `node scripts/check-i18n-parity.mjs` | All locales in parity (en / zh-CN / zh-TW), 4183 leaves each | | Playwright smoke | en / zh-CN / zh-TW login page render correctly | | Live Docker deploy smoke | Language picker shows `繁體中文 (Chinese (Traditional))`; UI renders with Taiwan usage | ## Screenshots Settings page with `繁體中文 (Chinese (Traditional))` selected — shows the new option in the language picker and Taiwan-style terminology across navigation, field labels, and action buttons: <img width="1673" height="956" alt="Settings page rendered in 繁體中文" src="https://github.com/user-attachments/assets/53cb8c83-9f74-468c-bf5d-a1c46a64bc05" /> <img width="1673" height="956" alt="Settings page language picker showing 繁體中文 (Chinese (Traditional)) option" src="https://github.com/user-attachments/assets/1b9e8536-3278-4c94-925c-a8d1c4d2d2d5" /> ## Out of scope (follow-up issues recommended) - **Extending `frontend/src/__tests__/i18n/locales.test.ts` to all locales** — current test only checks en↔de and uses `.size` comparison instead of set equality (pre-existing bug). Extending would require fixing drift in de/fr/ja/it/pt-BR first, which is beyond issue #1017. - **Hardcoded English strings in `ArchivesPage.tsx`** — noticed during smoke test that `Archives` title, `All Printers` / `All Materials` / `All Files` / `Hide Failed` / `Export` / `Select` / `Upload 3MF` (lines ~2966, 3147, 3164, 3179, 3206) are not wrapped in `t()`. Should be tracked as a separate i18n hardcoded-strings issue so they can be wired through all locales. - **Parity script coverage expansion** to de/fr/ja/it/pt-BR (intentionally kept to 3-way to avoid blocking this PR on drift in other locales). ## Drift policy This PR targets `upstream/dev` at the time of opening. If upstream/dev moves forward during review, I will **not** rebase this branch — upstream maintainer can merge normally, or I'll open a separate sync PR if conflicts arise. This keeps the diff stable and review-focused. ## Documentation No wiki PR required per `CONTRIBUTING.md` — adding a UI language is not a new feature, config key, URL, API, or install/upgrade flow change. The `availableLanguages` array in `i18n/index.ts` automatically drives the existing language picker in `SettingsPage.tsx` (two `<select>` consumers at lines 1339 and 3060) — no UI code changes needed. ## Review history Locale changes reviewed via three rounds of independent Codex review (APPROVED on round 3 after addressing `backToLogin` phrasing and unifying `提供者` terminology) and multi-agent PR review (code-reviewer / pr-test-analyzer / silent-failure-hunter / comment-analyzer) covering CLAUDE.md compliance, test coverage strategy, silent-failure hardening, and comment accuracy. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 12:35:20 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/bambuddy#1148
No description provided.