feat(i18n): add Traditional Chinese (zh-TW) language pack#394
Conversation
Add zh-TW case to both locale and todayText switch statements in currentDateString(), import dayjs/locale/zh-tw, and add Vitest tests confirming 今天是 prefix and Chinese weekday names for zh-TW locale.
Add Traditional Chinese greeting branch using 早安/午安/晚安 (distinct from Simplified Chinese 早上好/下午好/晚上好). Extend the Chinese-structure return condition to cover zh-TW so greetingSuffix is correctly omitted. Include TDD test covering both the Chinese greeting structure and the zh-TW-specific time-period wording.
…rble setSession encodes with btoa(unescape(encodeURIComponent(...))), but getUserSession decoded with atob() only. Multibyte UTF-8 (e.g. a Chinese display name such as 測試小明) was therefore read back as Latin-1 and rendered as mojibake (æ¸¬è©¦å°æ) in the home greeting. Add the symmetric decodeURIComponent(escape(...)) on read, plus a round-trip test.
📝 WalkthroughWalkthroughThis PR adds a complete Traditional Chinese (zh-TW) locale to the frontend, introducing new JSON translation files across nearly all feature areas, registering ChangesTraditional Chinese Locale Addition
Estimated code review effort: 2 (Simple) | ~15 minutes Related issues: Suggested labels: i18n, localization, frontend Suggested reviewers: none identified from the provided context 🐇 A rabbit hops through JSON trees so wide, 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (18)
worklenz-frontend/public/locales/zh-TW/admin-center/current-bill.json-8-8 (1)
8-8: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winNormalize the zh-TW wording in this namespace.
1個月19天后should be1個月19天後, and this file also mixes in other non-Taiwan terms such as賬單/賬戶/配置, so the rest of the pack needs the same cleanup.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/admin-center/current-bill.json` at line 8, Normalize the zh-TW translations in this locale file by correcting `cardBodyText02` from `1個月19天后` to `1個月19天後`, and audit the rest of the `current-bill.json` namespace for non-Taiwan wording such as `賬單`, `賬戶`, and `配置`, replacing them with standard zh-TW terms consistently across all keys.worklenz-frontend/public/locales/zh-TW/task-list-filters.json-50-50 (1)
50-50: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRemove the duplicate
selectCategoryentry.Biome is right here: the second key silently overrides the first one, so one of these definitions is dead data.
♻️ Proposed fix
"createStatus": "建立狀態", "name": "名稱", "category": "類別", "selectCategory": "選擇類別", @@ "rename": "重新命名", "delete": "刪除", "enterStatusName": "輸入狀態名稱", - "selectCategory": "選擇類別", "close": "關閉",Also applies to: 78-78
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/task-list-filters.json` at line 50, The zh-TW task-list-filters locale has duplicate selectCategory entries, and the later one silently overrides the earlier value. In task-list-filters.json, remove the duplicate selectCategory definition and keep only the intended single translation entry so the locale data stays unambiguous and Biome no longer flags dead data.Source: Linters/SAST tools
worklenz-frontend/public/locales/zh-TW/all-project-list.json-33-33 (1)
33-33: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse
權限here.
許可權reads as a typo in zh-TW.您沒有權限執行此操作is the expected wording.♻️ Proposed fix
- "noPermission": "您沒有許可權執行此操作" + "noPermission": "您沒有權限執行此操作"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/all-project-list.json` at line 33, The zh-TW translation for noPermission uses the wrong wording; update the string in all-project-list.json to use 權限 instead of 許可權. Locate the noPermission entry in the locale JSON and change the message to match the expected zh-TW phrasing so it reads naturally and consistently with other translations.worklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer-info-tab.json-5-5 (1)
5-5: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse the standard assignee term.
受託人reads like a trustee/entrusted party, not a task assignee. Please align this with the rest of the zh-TW pack, e.g.受指派人.♻️ Proposed fix
- "assignees": "受託人", + "assignees": "受指派人",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer-info-tab.json` at line 5, The zh-TW translation for the assignee label uses the wrong term and should be aligned with the rest of the locale pack. Update the assignees entry in the task-drawer info tab localization file to use the standard task-assignee wording, matching existing zh-TW translations such as 受指派人 rather than 受託人.worklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer.json-16-18 (1)
16-18: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winTighten the task-label terminology.
任務鍵/受理人are awkward in zh-TW and make this drawer read differently from the related task-drawer copy. Please standardize the wording here.♻️ Proposed fix
- "task-key": "任務鍵", + "task-key": "任務ID", ... - "assignees": "受理人", + "assignees": "受指派人",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer.json` around lines 16 - 18, The zh-TW task-drawer labels for task-key and assignees use awkward terminology and should be standardized to match the related task-drawer copy. Update the localized strings in task-drawer.json so these labels use the same terminology conventions as the rest of the drawer, and verify the surrounding keys like phase remain consistent with the shared task wording.worklenz-frontend/public/locales/zh-TW/task-list-table.json-113-113 (1)
113-113: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winIncorrect character: "覈取方塊" should be "核取方塊" (checkbox).
Standard Traditional Chinese term for "checkbox" is 核取方塊; "覈" is a non-standard variant character not used for this term in modern UI text.
🔤 Proposed fix
- "checkbox": "覈取方塊", + "checkbox": "核取方塊",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/task-list-table.json` at line 113, Update the zh-TW translation entry for the checkbox label in the task-list-table locale so it uses the standard Traditional Chinese term. In the task-list-table JSON translation object, replace the existing checkbox value from the non-standard variant to the correct form "核取方塊" and keep the key name unchanged.worklenz-frontend/public/locales/zh-TW/project-drawer.json-41-41 (1)
41-41: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse a standard zh-TW permission label.
無許可權is awkward here and reads like a non-TW term. Please switch this to沒有權限(or無權限) so the no-permission state matches the rest of the locale.♻️ Proposed fix
- "noPermission": "無許可權" + "noPermission": "沒有權限"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/project-drawer.json` at line 41, The zh-TW no-permission label in the project drawer locale uses an awkward non-TW phrasing, so update the noPermission translation in project-drawer.json to a standard form such as 沒有權限 or 無權限. Keep the change limited to the translation key and make sure the wording is consistent with the rest of the zh-TW locale strings.worklenz-frontend/public/locales/zh-TW/kanban-board.json-1-46 (1)
1-46: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRestore the missing
exampleTaskstranslations.
board-section-card.tsxalready readsexampleTasks.prefixandexampleTasks.task1/2/3from this namespace, but this zh-TW file doesn't define them, so the example board cards will stay in English. Please add the Traditional Chinese variants here.♻️ Proposed fix
{ + "exampleTasks": { + "prefix": "例如", + "task1": "定義專案範圍", + "task2": "與利害關係人確認", + "task3": "安排啟動會議" + }, "rename": "重新命名", "delete": "刪除", "addTask": "新增任務",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/kanban-board.json` around lines 1 - 46, Restore the missing exampleTasks entries in the zh-TW kanban-board namespace so board-section-card.tsx can resolve the localized example board text. Update the kanban-board.json translations to include the exampleTasks group with prefix and task1/task2/task3 in Traditional Chinese, matching the keys already consumed by board-section-card.tsx and keeping the JSON structure valid.worklenz-frontend/public/locales/zh-TW/schedule.json-3-3 (1)
3-3: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse
週for the week label.
周is the simplified form and stands out in an otherwise Traditional Chinese file. Switching to週will make the schedule header read more naturally for zh-TW users.♻️ Proposed fix
- "week": "周", + "week": "週",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/schedule.json` at line 3, The zh-TW schedule translation for the week label is using the simplified character form, so update the existing week entry in the schedule locale file to use the Traditional Chinese form `週`. Locate the `week` key in the zh-TW locale JSON and replace its current value accordingly so the schedule header reads naturally for zh-TW users.worklenz-frontend/public/locales/zh-TW/project-view-members.json-1-16 (1)
1-16: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winFix the empty-state copy.
emptyTextsays the project has no attachments, but this namespace is rendered by the members screen. That will show the wrong empty state when a project has no members.Proposed fix
- "emptyText": "專案中沒有附件。" + "emptyText": "專案中沒有成員。"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/project-view-members.json` around lines 1 - 16, The empty-state message in the project members localization entry is incorrect because the members screen is using attachment wording; update the emptyText value in the zh-TW project-view-members locale so it describes that there are no members instead of no attachments. Make the fix within the members translation keys alongside nameColumn, memberCount, and membersCountPlural, and keep the copy consistent with the members view.worklenz-frontend/public/locales/zh-TW/settings/categories.json-6-6 (1)
6-6: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAlign the column label with the task domain.
associatedTaskColumnreads like a task-related label, but this translation says “project,” which will mislabel the categories table if the column is about task associations.💡 Suggested fix
- "associatedTaskColumn": "關聯專案", + "associatedTaskColumn": "關聯任務",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/settings/categories.json` at line 6, The translation for associatedTaskColumn in the zh-TW categories localization is mismatched with the task domain and should not read as “project.” Update the entry in the categories.json locale file so the label reflects task association instead, and keep it consistent with the surrounding category/table terminology used by the settings localization keys.worklenz-frontend/public/locales/zh-TW/settings/team-members.json-10-10 (1)
10-10: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winFix the pin tooltip text.
pinTooltipcurrently says “refresh member list,” which conflicts with the pin action used by this key in the other settings locales. That will show the wrong action label in zh-TW.💡 Suggested fix
- "pinTooltip": "重新整理成員列表", + "pinTooltip": "點選將其固定到主選單",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/settings/team-members.json` at line 10, The zh-TW translation for pinTooltip is using the wrong action label and should match the pin behavior used in the other settings locales. Update the pinTooltip entry in the team-members locale file to the correct pin-related text, and keep the wording consistent with the corresponding pinTooltip key used by the settings translations.worklenz-frontend/public/locales/zh-TW/settings/labels.json-1-15 (1)
1-15: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winAdd the missing fetch error copy.
worklenz-frontend/src/pages/settings/labels/labels-drawer.tsx:316-346usest('fetchLabelErrorMessage', 'Failed to fetch label'), so zh-TW users will still see the English fallback on API failures.🛠️ Suggested patch
{ "labelColumn": "標籤", + "fetchLabelErrorMessage": "無法取得標籤", "deleteConfirmationTitle": "您確定嗎?",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/settings/labels.json` around lines 1 - 15, The zh-TW labels locale is missing the fetch error copy used by labels-drawer.tsx via t('fetchLabelErrorMessage', 'Failed to fetch label'), so add the missing fetchLabelErrorMessage entry in this JSON with a proper Traditional Chinese translation. Keep the key alongside the other label-related strings in the labels resource so the Settings labels drawer no longer falls back to English on API failures.worklenz-frontend/public/locales/zh-TW/settings/sidebar.json-1-15 (1)
1-15: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winLocalize the settings search box text.
worklenz-frontend/src/pages/settings/sidebar/settings-sidebar.tsx:1-180readst('searchSettings', ...)for both the placeholder and aria-label, so leaving this key out will keep the English fallback in the zh-TW UI.🛠️ Suggested patch
{ + "searchSettings": "搜尋設定...", "profile": "個人資料",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/settings/sidebar.json` around lines 1 - 15, The zh-TW settings sidebar translations are missing the search box text used by settings-sidebar.tsx via t('searchSettings') for both placeholder and aria-label, so add the missing searchSettings key to the zh-TW sidebar locale object alongside the existing labels. Keep the translation consistent with the other settings terms in this file so the SettingsSidebar component no longer falls back to English.worklenz-frontend/public/locales/zh-TW/common.json-6-6 (1)
6-6: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winMake
reconnectingreflect the in-progress state.This currently reads like the connection is already lost, which duplicates
connection-lostand can mislead users during transient reconnects.🛠️ Proposed fix
- "reconnecting": "與伺服器斷開連線。", + "reconnecting": "正在重新連線...",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/common.json` at line 6, Update the `reconnecting` translation in `common.json` so it describes an active reconnect attempt rather than a completed disconnect. Use the existing `connection-lost` entry as the contrast and change only the `reconnecting` string to wording that indicates the app is trying to reconnect, keeping the key name and locale consistent with the rest of the `common.json` translations.worklenz-frontend/public/locales/zh-TW/auth/signup.json-10-15 (1)
10-15: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winFinish localizing the password copy.
passwordLabel,passwordGuideline,passwordPlaceholder, andpasswordMaxCharacterRequiredare still English, so the zh-TW signup flow will mix languages on the primary registration form.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/auth/signup.json` around lines 10 - 15, The zh-TW signup password copy is only partially localized, so finish translating the remaining English strings in the auth/signup translation entry. Update the values for passwordLabel, passwordGuideline, passwordPlaceholder, and passwordMaxCharacterRequired in the signup.json locale file so the registration form uses consistent Traditional Chinese text throughout.worklenz-frontend/public/locales/zh-TW/auth/login.json-10-15 (1)
10-15: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winFinish localizing the password copy.
passwordLabel,passwordGuideline,passwordPlaceholder, andpasswordMaxCharacterRequiredare still English, so the zh-TW login flow will mix languages on the core auth form.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/auth/login.json` around lines 10 - 15, The zh-TW login localization is incomplete because the password-related strings in the login translation object are still in English. Update the login JSON entries for passwordLabel, passwordGuideline, passwordPlaceholder, and passwordMaxCharacterRequired in the auth/login locale so the core auth form uses consistent Traditional Chinese text; use the existing keys in this file to locate and replace those values.worklenz-frontend/public/locales/zh-TW/create-first-tasks.json-3-3 (1)
3-3: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRename the typoed key.
inputLableshould beinputLabel; otherwise the consumer contract won't match this namespace.Proposed fix
- "inputLable": "輸入您將在其中完成的幾個任務", + "inputLabel": "輸入您將在其中完成的幾個任務",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/create-first-tasks.json` at line 3, Rename the typoed locale key in the create-first-tasks zh-TW namespace from inputLable to inputLabel so it matches the consumer contract; update the JSON key in this translation file and keep the existing translated value unchanged.
🧹 Nitpick comments (2)
worklenz-frontend/src/utils/session-helper.ts (1)
13-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffCorrect symmetric decode fix.
This correctly mirrors
setSession'sbtoa(unescape(encodeURIComponent(...)))encoding, resolving mojibake for multibyte names.One optional note:
escape/unescapeare deprecated legacy globals. SincesetSession(unchanged here) also relies on them, a full modernization (e.g., usingTextEncoder/TextDecoderfor base64 round-tripping) would need to touch both functions together — not necessary now, but worth keeping in mind if this code is revisited.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/src/utils/session-helper.ts` around lines 13 - 15, The session decode path in session-helper’s getSession should symmetrically reverse setSession’s btoa(unescape(encodeURIComponent(...))) encoding, so update the decode logic around atob to use the matching UTF-8 round-trip and keep JSON.parse applied to the fully decoded string. Make sure the implementation preserves multibyte characters correctly and stays aligned with the existing setSession helper; a broader TextEncoder/TextDecoder refactor can be deferred since both helpers would need to change together.worklenz-frontend/public/locales/zh-TW/template-drawer.json (1)
16-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value"Worklenz模板" missing a space before the trailing Chinese suffix.
Compare with other product-name usages; consider
Worklenz 模板for consistent spacing between Latin and CJK text, matching common Traditional Chinese typography conventions (this file otherwise doesn't mix scripts elsewhere).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@worklenz-frontend/public/locales/zh-TW/template-drawer.json` at line 16, The localized value for worklenzTemplates should use a space between the Latin product name and the Chinese suffix for consistent mixed-script typography. Update the translation entry in the zh-TW template-drawer JSON so the Worklenz label follows the same spacing pattern as other product-name strings, using the worklenzTemplates key to locate it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@worklenz-frontend/public/locales/zh-TW/account-setup.json`:
- Around line 32-35: The onboarding locale object has duplicate keys that
overwrite earlier strings, so split the repeated entries in the zh-TW
account-setup JSON into distinct unique keys or merge the duplicated onboarding
copy sections so each string is preserved. Check the repeated `tasksStepTitle`
and `previousToolsPlaceholder` entries in the account setup translations and
rename or relocate them so the flat object contains no duplicate property names.
In `@worklenz-frontend/public/locales/zh-TW/auth/verify-reset-email.json`:
- Around line 1-14: The zh-TW auth/verify-reset-email translation namespace is
missing the success-state strings used by verify-reset-email.tsx. Add the
successTitle and successMessage keys to this JSON so the page can render the
success state without falling back to raw keys, keeping the values consistent
with the existing reset-email wording and tone.
In `@worklenz-frontend/src/features/i18n/localesSlice.ts`:
- Line 11: Browser-language detection in the locales slice is collapsing Chinese
variants to a generic value that never matches the existing Language entries.
Update the locale resolution logic in localesSlice to use the full browser
locale or explicitly map Chinese variants like zh-TW, zh-Hant-TW, and zh-CN to
the correct Language values, so the detected locale matches ZH_TW or ZH rather
than falling back to English.
---
Minor comments:
In `@worklenz-frontend/public/locales/zh-TW/admin-center/current-bill.json`:
- Line 8: Normalize the zh-TW translations in this locale file by correcting
`cardBodyText02` from `1個月19天后` to `1個月19天後`, and audit the rest of the
`current-bill.json` namespace for non-Taiwan wording such as `賬單`, `賬戶`, and
`配置`, replacing them with standard zh-TW terms consistently across all keys.
In `@worklenz-frontend/public/locales/zh-TW/all-project-list.json`:
- Line 33: The zh-TW translation for noPermission uses the wrong wording; update
the string in all-project-list.json to use 權限 instead of 許可權. Locate the
noPermission entry in the locale JSON and change the message to match the
expected zh-TW phrasing so it reads naturally and consistently with other
translations.
In `@worklenz-frontend/public/locales/zh-TW/auth/login.json`:
- Around line 10-15: The zh-TW login localization is incomplete because the
password-related strings in the login translation object are still in English.
Update the login JSON entries for passwordLabel, passwordGuideline,
passwordPlaceholder, and passwordMaxCharacterRequired in the auth/login locale
so the core auth form uses consistent Traditional Chinese text; use the existing
keys in this file to locate and replace those values.
In `@worklenz-frontend/public/locales/zh-TW/auth/signup.json`:
- Around line 10-15: The zh-TW signup password copy is only partially localized,
so finish translating the remaining English strings in the auth/signup
translation entry. Update the values for passwordLabel, passwordGuideline,
passwordPlaceholder, and passwordMaxCharacterRequired in the signup.json locale
file so the registration form uses consistent Traditional Chinese text
throughout.
In `@worklenz-frontend/public/locales/zh-TW/common.json`:
- Line 6: Update the `reconnecting` translation in `common.json` so it describes
an active reconnect attempt rather than a completed disconnect. Use the existing
`connection-lost` entry as the contrast and change only the `reconnecting`
string to wording that indicates the app is trying to reconnect, keeping the key
name and locale consistent with the rest of the `common.json` translations.
In `@worklenz-frontend/public/locales/zh-TW/create-first-tasks.json`:
- Line 3: Rename the typoed locale key in the create-first-tasks zh-TW namespace
from inputLable to inputLabel so it matches the consumer contract; update the
JSON key in this translation file and keep the existing translated value
unchanged.
In `@worklenz-frontend/public/locales/zh-TW/kanban-board.json`:
- Around line 1-46: Restore the missing exampleTasks entries in the zh-TW
kanban-board namespace so board-section-card.tsx can resolve the localized
example board text. Update the kanban-board.json translations to include the
exampleTasks group with prefix and task1/task2/task3 in Traditional Chinese,
matching the keys already consumed by board-section-card.tsx and keeping the
JSON structure valid.
In `@worklenz-frontend/public/locales/zh-TW/project-drawer.json`:
- Line 41: The zh-TW no-permission label in the project drawer locale uses an
awkward non-TW phrasing, so update the noPermission translation in
project-drawer.json to a standard form such as 沒有權限 or 無權限. Keep the change
limited to the translation key and make sure the wording is consistent with the
rest of the zh-TW locale strings.
In `@worklenz-frontend/public/locales/zh-TW/project-view-members.json`:
- Around line 1-16: The empty-state message in the project members localization
entry is incorrect because the members screen is using attachment wording;
update the emptyText value in the zh-TW project-view-members locale so it
describes that there are no members instead of no attachments. Make the fix
within the members translation keys alongside nameColumn, memberCount, and
membersCountPlural, and keep the copy consistent with the members view.
In `@worklenz-frontend/public/locales/zh-TW/schedule.json`:
- Line 3: The zh-TW schedule translation for the week label is using the
simplified character form, so update the existing week entry in the schedule
locale file to use the Traditional Chinese form `週`. Locate the `week` key in
the zh-TW locale JSON and replace its current value accordingly so the schedule
header reads naturally for zh-TW users.
In `@worklenz-frontend/public/locales/zh-TW/settings/categories.json`:
- Line 6: The translation for associatedTaskColumn in the zh-TW categories
localization is mismatched with the task domain and should not read as
“project.” Update the entry in the categories.json locale file so the label
reflects task association instead, and keep it consistent with the surrounding
category/table terminology used by the settings localization keys.
In `@worklenz-frontend/public/locales/zh-TW/settings/labels.json`:
- Around line 1-15: The zh-TW labels locale is missing the fetch error copy used
by labels-drawer.tsx via t('fetchLabelErrorMessage', 'Failed to fetch label'),
so add the missing fetchLabelErrorMessage entry in this JSON with a proper
Traditional Chinese translation. Keep the key alongside the other label-related
strings in the labels resource so the Settings labels drawer no longer falls
back to English on API failures.
In `@worklenz-frontend/public/locales/zh-TW/settings/sidebar.json`:
- Around line 1-15: The zh-TW settings sidebar translations are missing the
search box text used by settings-sidebar.tsx via t('searchSettings') for both
placeholder and aria-label, so add the missing searchSettings key to the zh-TW
sidebar locale object alongside the existing labels. Keep the translation
consistent with the other settings terms in this file so the SettingsSidebar
component no longer falls back to English.
In `@worklenz-frontend/public/locales/zh-TW/settings/team-members.json`:
- Line 10: The zh-TW translation for pinTooltip is using the wrong action label
and should match the pin behavior used in the other settings locales. Update the
pinTooltip entry in the team-members locale file to the correct pin-related
text, and keep the wording consistent with the corresponding pinTooltip key used
by the settings translations.
In
`@worklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer-info-tab.json`:
- Line 5: The zh-TW translation for the assignee label uses the wrong term and
should be aligned with the rest of the locale pack. Update the assignees entry
in the task-drawer info tab localization file to use the standard task-assignee
wording, matching existing zh-TW translations such as 受指派人 rather than 受託人.
In `@worklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer.json`:
- Around line 16-18: The zh-TW task-drawer labels for task-key and assignees use
awkward terminology and should be standardized to match the related task-drawer
copy. Update the localized strings in task-drawer.json so these labels use the
same terminology conventions as the rest of the drawer, and verify the
surrounding keys like phase remain consistent with the shared task wording.
In `@worklenz-frontend/public/locales/zh-TW/task-list-filters.json`:
- Line 50: The zh-TW task-list-filters locale has duplicate selectCategory
entries, and the later one silently overrides the earlier value. In
task-list-filters.json, remove the duplicate selectCategory definition and keep
only the intended single translation entry so the locale data stays unambiguous
and Biome no longer flags dead data.
In `@worklenz-frontend/public/locales/zh-TW/task-list-table.json`:
- Line 113: Update the zh-TW translation entry for the checkbox label in the
task-list-table locale so it uses the standard Traditional Chinese term. In the
task-list-table JSON translation object, replace the existing checkbox value
from the non-standard variant to the correct form "核取方塊" and keep the key name
unchanged.
---
Nitpick comments:
In `@worklenz-frontend/public/locales/zh-TW/template-drawer.json`:
- Line 16: The localized value for worklenzTemplates should use a space between
the Latin product name and the Chinese suffix for consistent mixed-script
typography. Update the translation entry in the zh-TW template-drawer JSON so
the Worklenz label follows the same spacing pattern as other product-name
strings, using the worklenzTemplates key to locate it.
In `@worklenz-frontend/src/utils/session-helper.ts`:
- Around line 13-15: The session decode path in session-helper’s getSession
should symmetrically reverse setSession’s
btoa(unescape(encodeURIComponent(...))) encoding, so update the decode logic
around atob to use the matching UTF-8 round-trip and keep JSON.parse applied to
the fully decoded string. Make sure the implementation preserves multibyte
characters correctly and stays aligned with the existing setSession helper; a
broader TextEncoder/TextDecoder refactor can be deferred since both helpers
would need to change together.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b03612bb-850e-430b-94a1-d77ffc98c48e
📒 Files selected for processing (81)
worklenz-frontend/public/locales/zh-TW/404-page.jsonworklenz-frontend/public/locales/zh-TW/account-setup.jsonworklenz-frontend/public/locales/zh-TW/admin-center/current-bill.jsonworklenz-frontend/public/locales/zh-TW/admin-center/overview.jsonworklenz-frontend/public/locales/zh-TW/admin-center/projects.jsonworklenz-frontend/public/locales/zh-TW/admin-center/sidebar.jsonworklenz-frontend/public/locales/zh-TW/admin-center/teams.jsonworklenz-frontend/public/locales/zh-TW/admin-center/users.jsonworklenz-frontend/public/locales/zh-TW/all-project-list.jsonworklenz-frontend/public/locales/zh-TW/auth/auth-common.jsonworklenz-frontend/public/locales/zh-TW/auth/forgot-password.jsonworklenz-frontend/public/locales/zh-TW/auth/login.jsonworklenz-frontend/public/locales/zh-TW/auth/signup.jsonworklenz-frontend/public/locales/zh-TW/auth/verify-reset-email.jsonworklenz-frontend/public/locales/zh-TW/common.jsonworklenz-frontend/public/locales/zh-TW/create-first-project-form.jsonworklenz-frontend/public/locales/zh-TW/create-first-tasks.jsonworklenz-frontend/public/locales/zh-TW/home.jsonworklenz-frontend/public/locales/zh-TW/invite-initial-team-members.jsonworklenz-frontend/public/locales/zh-TW/kanban-board.jsonworklenz-frontend/public/locales/zh-TW/license-expired.jsonworklenz-frontend/public/locales/zh-TW/navbar.jsonworklenz-frontend/public/locales/zh-TW/organization-name-form.jsonworklenz-frontend/public/locales/zh-TW/phases-drawer.jsonworklenz-frontend/public/locales/zh-TW/project-drawer.jsonworklenz-frontend/public/locales/zh-TW/project-view-files.jsonworklenz-frontend/public/locales/zh-TW/project-view-insights.jsonworklenz-frontend/public/locales/zh-TW/project-view-members.jsonworklenz-frontend/public/locales/zh-TW/project-view-updates.jsonworklenz-frontend/public/locales/zh-TW/project-view.jsonworklenz-frontend/public/locales/zh-TW/project-view/import-task-templates.jsonworklenz-frontend/public/locales/zh-TW/project-view/project-member-drawer.jsonworklenz-frontend/public/locales/zh-TW/project-view/project-view-header.jsonworklenz-frontend/public/locales/zh-TW/project-view/save-as-template.jsonworklenz-frontend/public/locales/zh-TW/reporting-members-drawer.jsonworklenz-frontend/public/locales/zh-TW/reporting-members.jsonworklenz-frontend/public/locales/zh-TW/reporting-overview-drawer.jsonworklenz-frontend/public/locales/zh-TW/reporting-overview.jsonworklenz-frontend/public/locales/zh-TW/reporting-projects-drawer.jsonworklenz-frontend/public/locales/zh-TW/reporting-projects-filters.jsonworklenz-frontend/public/locales/zh-TW/reporting-projects.jsonworklenz-frontend/public/locales/zh-TW/reporting-sidebar.jsonworklenz-frontend/public/locales/zh-TW/schedule.jsonworklenz-frontend/public/locales/zh-TW/settings/categories.jsonworklenz-frontend/public/locales/zh-TW/settings/change-password.jsonworklenz-frontend/public/locales/zh-TW/settings/clients.jsonworklenz-frontend/public/locales/zh-TW/settings/job-titles.jsonworklenz-frontend/public/locales/zh-TW/settings/labels.jsonworklenz-frontend/public/locales/zh-TW/settings/language.jsonworklenz-frontend/public/locales/zh-TW/settings/notifications.jsonworklenz-frontend/public/locales/zh-TW/settings/profile.jsonworklenz-frontend/public/locales/zh-TW/settings/project-templates.jsonworklenz-frontend/public/locales/zh-TW/settings/sidebar.jsonworklenz-frontend/public/locales/zh-TW/settings/task-templates.jsonworklenz-frontend/public/locales/zh-TW/settings/team-members.jsonworklenz-frontend/public/locales/zh-TW/settings/teams.jsonworklenz-frontend/public/locales/zh-TW/survey.jsonworklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer-info-tab.jsonworklenz-frontend/public/locales/zh-TW/task-drawer/task-drawer.jsonworklenz-frontend/public/locales/zh-TW/task-list-filters.jsonworklenz-frontend/public/locales/zh-TW/task-list-table.jsonworklenz-frontend/public/locales/zh-TW/task-management.jsonworklenz-frontend/public/locales/zh-TW/task-template-drawer.jsonworklenz-frontend/public/locales/zh-TW/tasks/task-table-bulk-actions.jsonworklenz-frontend/public/locales/zh-TW/template-drawer.jsonworklenz-frontend/public/locales/zh-TW/templateDrawer.jsonworklenz-frontend/public/locales/zh-TW/time-report.jsonworklenz-frontend/public/locales/zh-TW/unauthorized.jsonworklenz-frontend/src/features/i18n/LanguageSelector.tsxworklenz-frontend/src/features/i18n/__tests__/localesSlice.test.tsworklenz-frontend/src/features/i18n/localesSlice.tsworklenz-frontend/src/pages/account-setup/account-setup.tsxworklenz-frontend/src/pages/settings/language-and-region/language-and-region-settings.tsxworklenz-frontend/src/utils/__tests__/current-date-string.test.tsworklenz-frontend/src/utils/__tests__/dateUtils.test.tsworklenz-frontend/src/utils/__tests__/greetingString.test.tsworklenz-frontend/src/utils/__tests__/session-helper.test.tsworklenz-frontend/src/utils/current-date-string.tsworklenz-frontend/src/utils/dateUtils.tsworklenz-frontend/src/utils/greetingString.tsworklenz-frontend/src/utils/session-helper.ts
| "tasksStepTitle": "建立您的第一個任務", | ||
| "tasksStepLabel": "輸入您將在其中完成的幾個任務", | ||
| "tasksStepAddAnother": "新增另一個", | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Split the duplicated onboarding keys.
tasksStepTitle and previousToolsPlaceholder are each declared twice in this flat object. JSON will keep only the last value, so the earlier strings are silently shadowed and one set of onboarding copy is lost.
Also applies to: 85-87, 123-127, 155-157
🧰 Tools
🪛 Biome (2.5.1)
[error] 32-32: The key tasksStepTitle was already declared.
(lint/suspicious/noDuplicateObjectKeys)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@worklenz-frontend/public/locales/zh-TW/account-setup.json` around lines 32 -
35, The onboarding locale object has duplicate keys that overwrite earlier
strings, so split the repeated entries in the zh-TW account-setup JSON into
distinct unique keys or merge the duplicated onboarding copy sections so each
string is preserved. Check the repeated `tasksStepTitle` and
`previousToolsPlaceholder` entries in the account setup translations and rename
or relocate them so the flat object contains no duplicate property names.
Source: Linters/SAST tools
| { | ||
| "title": "驗證重置電子郵件", | ||
| "description": "輸入您的新密碼", | ||
| "placeholder": "輸入您的新密碼", | ||
| "confirmPasswordPlaceholder": "確認您的新密碼", | ||
| "passwordHint": "至少8個字元,包括大小寫字母、一個數字和一個符號。", | ||
| "resetPasswordButton": "重置密碼", | ||
| "orText": "或", | ||
| "resendResetEmail": "重新傳送重置電子郵件", | ||
| "passwordRequired": "請輸入您的新密碼", | ||
| "returnToLoginButton": "返回登入", | ||
| "confirmPasswordRequired": "請確認您的新密碼", | ||
| "passwordMismatch": "兩次輸入的密碼不匹配" | ||
| } No newline at end of file |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Add the success-state keys consumed by the page.
verify-reset-email.tsx calls t('successTitle') and t('successMessage'), but this namespace does not define either key. The success result will fall back to raw keys or empty text.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@worklenz-frontend/public/locales/zh-TW/auth/verify-reset-email.json` around
lines 1 - 14, The zh-TW auth/verify-reset-email translation namespace is missing
the success-state strings used by verify-reset-email.tsx. Add the successTitle
and successMessage keys to this JSON so the page can render the success state
without falling back to raw keys, keeping the values consistent with the
existing reset-email wording and tone.
| ALB = 'alb', | ||
| DE = 'de', | ||
| ZH = 'zh_cn', | ||
| ZH_TW = 'zh-TW', |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map relevant files first
git ls-files 'worklenz-frontend/src/features/i18n/**' | sort
printf '\n--- localesSlice outline ---\n'
ast-grep outline worklenz-frontend/src/features/i18n/localesSlice.ts --view expanded || true
printf '\n--- search for Language enum / zh variants / getDefaultLanguage ---\n'
rg -n --hidden --glob '!**/node_modules/**' \
-e 'enum Language|type ILanguageType|getDefaultLanguage|ZH_TW|zh-TW|zh_cn|zh-CN|navigator.language|Object\.values\(Language\)' \
worklenz-frontend/src/features/i18n
printf '\n--- localesSlice.ts excerpt ---\n'
sed -n '1,220p' worklenz-frontend/src/features/i18n/localesSlice.tsRepository: Worklenz/worklenz
Length of output: 5668
Handle Chinese locales in browser-language detection
navigator.language.split('-')[0] reduces zh-TW, zh-Hant-TW, and zh-CN to zh, which never matches Language.ZH_TW or Language.ZH (zh_cn). Chinese browsers will fall back to English instead of the intended locale. Use the full browser locale or map Chinese variants explicitly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@worklenz-frontend/src/features/i18n/localesSlice.ts` at line 11,
Browser-language detection in the locales slice is collapsing Chinese variants
to a generic value that never matches the existing Language entries. Update the
locale resolution logic in localesSlice to use the full browser locale or
explicitly map Chinese variants like zh-TW, zh-Hant-TW, and zh-CN to the correct
Language values, so the detected locale matches ZH_TW or ZH rather than falling
back to English.
|
@TW199501, Thank you for this contribution! Adding zh-TW support is a great addition to Worklenz. We'll review the PR and merge it into main once the review is complete. We appreciate your effort and support! |
|
Your project is quite unique. Could you please suggest integrating the project with GitHub via API in the future? This would make the tool even more distinctive. If you're open to my suggestion, I've already prepared a plan and specification, which I'll present to you later. Since your project is currently closed-source, I'd appreciate your reply in advance. |
Summary
Add Traditional Chinese (zh-TW) language support with tests and a bundled UTF-8 session fix. Requested in #390, approved by @cdsthakshila.
Note on PR #380
PR #380 also proposes Traditional Chinese support with different design choices (uses
zh_twdirectory, includes a backend migration, and touches more datetime utils). This PR takes a different approach — BCP-47zh-TWdirectory naming, focused frontend scope, plus unit tests and an unrelated UTF-8 session fix. Please pick whichever fits the project direction; happy to close this if #380 is preferred.What's included
ZH_TW = 'zh-TW'in theLanguageenumLanguageSelector, account setup, settings › language and region)zh-TWto dayjszh-twlocale for relative time formattingcurrentDateString()with Chinese weekday + 今天是 prefix for zh-TWpublic/locales/zh-TW/(68 files)Additional fix (bundled because it's the same UTF-8 concern)
fix(i18n): decode base64 session as UTF-8setSession()encodes display names withbtoa(unescape(encodeURIComponent(...))), butgetUserSession()decoded with plainatob(). Multi-byte UTF-8 display names (e.g. 測試小明) were therefore read back as Latin-1 and rendered as mojibake (`測試...`) in the home-page greeting. Adds the symmetric UTF-8 decode.Test plan
Closes #390
Refs #380
Summary by CodeRabbit
New Features
Bug Fixes
Tests