修复缺失的汉化
Some checks are pending
Build Test / Build Test (${{ matrix.platform.name }}) (map[name:Linux os:ubuntu-latest rust-target:x86_64-unknown-linux-gnu]) (push) Waiting to run
Build Test / Build Test (${{ matrix.platform.name }}) (map[name:Windows os:windows-latest rust-target:x86_64-pc-windows-msvc]) (push) Waiting to run
Build Test / Build Test (${{ matrix.platform.name }}) (map[name:macOS os:macos-latest rust-target:x86_64-apple-darwin]) (push) Waiting to run
Build Test / Build Test Summary (push) Blocked by required conditions
Some checks are pending
Build Test / Build Test (${{ matrix.platform.name }}) (map[name:Linux os:ubuntu-latest rust-target:x86_64-unknown-linux-gnu]) (push) Waiting to run
Build Test / Build Test (${{ matrix.platform.name }}) (map[name:Windows os:windows-latest rust-target:x86_64-pc-windows-msvc]) (push) Waiting to run
Build Test / Build Test (${{ matrix.platform.name }}) (map[name:macOS os:macos-latest rust-target:x86_64-apple-darwin]) (push) Waiting to run
Build Test / Build Test Summary (push) Blocked by required conditions
This commit is contained in:
@@ -7,6 +7,7 @@ import { Badge } from "@/components/ui/badge";
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||
import { Loader2, Terminal, Package, Check } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface ClaudeVersionSelectorProps {
|
||||
/**
|
||||
@@ -52,6 +53,7 @@ export const ClaudeVersionSelector: React.FC<ClaudeVersionSelectorProps> = ({
|
||||
onSave,
|
||||
isSaving = false,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [installations, setInstallations] = useState<ClaudeInstallation[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -91,7 +93,7 @@ export const ClaudeVersionSelector: React.FC<ClaudeVersionSelectorProps> = ({
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to load Claude installations:", err);
|
||||
setError(err instanceof Error ? err.message : "Failed to load Claude installations");
|
||||
setError(err instanceof Error ? err.message : t('settings.claudeInstallationLoadFailed'));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -140,7 +142,7 @@ export const ClaudeVersionSelector: React.FC<ClaudeVersionSelectorProps> = ({
|
||||
return (
|
||||
<Card className={cn("p-4", className)}>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
No Claude Code installations found on your system.
|
||||
{t('settings.noClaudeInstallations')}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
@@ -148,65 +150,60 @@ export const ClaudeVersionSelector: React.FC<ClaudeVersionSelectorProps> = ({
|
||||
|
||||
return (
|
||||
<div className={cn("space-y-4", className)}>
|
||||
<div>
|
||||
<Label className="text-sm font-medium mb-3 block">
|
||||
Select Claude Code Installation
|
||||
</Label>
|
||||
<RadioGroup
|
||||
value={selectedInstallation?.path}
|
||||
onValueChange={(value: string) => {
|
||||
const installation = installations.find(i => i.path === value);
|
||||
if (installation) {
|
||||
handleSelect(installation);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
{installations.map((installation) => (
|
||||
<Card
|
||||
key={installation.path}
|
||||
className={cn(
|
||||
"relative cursor-pointer transition-colors",
|
||||
selectedInstallation?.path === installation.path
|
||||
? "border-primary"
|
||||
: "hover:border-muted-foreground/50"
|
||||
)}
|
||||
onClick={() => handleSelect(installation)}
|
||||
>
|
||||
<div className="flex items-start p-4">
|
||||
<RadioGroupItem
|
||||
value={installation.path}
|
||||
id={installation.path}
|
||||
className="mt-1"
|
||||
/>
|
||||
<div className="ml-3 flex-1">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
{getSourceIcon(installation.source)}
|
||||
<span className="font-medium text-sm">
|
||||
{getSourceLabel(installation.source)}
|
||||
</span>
|
||||
{installation.version && (
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
v{installation.version}
|
||||
</Badge>
|
||||
)}
|
||||
{selectedPath === installation.path && (
|
||||
<Badge variant="default" className="text-xs">
|
||||
<Check className="w-3 h-3 mr-1" />
|
||||
Current
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground font-mono break-all">
|
||||
{installation.path}
|
||||
</p>
|
||||
<RadioGroup
|
||||
value={selectedInstallation?.path}
|
||||
onValueChange={(value: string) => {
|
||||
const installation = installations.find(i => i.path === value);
|
||||
if (installation) {
|
||||
handleSelect(installation);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
{installations.map((installation) => (
|
||||
<Card
|
||||
key={installation.path}
|
||||
className={cn(
|
||||
"relative cursor-pointer transition-colors",
|
||||
selectedInstallation?.path === installation.path
|
||||
? "border-primary"
|
||||
: "hover:border-muted-foreground/50"
|
||||
)}
|
||||
onClick={() => handleSelect(installation)}
|
||||
>
|
||||
<div className="flex items-start p-4">
|
||||
<RadioGroupItem
|
||||
value={installation.path}
|
||||
id={installation.path}
|
||||
className="mt-1"
|
||||
/>
|
||||
<div className="ml-3 flex-1">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
{getSourceIcon(installation.source)}
|
||||
<span className="font-medium text-sm">
|
||||
{getSourceLabel(installation.source)}
|
||||
</span>
|
||||
{installation.version && (
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
v{installation.version}
|
||||
</Badge>
|
||||
)}
|
||||
{selectedPath === installation.path && (
|
||||
<Badge variant="default" className="text-xs">
|
||||
<Check className="w-3 h-3 mr-1" />
|
||||
{t('settings.current')}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground font-mono break-all">
|
||||
{installation.path}
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</RadioGroup>
|
||||
|
||||
{showSaveButton && onSave && (
|
||||
<div className="flex justify-end">
|
||||
@@ -218,14 +215,14 @@ export const ClaudeVersionSelector: React.FC<ClaudeVersionSelectorProps> = ({
|
||||
{isSaving ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
Saving...
|
||||
{t('common.saving')}
|
||||
</>
|
||||
) : (
|
||||
"Save Selection"
|
||||
t('settings.saveSelection')
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
@@ -266,14 +266,14 @@ export const MCPAddServer: React.FC<MCPAddServerProps> = ({
|
||||
</div>
|
||||
|
||||
<Tabs value={transport} onValueChange={(v) => setTransport(v as "stdio" | "sse")}>
|
||||
<TabsList className="grid w-full grid-cols-2 max-w-sm mb-6">
|
||||
<TabsTrigger value="stdio" className="gap-2">
|
||||
<Terminal className="h-4 w-4 text-amber-500" />
|
||||
Stdio
|
||||
<TabsList className="grid w-full grid-cols-2 max-w-xs mb-6">
|
||||
<TabsTrigger value="stdio" className="gap-2 min-w-0 flex-1">
|
||||
<Terminal className="h-4 w-4 text-amber-500 flex-shrink-0" />
|
||||
<span className="truncate">Stdio</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="sse" className="gap-2">
|
||||
<Globe className="h-4 w-4 text-emerald-500" />
|
||||
SSE
|
||||
<TabsTrigger value="sse" className="gap-2 min-w-0 flex-1">
|
||||
<Globe className="h-4 w-4 text-emerald-500 flex-shrink-0" />
|
||||
<span className="truncate">SSE</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
|
@@ -151,18 +151,18 @@ export const MCPManager: React.FC<MCPManagerProps> = ({
|
||||
) : (
|
||||
<div className="flex-1 overflow-y-auto p-4">
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-6">
|
||||
<TabsList className="grid w-full max-w-md grid-cols-3">
|
||||
<TabsTrigger value="servers" className="gap-2">
|
||||
<Network className="h-4 w-4 text-blue-500" />
|
||||
{t('mcp.servers')}
|
||||
<TabsList className="grid w-full max-w-lg grid-cols-3">
|
||||
<TabsTrigger value="servers" className="gap-2 min-w-0 flex-1">
|
||||
<Network className="h-4 w-4 text-blue-500 flex-shrink-0" />
|
||||
<span className="truncate">{t('mcp.servers')}</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="add" className="gap-2">
|
||||
<Plus className="h-4 w-4 text-green-500" />
|
||||
{t('mcp.addServer')}
|
||||
<TabsTrigger value="add" className="gap-2 min-w-0 flex-1">
|
||||
<Plus className="h-4 w-4 text-green-500 flex-shrink-0" />
|
||||
<span className="truncate">{t('mcp.addServer')}</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="import" className="gap-2">
|
||||
<Download className="h-4 w-4 text-purple-500" />
|
||||
{t('mcp.importExport')}
|
||||
<TabsTrigger value="import" className="gap-2 min-w-0 flex-1">
|
||||
<Download className="h-4 w-4 text-purple-500 flex-shrink-0" />
|
||||
<span className="truncate">{t('mcp.importExport')}</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
|
@@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Toast, ToastContainer } from "@/components/ui/toast";
|
||||
import { api } from "@/lib/api";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface MarkdownEditorProps {
|
||||
/**
|
||||
@@ -28,6 +29,7 @@ export const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
|
||||
onBack,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [content, setContent] = useState<string>("");
|
||||
const [originalContent, setOriginalContent] = useState<string>("");
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -51,7 +53,7 @@ export const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
|
||||
setOriginalContent(prompt);
|
||||
} catch (err) {
|
||||
console.error("Failed to load system prompt:", err);
|
||||
setError("Failed to load CLAUDE.md file");
|
||||
setError(t('markdownEditor.loadFailed'));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -64,11 +66,11 @@ export const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
|
||||
setToast(null);
|
||||
await api.saveSystemPrompt(content);
|
||||
setOriginalContent(content);
|
||||
setToast({ message: "CLAUDE.md saved successfully", type: "success" });
|
||||
setToast({ message: t('markdownEditor.saveSuccess'), type: "success" });
|
||||
} catch (err) {
|
||||
console.error("Failed to save system prompt:", err);
|
||||
setError("Failed to save CLAUDE.md file");
|
||||
setToast({ message: "Failed to save CLAUDE.md", type: "error" });
|
||||
setError(t('markdownEditor.saveFailed'));
|
||||
setToast({ message: t('markdownEditor.saveFailed'), type: "error" });
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
@@ -77,7 +79,7 @@ export const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
|
||||
const handleBack = () => {
|
||||
if (hasChanges) {
|
||||
const confirmLeave = window.confirm(
|
||||
"You have unsaved changes. Are you sure you want to leave?"
|
||||
t('markdownEditor.unsavedChanges')
|
||||
);
|
||||
if (!confirmLeave) return;
|
||||
}
|
||||
@@ -106,7 +108,7 @@ export const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold">CLAUDE.md</h2>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Edit your Claude Code system prompt
|
||||
{t('markdownEditor.description')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -121,7 +123,7 @@ export const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
|
||||
) : (
|
||||
<Save className="mr-2 h-4 w-4" />
|
||||
)}
|
||||
{saving ? "Saving..." : "Save"}
|
||||
{saving ? t('common.saving') : t('common.save')}
|
||||
</Button>
|
||||
</motion.div>
|
||||
|
||||
|
@@ -432,7 +432,7 @@ export const Settings: React.FC<SettingsProps> = ({
|
||||
{/* Claude Binary Path Selector */}
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label className="text-sm font-medium mb-2 block">{t('settings.claudeInstallation')}</Label>
|
||||
<Label className="text-sm font-medium mb-2 block">{t('settings.selectClaudeInstallation')}</Label>
|
||||
<p className="text-xs text-muted-foreground mb-4">
|
||||
{t('settings.claudeInstallationDesc')}
|
||||
</p>
|
||||
|
@@ -210,7 +210,12 @@
|
||||
"chatRetention": "Chat Transcript Retention (days)",
|
||||
"chatRetentionDesc": "How long to retain chat transcripts locally (default: 30 days)",
|
||||
"claudeInstallation": "Claude Code Installation",
|
||||
"selectClaudeInstallation": "Select Claude Code Installation",
|
||||
"claudeInstallationDesc": "Select which Claude Code installation to use",
|
||||
"current": "Current",
|
||||
"noClaudeInstallations": "No Claude Code installations found on your system",
|
||||
"claudeInstallationLoadFailed": "Failed to load Claude installations",
|
||||
"saveSelection": "Save Selection",
|
||||
"permissionRules": "Permission Rules",
|
||||
"permissionRulesDesc": "Control which tools Claude Code can use without manual approval",
|
||||
"allowRules": "Allow Rules",
|
||||
@@ -379,6 +384,13 @@
|
||||
"auto": "Auto",
|
||||
"fullscreen": "Fullscreen"
|
||||
},
|
||||
"markdownEditor": {
|
||||
"description": "Edit your Claude Code system prompt",
|
||||
"loadFailed": "Failed to load CLAUDE.md file",
|
||||
"saveSuccess": "CLAUDE.md saved successfully",
|
||||
"saveFailed": "Failed to save CLAUDE.md",
|
||||
"unsavedChanges": "You have unsaved changes. Are you sure you want to leave?"
|
||||
},
|
||||
"errors": {
|
||||
"loadProjectsFailed": "Failed to load projects. Please ensure ~/.claude directory exists.",
|
||||
"loadSessionsFailed": "Failed to load sessions for this project."
|
||||
|
@@ -162,7 +162,6 @@
|
||||
"outputCopiedAsJsonl": "输出已复制为 JSONL",
|
||||
"outputRefreshed": "输出已刷新",
|
||||
"agentExecutionCompleted": "智能体执行完成",
|
||||
"queuedPrompts": "排队提示({{count}})",
|
||||
"scrollToTop": "滚动到顶部",
|
||||
"scrollToBottom": "滚动到底部",
|
||||
"tokens": "标记",
|
||||
@@ -231,7 +230,12 @@
|
||||
"chatRetention": "聊天记录保留期(天)",
|
||||
"chatRetentionDesc": "本地保留聊天记录的时长(默认:30天)",
|
||||
"claudeInstallation": "Claude Code 安装",
|
||||
"selectClaudeInstallation": "选择 Claude Code 安装",
|
||||
"claudeInstallationDesc": "选择要使用的 Claude Code 安装",
|
||||
"current": "当前",
|
||||
"noClaudeInstallations": "在您的系统上未找到 Claude Code 安装",
|
||||
"claudeInstallationLoadFailed": "加载 Claude 安装失败",
|
||||
"saveSelection": "保存选择",
|
||||
"permissionRules": "权限规则",
|
||||
"permissionRulesDesc": "控制 Claude Code 无需手动批准即可使用的工具",
|
||||
"allowRules": "允许规则",
|
||||
@@ -268,11 +272,17 @@
|
||||
"modelNameDesc": "自定义模型名称",
|
||||
"costWarningsDesc": "禁用成本警告 (1)"
|
||||
},
|
||||
"markdownEditor": {
|
||||
"description": "编辑您的 Claude Code 系统提示",
|
||||
"loadFailed": "加载 CLAUDE.md 文件失败",
|
||||
"saveSuccess": "CLAUDE.md 保存成功",
|
||||
"saveFailed": "保存 CLAUDE.md 失败",
|
||||
"unsavedChanges": "您有未保存的更改。确定要离开吗?"
|
||||
},
|
||||
"mcp": {
|
||||
"title": "MCP 服务器",
|
||||
"description": "管理 Model Context Protocol 服务器",
|
||||
"servers": "服务器",
|
||||
"addServer": "添加服务器",
|
||||
"importExport": "导入/导出",
|
||||
"configuredServers": "已配置的服务器",
|
||||
"running": "运行中",
|
||||
|
Reference in New Issue
Block a user