Skip to content

feat(i18n): add Traditional Chinese (zh-TW) locale support#3995

Closed
NkAntony777 wants to merge 1 commit into
esengine:main-v2from
NkAntony777:feat/3898-traditional-chinese-locale
Closed

feat(i18n): add Traditional Chinese (zh-TW) locale support#3995
NkAntony777 wants to merge 1 commit into
esengine:main-v2from
NkAntony777:feat/3898-traditional-chinese-locale

Conversation

@NkAntony777

Copy link
Copy Markdown
Contributor

Summary

  • Add Traditional Chinese (zh-TW) locale support for both frontend and backend
  • Enable users in Taiwan, Hong Kong, and Macau to use the UI in their native language
  • Support automatic locale detection from system settings (zh-TW, zh-Hant, etc.)

Changes

Frontend

  • zh-TW.ts: New locale file with full Traditional Chinese translations (936 keys)
  • i18n.tsx: Add zh-TW to Locale type, DICTS map, detectLocale(), normalizeLangPref(), and SPINNER_WORDS
  • bridge.ts: Update SetTrayLocale and MigrateDesktopPreferences to accept "zh-TW"

Backend (CLI)

  • messages_zh_tw.go: New Traditional Chinese message catalogue (339 fields)
  • i18n.go: Update setLanguage() to handle "zh-TW" tag and normalize() to detect zh-TW locale strings
  • i18n_test.go: Add zh-TW to catalog completeness, placeholder agreement, and normalize tests

Locale Detection

The following locale strings are recognized as zh-TW:

  • zh-TW, zh_TW.UTF-8, zh-Hant-TW, zh-Hant
  • Chinese Traditional, 繁體

Related Issue

Fixes #3898

Testing

  • Frontend TypeScript type check passes (npm run typecheck)
  • Backend Go tests updated to include zh-TW catalog validation
  • All translations maintain the same placeholder count as English

@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) labels Jun 11, 2026
@esengine

Copy link
Copy Markdown
Owner

This is genuinely good work — it's a real Traditional translation, not a Simplified copy with a few swaps (程式碼庫, 相容, 專案, 儲存 are the right Taiwan terms), TestCatalogsComplete and TestCatalogsAgreeOnPlaceholders both pass, and the frontend thoughtfully maps zh-hk/zh-mo to zh-TW too. Thank you for that.

One blocker before it can merge: your own TestNormalize fails locally:

normalize("zh_TW.UTF-8") = "zh", want "zh-TW"
normalize("  ZH_TW  ")   = "zh", want "zh-TW"

normalize() lowercases the input but the zh-TW branch only matches the hyphen form zh-tw (plus zh_hant/zh-hant) — it's missing the underscore form zh_tw, which is exactly what POSIX env locales use (LANG=zh_TW.UTF-8). So those fall through to the generic zh branch.

Simplest fix — normalize separators once at the top so both forms (and zh_hant) are covered:

func normalize(s string) string {
	s = strings.ToLower(strings.TrimSpace(s))
	s = strings.ReplaceAll(s, "_", "-")   // zh_TW.UTF-8 → zh-tw.utf-8
	if s == "" {
		return ""
	}
	if strings.HasPrefix(s, "zh-tw") || strings.HasPrefix(s, "zh-hant") || strings.Contains(s, "chinese traditional") || strings.Contains(s, "繁體") {
		return "zh-TW"
	}
	...

(The frontend is fine as-is — navigator.language is always the hyphen form, never the POSIX underscore one.)

Push that and CI should go green — happy to merge once it does.

- Add zh-TW locale file with full Traditional Chinese translations (936 keys)
- Add messages_zh_tw.go with zh-TW message catalogue (339 fields)
- Update i18n.tsx: add zh-TW to Locale type, DICTS map, detectLocale(), normalizeLangPref(), and SPINNER_WORDS
- Update bridge.ts: accept zh-TW in SetTrayLocale and MigrateDesktopPreferences
- Fix normalize() to handle POSIX underscore form (zh_TW.UTF-8) by normalizing separators before prefix matching
- Add zh-TW to catalog completeness, placeholder agreement, and normalize tests
- Map zh-hk and zh-mo to zh-TW in frontend locale detection

Fixes esengine#3898
@NkAntony777 NkAntony777 force-pushed the feat/3898-traditional-chinese-locale branch from 58e6e2c to 6404cc4 Compare June 12, 2026 05:03
@NkAntony777

Copy link
Copy Markdown
Contributor Author

Fixed. Added strings.ReplaceAll(s, "_", "-") at the top of normalize() so POSIX underscore forms (zh_TW.UTF-8) are normalized before prefix matching. Also removed the now-redundant zh_hant underscore check since the separator normalization covers it.

func normalize(s string) string {
	s = strings.ToLower(strings.TrimSpace(s))
	s = strings.ReplaceAll(s, "_", "-") // zh_TW.UTF-8 → zh-tw.utf-8
	...

All tests pass:

  • TestNormalizezh_TW.UTF-8, ZH_TW, zh-TW, zh-Hant, Chinese Traditional, 繁體 all resolve to zh-TW
  • TestCatalogsComplete — zh-TW catalog validated
  • TestCatalogsAgreeOnPlaceholders — placeholder counts match

@esengine

Copy link
Copy Markdown
Owner

Thank you for this — the Taiwan terminology is genuinely well done. I rebased it onto current main-v2 as #4199 and merged it from there. main-v2 had added ~560 i18n keys since you opened this (bots, hooks, memory, palette, status bar, music, custom font, /rename, /diff-fold, self-update, …), and the completeness checks on both sides require the full key set, so I backfilled them: OpenCC s2twp from the Simplified catalogues, aligned to your existing terms (權限 / 存取 / 參數 / 介面, kept your 當前) with a residual sweep, and dropped 13 keys en.ts has since renamed away. Your normalize fix is included. Credit kept to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

desktop Wails desktop app (desktop/**) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: 新增繁體中文 (zh-TW) 介面語言支援 / Add Traditional Chinese locale

2 participants