Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: add Chinese i18n support to high-priority components
- Add Chinese translations for ErrorBoundary error messages
- Add Chinese translations for Topbar status indicators and messages
- Add Chinese translations for session component common UI text
- Update ErrorBoundary component to use i18n with useTranslation
- Update Topbar component to use i18n with useTranslation
- Expand zh-CN.json with 30+ new translation keys
- Maintain English as default language with fallback support

This improves user experience for Chinese-speaking users by translating
the most frequently used error and status messages in the application.

Addresses priority P1 components identified in translation audit.
  • Loading branch information
zhu976 committed Dec 2, 2025
commit b3a77c0aadae0de7ce3955585f2a11554ad66089
14 changes: 8 additions & 6 deletions src/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { Component, ReactNode } from "react";
import { AlertCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import i18n from "@/i18n";

interface ErrorBoundaryProps {
children: ReactNode;
Expand Down Expand Up @@ -43,22 +44,23 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
return this.props.fallback(this.state.error, this.reset);
}

// Default error UI
// Default error UI with i18n
const t = i18n.t.bind(i18n);
return (
<div className="flex items-center justify-center min-h-[200px] p-4">
<Card className="max-w-md w-full">
<CardContent className="p-6">
<div className="flex items-start gap-4">
<AlertCircle className="h-8 w-8 text-destructive flex-shrink-0 mt-0.5" />
<div className="flex-1 space-y-2">
<h3 className="text-lg font-semibold">Something went wrong</h3>
<h3 className="text-lg font-semibold">{t('errorBoundary.somethingWentWrong')}</h3>
<p className="text-sm text-muted-foreground">
An error occurred while rendering this component.
{t('errorBoundary.errorOccurred')}
</p>
{this.state.error.message && (
<details className="mt-2">
<summary className="text-sm cursor-pointer text-muted-foreground hover:text-foreground">
Error details
{t('errorBoundary.errorDetails')}
</summary>
<pre className="mt-2 text-xs bg-muted p-2 rounded overflow-auto">
{this.state.error.message}
Expand All @@ -70,7 +72,7 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
size="sm"
className="mt-4"
>
Try again
{t('errorBoundary.tryAgain')}
</Button>
</div>
</div>
Expand All @@ -82,4 +84,4 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt

return this.props.children;
}
}
}
20 changes: 11 additions & 9 deletions src/components/Topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Button } from "@/components/ui/button";
import { Popover } from "@/components/ui/popover";
import { api, type ClaudeVersionStatus } from "@/lib/api";
import { cn } from "@/lib/utils";
import { useTranslation } from "react-i18next";

interface TopbarProps {
/**
Expand Down Expand Up @@ -52,6 +53,7 @@ export const Topbar: React.FC<TopbarProps> = ({
onSettingsClick,
className,
}) => {
const { t } = useTranslation();
const [versionStatus, setVersionStatus] = useState<ClaudeVersionStatus | null>(null);
const [checking, setChecking] = useState(true);

Expand All @@ -72,10 +74,10 @@ export const Topbar: React.FC<TopbarProps> = ({
window.dispatchEvent(new CustomEvent('claude-not-found'));
}
} catch (err) {
console.error("Failed to check Claude version:", err);
console.error(t('topbar.failedToCheckVersion'), err);
setVersionStatus({
is_installed: false,
output: "Failed to check version",
output: t('topbar.failedToCheckVersion'),
});
} finally {
setChecking(false);
Expand All @@ -87,7 +89,7 @@ export const Topbar: React.FC<TopbarProps> = ({
return (
<div className="flex items-center space-x-2 text-xs">
<Circle className="h-3 w-3 animate-pulse text-muted-foreground" />
<span className="text-muted-foreground">Checking...</span>
<span className="text-muted-foreground">{t('topbar.checking')}</span>
</div>
);
}
Expand All @@ -112,8 +114,8 @@ export const Topbar: React.FC<TopbarProps> = ({
/>
<span>
{versionStatus.is_installed && versionStatus.version
? `Claude Code v${versionStatus.version}`
: "Claude Code"}
? `${t('topbar.claudeCode')} ${t('topbar.version', { version: versionStatus.version })}`
: t('topbar.claudeCode')}
</span>
</div>
</Button>
Expand All @@ -125,7 +127,7 @@ export const Topbar: React.FC<TopbarProps> = ({
trigger={statusContent}
content={
<div className="space-y-3 max-w-xs">
<p className="text-sm font-medium">Claude Code not found</p>
<p className="text-sm font-medium">{t('topbar.claudeCodeNotFound')}</p>
<div className="rounded-md bg-muted p-3">
<pre className="text-xs font-mono whitespace-pre-wrap">
{versionStatus.output}
Expand All @@ -137,15 +139,15 @@ export const Topbar: React.FC<TopbarProps> = ({
className="w-full"
onClick={onSettingsClick}
>
Select Claude Installation
{t('topbar.selectInstallation')}
</Button>
<a
href="https://www.anthropic.com/claude-code"
target="_blank"
rel="noopener noreferrer"
className="flex items-center space-x-1 text-xs text-primary hover:underline"
>
<span>Install Claude Code</span>
<span>{t('topbar.installClaudeCode')}</span>
<ExternalLink className="h-3 w-3" />
</a>
</div>
Expand Down Expand Up @@ -175,4 +177,4 @@ export const Topbar: React.FC<TopbarProps> = ({
<div></div>
</motion.div>
);
};
};
31 changes: 30 additions & 1 deletion src/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,5 +373,34 @@
"totalTokens": "总令牌数:",
"totalTokensFormat": "{{total}}(输入 {{input}},输出 {{output}})"
}
},
"errorBoundary": {
"somethingWentWrong": "出错了",
"errorOccurred": "呈现此组件时出现错误",
"errorDetails": "错误详情",
"tryAgain": "重试"
},
"topbar": {
"checking": "检查中...",
"claudeCode": "Claude Code",
"claudeCodeNotFound": "未找到 Claude Code",
"failedToCheckVersion": "检查版本失败",
"selectInstallation": "选择 Claude 安装路径",
"installClaudeCode": "安装 Claude Code",
"version": "v{{version}}"
},
"sessionComponent": {
"loading": "加载中...",
"error": "错误",
"errorOccurred": "发生错误",
"failedToLoad": "加载失败",
"checkingStatus": "检查状态中...",
"running": "运行中",
"completed": "已完成",
"stopped": "已停止",
"noProjectPath": "未选择项目路径",
"selectProject": "请选择项目路径",
"sendMessage": "发送消息",
"typeMessage": "输入消息..."
}
}
}