feat(i18n): add Simplified Chinese locale and extract issue component strings#1921
feat(i18n): add Simplified Chinese locale and extract issue component strings#1921daidaidaiok wants to merge 3 commits intoAndyMik90:developfrom
Conversation
…Lab issue strings - Add complete zh locale with 11 namespace files (common, navigation, settings, tasks, welcome, onboarding, dialogs, gitlab, taskReview, terminal, errors) - Extract hardcoded strings from GitHub/GitLab issue components into i18n translation keys - Add corresponding en/fr translations for newly extracted strings - Register zh language in i18n config, spellcheck mapping, and language selector - Add locale-coverage test to verify key alignment and placeholder consistency across locales - Separate issue state badge labels from filter labels for correct singular/plural translations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds i18n to GitHub and GitLab issue UIs and registers Simplified Chinese (zh) translations across multiple frontend namespaces; includes locale files, spellcheck mappings, supported-language updates, and tests validating locale coverage and placeholder alignment. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the application's internationalization capabilities by introducing full support for Simplified Chinese. It involves a comprehensive effort to extract previously hardcoded UI strings from various issue-related components, ensuring they are now managed through i18n translation keys. This foundational work not only enables the new Chinese locale but also improves the maintainability and future extensibility of the application's multilingual support, backed by automated testing for translation consistency. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
🎉 Thanks for your first PR!
A maintainer will review it soon. Please make sure:
- Your branch is synced with
develop - CI checks pass
- You've followed our contribution guide
Welcome to the Auto Claude community!
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Code Review
This pull request is a significant step towards internationalization. It adds support for Simplified Chinese and extracts many hardcoded strings from the GitHub and GitLab issue components into translation keys. The addition of a locale-coverage.test.ts is an excellent practice to ensure consistency and completeness across locales. The changes are well-implemented. I have a couple of minor suggestions to improve code readability in the list item components.
Note: Security Review did not run due to the size of the PR.
| className={`text-xs ${GITHUB_ISSUE_STATE_COLORS[issue.state]}`} | ||
| > | ||
| {GITHUB_ISSUE_STATE_LABELS[issue.state]} | ||
| {issue.state === 'open' ? t('issues.stateOpen') : issue.state === 'closed' ? t('issues.stateClosed') : (GITHUB_ISSUE_STATE_LABELS[issue.state] ?? issue.state)} |
There was a problem hiding this comment.
This line is a bit long and hard to read with the nested ternary operators. For improved readability, you could use an object lookup to get the translated state label. This makes the code more declarative and easier to maintain.
| {issue.state === 'open' ? t('issues.stateOpen') : issue.state === 'closed' ? t('issues.stateClosed') : (GITHUB_ISSUE_STATE_LABELS[issue.state] ?? issue.state)} | |
| {{ open: t('issues.stateOpen'), closed: t('issues.stateClosed') }[issue.state] ?? GITHUB_ISSUE_STATE_LABELS[issue.state] ?? issue.state} |
| className={`text-xs ${GITLAB_ISSUE_STATE_COLORS[issue.state] || ''}`} | ||
| > | ||
| {GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state} | ||
| {issue.state === 'opened' ? t('states.opened') : issue.state === 'closed' ? t('states.closed') : (GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state)} |
There was a problem hiding this comment.
Similar to the GitHub issue list item, this line is a bit long with nested ternary operators. Using an object lookup would make it more readable and maintainable.
| {issue.state === 'opened' ? t('states.opened') : issue.state === 'closed' ? t('states.closed') : (GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state)} | |
| {{ opened: t('states.opened'), closed: t('states.closed') }[issue.state] ?? (GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state)} |
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx (1)
55-64:⚠️ Potential issue | 🟠 MajorMake the icon button visible on keyboard focus.
Line 58 keeps this control fully transparent unless the row is hovered, so tabbing to it can land focus on an invisible button. Since this PR is already improving its accessibility label, please also expose it on focus.
♿ Proposed fix
- className="opacity-0 group-hover:opacity-100 transition-opacity h-8 w-8" + className="opacity-0 group-hover:opacity-100 focus-visible:opacity-100 transition-opacity h-8 w-8"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx` around lines 55 - 64, The icon Button in IssueListItem.tsx is invisible when focused because className sets opacity-0 and only group-hover:opacity-100 makes it visible on hover; update its classes so keyboard focus also makes it visible (e.g., add focus:opacity-100 and/or focus-visible:opacity-100) while keeping the existing group-hover behavior, and ensure no other styling (e.g., pointer events) prevents focus—locate the Button component with onClick and aria-label={t('issues.createTask')} to apply the change.apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx (1)
46-50:⚠️ Potential issue | 🟡 MinorUse the new i18n state keys for the badge.
This badge still renders
GITHUB_ISSUE_STATE_LABELS[issue.state], so the detail view bypasses the newly addedissues.stateOpen/stateClosedtranslations and stays English infr/zh.As per coding guidelines, "All frontend user-facing text must use `react-i18next` translation keys. Never hardcode strings in JSX/TSX. Add keys to both `en/*.json` and `fr/*.json` translation files."💡 Suggested fix
- {GITHUB_ISSUE_STATE_LABELS[issue.state]} + {issue.state === 'open' ? t('issues.stateOpen') : t('issues.stateClosed')}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx` around lines 46 - 50, The badge currently uses the hardcoded label lookup GITHUB_ISSUE_STATE_LABELS[issue.state], bypassing i18n; update IssueDetail to use react-i18next (useTranslation or t) and replace that label with the new translation keys (e.g., t('issues.stateOpen') when issue.state === 'open' and t('issues.stateClosed') when 'closed'), keeping the existing GITHUB_ISSUE_STATE_COLORS[issue.state] for styling; ensure the new keys exist in en/*.json and fr/*.json and remove the direct use of GITHUB_ISSUE_STATE_LABELS in the Badge.apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsx (1)
108-112:⚠️ Potential issue | 🟡 MinorLocalize the issue subtitle as well.
Issue #is still hardcoded here, so this dialog will show mixed-language UI even after switching to zh/fr. As per coding guidelines, "All frontend user-facing text must usereact-i18nexttranslation keys. Never hardcode strings in JSX/TSX. Add keys to bothen/*.jsonandfr/*.jsontranslation files."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsx` around lines 108 - 112, The subtitle in InvestigationDialog currently hardcodes "Issue #", so update the JSX inside DialogDescription to use the react-i18next translation hook (t) to render a localized string that includes the issue number and title (referencing selectedIssue.number and selectedIssue.title); add the corresponding translation key (e.g. "issue.subtitle": "Issue #{{number}}: {{title}}" and French equivalent) to both en/*.json and fr/*.json, and ensure the code uses t('issue.subtitle', { number: selectedIssue.number, title: selectedIssue.title }) within the DialogDescription rendering.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/frontend/src/shared/i18n/locale-coverage.test.ts`:
- Around line 135-146: The test currently hardcodes an exact equality assertion
for the EN/FR delta counts which will fail CI whenever the French translation
debt is legitimately changed; update the test so it no longer blocks CI by
removing the strict expect(deltas).toEqual([...]) check and instead emit the
audit as informational output (e.g., console.info or processLogger) or record it
via a non-blocking snapshot/report; keep the loop and variables (enLocales,
frLocales, flattenLeaves, deltas, missingInFr, extraInFr) intact so the computed
deltas are still produced but do not cause the test to fail.
In `@apps/frontend/src/shared/i18n/locales/en/common.json`:
- Line 527: Replace the current flat "commentsCount" value with a pluralized
form under the same key (use the project's ICU/pluralization format) so singular
displays "1 comment" and others "N comments"; make the identical key change for
"commentsCount" in the fr and zh locale files so the locale schema stays aligned
across languages and no structural changes are introduced elsewhere.
In `@apps/frontend/src/shared/i18n/locales/fr/common.json`:
- Line 508: The "openCount" translation currently uses a fixed plural form
("{{count}} ouvertes") and must be switched to the pluralization schema used by
sibling locales so it renders correctly for singular and plural; update the
"openCount" value to use the same count/plural structure (e.g., keys for "one"
and "other" or the project's existing ICU/plural format) matching other locale
files so 1 reads "1 ouverte" and plural reads "X ouvertes" while keeping the
same "openCount" key name.
In `@apps/frontend/src/shared/i18n/locales/zh/dialogs.json`:
- Around line 79-95: The Add Feature dialog uses inconsistent Chinese
terminology (e.g., "专题标题" and "复杂") that conflicts with "功能" used elsewhere;
update the i18n keys in this JSON block so field labels consistently reference
"功能" and proper nouns: change "featureTitle" to a clear label like "功能标题" and
its placeholder ("featureTitlePlaceholder") to match examples; change
"complexity" from "复杂" to "复杂度" and "selectComplexity" to a matching selector
label; verify "featureDescription", "featureDescriptionPlaceholder", "rationale"
and "rationalePlaceholder" use consistent wording for 功能/功能目的 and ensure all
keys (featureTitle, featureTitlePlaceholder, complexity, selectComplexity, etc.)
are semantically aligned with the rest of the locale.
In `@apps/frontend/src/shared/i18n/locales/zh/gitlab.json`:
- Around line 183-200: Update the GitLab locale entries under the findings
object to match the established severity vocabulary in common.json: replace the
incorrect values for findings.selectCriticalHigh and findings.severity.critical
(currently "拦截器/必需" and "拦截者") with the same terms used in
apps/frontend/src/shared/i18n/locales/zh/common.json (e.g., "阻断级" for
critical/阻断级 and ensure its description "必须修复" matches severity.criticalDesc),
and verify consistency for high/medium/low keys so the GitLab MR review severity
labels exactly mirror the common.json translations.
In `@apps/frontend/src/shared/i18n/locales/zh/onboarding.json`:
- Around line 100-131: Fix the mistranslations in the onboarding memory step by
updating the three keys: change "openaiGetKey" to a clearer Chinese label like
"获取您的 OpenAI 密钥"; change "providers.ollama" from "Ollama(当地 - 免费)" to "Ollama(本地
- 免费)"; and correct "modelRecommendation" to include the missing model names and
proper punctuation, e.g. "推荐:qwen3-embedding 4b(平衡),8b(质量),0.6b(快速)" so the
recommendation reads coherently in the UI.
In `@apps/frontend/src/shared/i18n/locales/zh/settings.json`:
- Around line 366-372: The auto-detect hint for defaultBranch currently
localizes literal branch names; update the "autoDetect" value under the
defaultBranch JSON object to use the untranslated branch names "main/master"
(e.g., "自动检测(main/master)") so the helper text matches actual repo branches and
dropdowns; locate the defaultBranch -> autoDetect key in the locales file and
replace the translated "主/主" with "main/master".
In `@apps/frontend/src/shared/i18n/locales/zh/terminal.json`:
- Around line 41-46: Replace the incorrect Chinese translation for the
"baseBranch" key (currently "基地支部") with a Git-appropriate term such as "基础分支"
or "基准分支" so it aligns with the surrounding Git UI; update the "baseBranch"
value in apps/frontend/src/shared/i18n/locales/zh/terminal.json to the chosen
term and verify adjacent keys like "selectBaseBranch" and "baseBranchHelp"
remain consistent with that wording.
---
Outside diff comments:
In
`@apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsx`:
- Around line 108-112: The subtitle in InvestigationDialog currently hardcodes
"Issue #", so update the JSX inside DialogDescription to use the react-i18next
translation hook (t) to render a localized string that includes the issue number
and title (referencing selectedIssue.number and selectedIssue.title); add the
corresponding translation key (e.g. "issue.subtitle": "Issue #{{number}}:
{{title}}" and French equivalent) to both en/*.json and fr/*.json, and ensure
the code uses t('issue.subtitle', { number: selectedIssue.number, title:
selectedIssue.title }) within the DialogDescription rendering.
In
`@apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx`:
- Around line 46-50: The badge currently uses the hardcoded label lookup
GITHUB_ISSUE_STATE_LABELS[issue.state], bypassing i18n; update IssueDetail to
use react-i18next (useTranslation or t) and replace that label with the new
translation keys (e.g., t('issues.stateOpen') when issue.state === 'open' and
t('issues.stateClosed') when 'closed'), keeping the existing
GITHUB_ISSUE_STATE_COLORS[issue.state] for styling; ensure the new keys exist in
en/*.json and fr/*.json and remove the direct use of GITHUB_ISSUE_STATE_LABELS
in the Badge.
In
`@apps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsx`:
- Around line 55-64: The icon Button in IssueListItem.tsx is invisible when
focused because className sets opacity-0 and only group-hover:opacity-100 makes
it visible on hover; update its classes so keyboard focus also makes it visible
(e.g., add focus:opacity-100 and/or focus-visible:opacity-100) while keeping the
existing group-hover behavior, and ensure no other styling (e.g., pointer
events) prevents focus—locate the Button component with onClick and
aria-label={t('issues.createTask')} to apply the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7b538056-2839-440d-b2bd-4bcb6247ddda
📒 Files selected for processing (29)
apps/frontend/src/renderer/components/GitHubIssues.tsxapps/frontend/src/renderer/components/github-issues/components/EmptyStates.tsxapps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsxapps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsxapps/frontend/src/renderer/components/github-issues/components/IssueList.tsxapps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsxapps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsxapps/frontend/src/renderer/components/gitlab-issues/components/InvestigationDialog.tsxapps/frontend/src/renderer/components/gitlab-issues/components/IssueList.tsxapps/frontend/src/renderer/components/gitlab-issues/components/IssueListItem.tsxapps/frontend/src/shared/constants/i18n.tsapps/frontend/src/shared/constants/spellcheck.tsapps/frontend/src/shared/i18n/index.tsapps/frontend/src/shared/i18n/locale-coverage.test.tsapps/frontend/src/shared/i18n/locales/en/common.jsonapps/frontend/src/shared/i18n/locales/en/gitlab.jsonapps/frontend/src/shared/i18n/locales/fr/common.jsonapps/frontend/src/shared/i18n/locales/fr/gitlab.jsonapps/frontend/src/shared/i18n/locales/zh/common.jsonapps/frontend/src/shared/i18n/locales/zh/dialogs.jsonapps/frontend/src/shared/i18n/locales/zh/errors.jsonapps/frontend/src/shared/i18n/locales/zh/gitlab.jsonapps/frontend/src/shared/i18n/locales/zh/navigation.jsonapps/frontend/src/shared/i18n/locales/zh/onboarding.jsonapps/frontend/src/shared/i18n/locales/zh/settings.jsonapps/frontend/src/shared/i18n/locales/zh/taskReview.jsonapps/frontend/src/shared/i18n/locales/zh/tasks.jsonapps/frontend/src/shared/i18n/locales/zh/terminal.jsonapps/frontend/src/shared/i18n/locales/zh/welcome.json
| "notConnectedTitle": "GitHub Not Connected", | ||
| "notConnectedDescription": "Configure your GitHub token and repository in project settings to sync issues.", | ||
| "openSettings": "Open Settings", | ||
| "commentsCount": "{{count}} comments", |
There was a problem hiding this comment.
Split commentsCount into singular/plural forms.
This currently renders as 1 comments for singular counts. Please add the singular form here and mirror the same key shape in fr/zh so the locale schema stays aligned.
💬 Suggested change
- "commentsCount": "{{count}} comments",
+ "commentsCount": "{{count}} comment",
+ "commentsCount_plural": "{{count}} comments",Based on learnings, "When adding a new locale file under apps/frontend/src/shared/i18n/locales, maintain the existing structural shape (keys, nested objects, and pluralization schema) consistent with existing locales (e.g., en, fr). Do not introduce language-specific structural changes in translation PRs. If an i18n structure refactor is needed, perform it across all locales in a single dedicated PR."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "commentsCount": "{{count}} comments", | |
| "commentsCount": "{{count}} comment", | |
| "commentsCount_plural": "{{count}} comments", |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/shared/i18n/locales/en/common.json` at line 527, Replace
the current flat "commentsCount" value with a pluralized form under the same key
(use the project's ICU/pluralization format) so singular displays "1 comment"
and others "N comments"; make the identical key change for "commentsCount" in
the fr and zh locale files so the locale schema stays aligned across languages
and no structural changes are introduced elsewhere.
| "findings": { | ||
| "summary": "已选择", | ||
| "selectCriticalHigh": "选择拦截器/必需", | ||
| "selectAll": "选择全部", | ||
| "clear": "清除", | ||
| "noIssues": "没有发现问题!代码看起来不错。", | ||
| "suggestedFix": "建议修复:", | ||
| "posted": "已发布", | ||
| "severity": { | ||
| "critical": "拦截者", | ||
| "criticalDesc": "必须修复", | ||
| "high": "必须修复", | ||
| "highDesc": "应该修复", | ||
| "medium": "推荐", | ||
| "mediumDesc": "提高质量", | ||
| "low": "建议", | ||
| "lowDesc": "考虑" | ||
| }, |
There was a problem hiding this comment.
Fix the GitLab findings severity vocabulary before enabling zh.
selectCriticalHigh / severity.critical are currently translated as 拦截器/必需 and 拦截者, which changes the meaning of the MR review severity scale. The same scale is already rendered as 阻断级 / 必须修复 / 建议修复 / 建议 in apps/frontend/src/shared/i18n/locales/zh/common.json, so users will see contradictory severity terms across GitHub and GitLab review flows.
💡 Suggested fix
"findings": {
"summary": "已选择",
- "selectCriticalHigh": "选择拦截器/必需",
+ "selectCriticalHigh": "选择阻断级/必须修复",
"selectAll": "选择全部",
"clear": "清除",
"noIssues": "没有发现问题!代码看起来不错。",
"suggestedFix": "建议修复:",
"posted": "已发布",
"severity": {
- "critical": "拦截者",
+ "critical": "阻断级",
"criticalDesc": "必须修复",
"high": "必须修复",
"highDesc": "应该修复",
- "medium": "推荐",
+ "medium": "建议修复",
"mediumDesc": "提高质量",
"low": "建议",
"lowDesc": "考虑"
},🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/shared/i18n/locales/zh/gitlab.json` around lines 183 - 200,
Update the GitLab locale entries under the findings object to match the
established severity vocabulary in common.json: replace the incorrect values for
findings.selectCriticalHigh and findings.severity.critical (currently "拦截器/必需"
and "拦截者") with the same terms used in
apps/frontend/src/shared/i18n/locales/zh/common.json (e.g., "阻断级" for
critical/阻断级 and ensure its description "必须修复" matches severity.criticalDesc),
and verify consistency for high/medium/low keys so the GitLab MR review severity
labels exactly mirror the common.json translations.
| "openaiGetKey": "获取您的钥匙", | ||
| "voyageApiKey": "Voyage AI API 密钥", | ||
| "voyageApiKeyDescription": "Voyage AI 嵌入所需", | ||
| "voyageEmbeddingModel": "嵌入模型", | ||
| "googleApiKey": "Google AI API 密钥", | ||
| "googleApiKeyDescription": "Google AI 嵌入所需", | ||
| "azureConfig": "Azure OpenAI 配置", | ||
| "azureApiKey": "API密钥", | ||
| "azureBaseUrl": "基本网址", | ||
| "azureEmbeddingDeployment": "嵌入部署名称", | ||
| "memoryInfo": "内存存储有关代码库的发现、模式和洞察,因此未来的会话从已加载的上下文开始。不需要 Docker - 使用嵌入式数据库。", | ||
| "learnMore": "了解有关内存的更多信息", | ||
| "back": "后退", | ||
| "skip": "跳过", | ||
| "saving": "保存...", | ||
| "saveAndContinue": "保存并继续", | ||
| "providers": { | ||
| "ollama": "Ollama(当地 - 免费)", | ||
| "openai": "OpenAI", | ||
| "voyage": "Voyage AI", | ||
| "google": "Google AI", | ||
| "azure": "Azure OpenAI" | ||
| }, | ||
| "ollamaConfig": "Ollama配置", | ||
| "checking": "检查...", | ||
| "connected": "已连接", | ||
| "notRunning": "未运行", | ||
| "baseUrl": "基本网址", | ||
| "embeddingModel": "嵌入模型", | ||
| "embeddingDim": "嵌入维度", | ||
| "embeddingDimDescription": "Ollama 嵌入所需(例如 nomic-embed-text 为 768)", | ||
| "modelRecommendation": "推荐:qwen3-embedding:4b(平衡),:8b(质量),:0.6b(快速)" |
There was a problem hiding this comment.
Fix the mistranslated setup copy in the memory step.
A few strings here will read broken in the onboarding UI: openaiGetKey says “获取您的钥匙”, providers.ollama uses “当地 - 免费”, and modelRecommendation is malformed (:8b / :0.6b without the model name). These should be corrected before exposing zh as a supported language.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/shared/i18n/locales/zh/onboarding.json` around lines 100 -
131, Fix the mistranslations in the onboarding memory step by updating the three
keys: change "openaiGetKey" to a clearer Chinese label like "获取您的 OpenAI 密钥";
change "providers.ollama" from "Ollama(当地 - 免费)" to "Ollama(本地 - 免费)"; and
correct "modelRecommendation" to include the missing model names and proper
punctuation, e.g. "推荐:qwen3-embedding 4b(平衡),8b(质量),0.6b(快速)" so the
recommendation reads coherently in the UI.
| "defaultBranch": { | ||
| "label": "默认分支", | ||
| "description": "用于创建任务工作树的基础分支", | ||
| "autoDetect": "自动检测(主/主)", | ||
| "searchPlaceholder": "搜索分支...", | ||
| "noBranchesFound": "没有找到分支", | ||
| "selectedBranchHelp": "所有新任务将从 {{branch}} 分支" |
There was a problem hiding this comment.
Keep literal branch names unlocalized in the auto-detect hint.
main/master are actual branch names. Translating them to 主/主 makes this helper text misleading and harder to match with what users see in their repositories and branch dropdowns.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/shared/i18n/locales/zh/settings.json` around lines 366 -
372, The auto-detect hint for defaultBranch currently localizes literal branch
names; update the "autoDetect" value under the defaultBranch JSON object to use
the untranslated branch names "main/master" (e.g., "自动检测(main/master)") so the
helper text matches actual repo branches and dropdowns; locate the defaultBranch
-> autoDetect key in the locales file and replace the translated "主/主" with
"main/master".
| "baseBranch": "基地支部", | ||
| "selectBaseBranch": "选择基础分支...", | ||
| "searchBranch": "搜索分支...", | ||
| "noBranchFound": "没有找到分支", | ||
| "useProjectDefault": "使用项目默认值 ({{branch}})", | ||
| "baseBranchHelp": "用于创建工作树的分支", |
There was a problem hiding this comment.
Use Git branch terminology for baseBranch.
“基地支部” is not a valid translation for a Git base branch and will be confusing in the worktree flow. This should stay as something like “基础分支” / “基准分支” so it matches the surrounding Git UI.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/shared/i18n/locales/zh/terminal.json` around lines 41 - 46,
Replace the incorrect Chinese translation for the "baseBranch" key (currently
"基地支部") with a Git-appropriate term such as "基础分支" or "基准分支" so it aligns with
the surrounding Git UI; update the "baseBranch" value in
apps/frontend/src/shared/i18n/locales/zh/terminal.json to the chosen term and
verify adjacent keys like "selectBaseBranch" and "baseBranchHelp" remain
consistent with that wording.
…mponents - Replace hardcoded "Issue #" subtitle with i18n key in InvestigationDialog - Use i18n object lookup instead of GITHUB_ISSUE_STATE_LABELS in IssueDetail badge - Replace nested ternary with object lookup in GitHub/GitLab IssueListItem - Add focus:opacity-100 for keyboard accessibility on investigate button - Add singular/plural forms for commentsCount and openCount across en/fr/zh - Make en/fr delta test informational instead of blocking CI - Fix zh translations: 专题标题→功能标题, 复杂→复杂度 - Remove unused GITHUB_ISSUE_STATE_LABELS imports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx`:
- Around line 143-152: The JSX in IssueDetail.tsx currently concatenates a colon
and taskId outside i18n (uses {t('issues.taskId')}: {taskId}), preventing
locale-specific ordering; change both occurrences to use a single translation
with interpolation (e.g., t('issues.taskIdValue', { taskId })) and add the
corresponding key "issues.taskIdValue" to en/common.json, fr/common.json, and
zh/common.json (value examples: "Task ID: {{taskId}}", localized equivalents) so
all user-facing text uses react-i18next and supports locale-specific phrase
structure.
In
`@apps/frontend/src/renderer/components/gitlab-issues/components/IssueListItem.tsx`:
- Line 44: The component IssueListItem.tsx currently falls back to
GITLAB_ISSUE_STATE_LABELS which contains hardcoded English labels; update the
expression to resolve state labels via react-i18next only (use
t('states.opened') and t('states.closed') for known "opened"/"closed" states)
and remove the GITLAB_ISSUE_STATE_LABELS fallback so that the only fallback is
the raw issue.state for unknown values; also add the corresponding keys
("states.opened" and "states.closed") to both the en and fr translation JSON
files so translations exist.
In `@apps/frontend/src/shared/i18n/locale-coverage.test.ts`:
- Around line 36-76: The test currently hardcodes the namespace lists in
enLocales, frLocales, and zhLocales which can drift from the actual registered
locale namespaces; update the test to derive the namespace inventory from a
single source of truth (for example import the exported locales map or
AVAILABLE_LANGUAGES/registered locales index used by the app) and build
enLocales/frLocales/zhLocales dynamically from that list, then add an explicit
assertion that the keys of each locale object match the derived namespace list
(so if a new namespace file is added the test will fail until all locales
include it). Reference enLocales, frLocales, zhLocales and the app's central
locales export (e.g. AVAILABLE_LANGUAGES or the locales registry) to implement
this change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5b14d247-5e63-4e21-b73a-53214ef88d3d
📒 Files selected for processing (10)
apps/frontend/src/renderer/components/github-issues/components/InvestigationDialog.tsxapps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsxapps/frontend/src/renderer/components/github-issues/components/IssueListItem.tsxapps/frontend/src/renderer/components/gitlab-issues/components/IssueListItem.tsxapps/frontend/src/shared/i18n/locale-coverage.test.tsapps/frontend/src/shared/i18n/locales/en/common.jsonapps/frontend/src/shared/i18n/locales/fr/common.jsonapps/frontend/src/shared/i18n/locales/zh/common.jsonapps/frontend/src/shared/i18n/locales/zh/dialogs.jsonapps/frontend/src/shared/i18n/locales/zh/tasks.json
| <span className="text-xs text-muted-foreground"> | ||
| Task ID: {taskId} | ||
| {t('issues.taskId')}: {taskId} | ||
| </span> | ||
| </div> | ||
| </> | ||
| ) : ( | ||
| <div className="flex items-center gap-2"> | ||
| <span className="text-xs text-muted-foreground"> | ||
| Task ID: {taskId} | ||
| {t('issues.taskId')}: {taskId} | ||
| </span> |
There was a problem hiding this comment.
Localize the full task-ID phrase.
Lines 144 and 151 still hardcode the : {taskId} layout outside i18n, so the phrase structure cannot vary by locale. Move the whole string into a translation key with interpolation, e.g. t('issues.taskIdValue', { taskId }), and add that key to en/common.json, fr/common.json, and zh/common.json.
💡 Suggested change
- {t('issues.taskId')}: {taskId}
+ {t('issues.taskIdValue', { taskId })}- {t('issues.taskId')}: {taskId}
+ {t('issues.taskIdValue', { taskId })}As per coding guidelines, "All frontend user-facing text must use react-i18next translation keys. Never hardcode strings in JSX/TSX. Add keys to both en/*.json and fr/*.json translation files."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@apps/frontend/src/renderer/components/github-issues/components/IssueDetail.tsx`
around lines 143 - 152, The JSX in IssueDetail.tsx currently concatenates a
colon and taskId outside i18n (uses {t('issues.taskId')}: {taskId}), preventing
locale-specific ordering; change both occurrences to use a single translation
with interpolation (e.g., t('issues.taskIdValue', { taskId })) and add the
corresponding key "issues.taskIdValue" to en/common.json, fr/common.json, and
zh/common.json (value examples: "Task ID: {{taskId}}", localized equivalents) so
all user-facing text uses react-i18next and supports locale-specific phrase
structure.
| className={`text-xs ${GITLAB_ISSUE_STATE_COLORS[issue.state] || ''}`} | ||
| > | ||
| {GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state} | ||
| {{ opened: t('states.opened'), closed: t('states.closed') }[issue.state] ?? (GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state)} |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Drop the hardcoded English fallback for issue states.
This path still renders Open / Closed from GITLAB_ISSUE_STATE_LABELS, so the touched component keeps user-facing text in TSX after the i18n migration. Resolve the label from the locale directly and only fall back to issue.state for unknown states.
Proposed fix
- {{ opened: t('states.opened'), closed: t('states.closed') }[issue.state] ?? (GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state)}
+ {t(`states.${issue.state}`, { defaultValue: issue.state })}As per coding guidelines, "All frontend user-facing text must use react-i18next translation keys. Never hardcode strings in JSX/TSX. Add keys to both en/*.json and fr/*.json translation files."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {{ opened: t('states.opened'), closed: t('states.closed') }[issue.state] ?? (GITLAB_ISSUE_STATE_LABELS[issue.state] || issue.state)} | |
| {t(`states.${issue.state}`, { defaultValue: issue.state })} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@apps/frontend/src/renderer/components/gitlab-issues/components/IssueListItem.tsx`
at line 44, The component IssueListItem.tsx currently falls back to
GITLAB_ISSUE_STATE_LABELS which contains hardcoded English labels; update the
expression to resolve state labels via react-i18next only (use
t('states.opened') and t('states.closed') for known "opened"/"closed" states)
and remove the GITLAB_ISSUE_STATE_LABELS fallback so that the only fallback is
the raw issue.state for unknown values; also add the corresponding keys
("states.opened" and "states.closed") to both the en and fr translation JSON
files so translations exist.
| const enLocales = { | ||
| common: enCommon, | ||
| dialogs: enDialogs, | ||
| errors: enErrors, | ||
| gitlab: enGitlab, | ||
| navigation: enNavigation, | ||
| onboarding: enOnboarding, | ||
| settings: enSettings, | ||
| taskReview: enTaskReview, | ||
| tasks: enTasks, | ||
| terminal: enTerminal, | ||
| welcome: enWelcome | ||
| } as const; | ||
|
|
||
| const frLocales = { | ||
| common: frCommon, | ||
| dialogs: frDialogs, | ||
| errors: frErrors, | ||
| gitlab: frGitlab, | ||
| navigation: frNavigation, | ||
| onboarding: frOnboarding, | ||
| settings: frSettings, | ||
| taskReview: frTaskReview, | ||
| tasks: frTasks, | ||
| terminal: frTerminal, | ||
| welcome: frWelcome | ||
| } as const; | ||
|
|
||
| const zhLocales = { | ||
| common: zhCommon, | ||
| dialogs: zhDialogs, | ||
| errors: zhErrors, | ||
| gitlab: zhGitlab, | ||
| navigation: zhNavigation, | ||
| onboarding: zhOnboarding, | ||
| settings: zhSettings, | ||
| taskReview: zhTaskReview, | ||
| tasks: zhTasks, | ||
| terminal: zhTerminal, | ||
| welcome: zhWelcome | ||
| } as const; |
There was a problem hiding this comment.
Don’t hardcode the tested namespace inventory here.
This suite only validates the namespaces manually listed in enLocales, frLocales, and zhLocales. If a new locale namespace is added later but not added to these objects, the test still passes and gives a false “coverage is complete” signal. Please derive the namespace list from a single source of truth, or add an explicit guard that the test inventory matches the registered locale namespaces/files.
Based on learnings, "Before adding a new language to AVAILABLE_LANGUAGES, ensure UI translations exist and are complete in apps/frontend/src/shared/i18n/locales. Do not advertise official support for a language until its locale files are fully translated and validated, to avoid user-facing issues."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/shared/i18n/locale-coverage.test.ts` around lines 36 - 76,
The test currently hardcodes the namespace lists in enLocales, frLocales, and
zhLocales which can drift from the actual registered locale namespaces; update
the test to derive the namespace inventory from a single source of truth (for
example import the exported locales map or AVAILABLE_LANGUAGES/registered
locales index used by the app) and build enLocales/frLocales/zhLocales
dynamically from that list, then add an explicit assertion that the keys of each
locale object match the derived namespace list (so if a new namespace file is
added the test will fail until all locales include it). Reference enLocales,
frLocales, zhLocales and the app's central locales export (e.g.
AVAILABLE_LANGUAGES or the locales registry) to implement this change.
Summary
IssueDetail,IssueList,IssueListHeader,IssueListItem,InvestigationDialog,EmptyStates) into i18n translation keysi18n.tsconfig,spellcheck.tsmapping, and the language selector (i18n.tsconstants)stateOpen/stateClosed) from filter labels (filterOpen/filterClosed) for correct singular/plural translations across languageslocale-coverage.test.ts— a Vitest test that verifies key alignment, placeholder consistency, and readability across all localesChanges
locales/zh/*.json(11 files)GitHubIssues.tsx,github-issues/components/*.tsx,gitlab-issues/components/*.tsxi18n.ts,index.ts,spellcheck.tsen/common.json,en/gitlab.json,fr/common.json,fr/gitlab.jsonlocale-coverage.test.tsTest plan
locale-coverage.test.tspasses — verifies zh keys match en keys, placeholders are consistent, and no empty/garbled strings exist🤖 Generated with Claude Code
Summary by CodeRabbit