修复 i18n

This commit is contained in:
2025-10-17 17:20:46 +08:00
parent 9d30fd0dac
commit 0e32c6e64c
35 changed files with 2581 additions and 1674 deletions

View File

@@ -150,11 +150,11 @@ export const AgentsModal: React.FC<AgentsModalProps> = ({ open, onOpenChange })
if (filePath) {
const agent = await api.importAgentFromFile(filePath as string);
loadAgents(); // Refresh list
setToast({ message: `Agent "${agent.name}" imported successfully`, type: "success" });
setToast({ message: t('agents.importedSuccessfully', { name: agent.name }), type: "success" });
}
} catch (error) {
console.error('Failed to import agent:', error);
setToast({ message: "Failed to import agent", type: "error" });
setToast({ message: t('agents.importFailed'), type: "error" });
}
};
@@ -175,11 +175,11 @@ export const AgentsModal: React.FC<AgentsModalProps> = ({ open, onOpenChange })
if (filePath) {
await invoke('write_file', { path: filePath, content: JSON.stringify(exportData, null, 2) });
setToast({ message: "Agent exported successfully", type: "success" });
setToast({ message: t('agents.exportedSuccessfully', { name: agent.name }), type: "success" });
}
} catch (error) {
console.error('Failed to export agent:', error);
setToast({ message: "Failed to export agent", type: "error" });
setToast({ message: t('agents.exportFailed'), type: "error" });
}
};
@@ -424,7 +424,7 @@ export const AgentsModal: React.FC<AgentsModalProps> = ({ open, onOpenChange })
onImportSuccess={() => {
setShowGitHubBrowser(false);
loadAgents(); // Refresh the agents list
setToast({ message: "Agent imported successfully", type: "success" });
setToast({ message: t('agents.importedSuccessfully'), type: "success" });
}}
/>

View File

@@ -7,12 +7,14 @@ import { Badge } from "@/components/ui/badge";
import { Toast, ToastContainer } from "@/components/ui/toast";
import { ccrApi, type CcrServiceStatus } from "@/lib/api";
import { open } from '@tauri-apps/plugin-shell';
import { useTranslation } from '@/hooks/useTranslation';
interface CcrRouterManagerProps {
onBack: () => void;
}
export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
const { t } = useTranslation();
const [serviceStatus, setServiceStatus] = useState<CcrServiceStatus | null>(null);
const [loading, setLoading] = useState(true);
const [actionLoading, setActionLoading] = useState(false);
@@ -34,7 +36,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
} catch (error) {
console.error("Failed to load CCR service status:", error);
setToast({
message: `加载CCR服务状态失败: ${error}`,
message: t('ccr.loadStatusFailed', { error: String(error) }),
type: "error"
});
} finally {
@@ -63,7 +65,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
} catch (error) {
console.error("Failed to start CCR service:", error);
setToast({
message: `启动CCR服务失败: ${error}`,
message: t('ccr.startFailed', { error: String(error) }),
type: "error"
});
} finally {
@@ -83,7 +85,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
} catch (error) {
console.error("Failed to stop CCR service:", error);
setToast({
message: `停止CCR服务失败: ${error}`,
message: t('ccr.stopFailed', { error: String(error) }),
type: "error"
});
} finally {
@@ -103,7 +105,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
} catch (error) {
console.error("Failed to restart CCR service:", error);
setToast({
message: `重启CCR服务失败: ${error}`,
message: t('ccr.restartFailed', { error: String(error) }),
type: "error"
});
} finally {
@@ -118,14 +120,14 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
// 如果服务未运行,先尝试启动
if (!serviceStatus?.is_running) {
setToast({
message: "检测到服务未运行,正在启动...",
message: t('ccr.serviceStarting'),
type: "info"
});
const startResult = await ccrApi.startService();
setServiceStatus(startResult.status);
if (!startResult.status.is_running) {
throw new Error("服务启动失败");
throw new Error(t('ccr.serviceStartFailed'));
}
// 等待服务完全启动
@@ -134,7 +136,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
await ccrApi.openUI();
setToast({
message: "正在打开CCR UI...",
message: t('ccr.openingUI'),
type: "info"
});
@@ -145,7 +147,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
} catch (error) {
console.error("Failed to open CCR UI:", error);
setToast({
message: `打开CCR UI失败: ${error}`,
message: t('ccr.openUIFailed', { error: String(error) }),
type: "error"
});
} finally {
@@ -159,7 +161,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
if (!serviceStatus?.is_running) {
setActionLoading(true);
setToast({
message: "检测到服务未运行,正在启动...",
message: t('ccr.serviceStarting'),
type: "info"
});
@@ -167,7 +169,7 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
setServiceStatus(startResult.status);
if (!startResult.status.is_running) {
throw new Error("服务启动失败");
throw new Error(t('ccr.serviceStartFailed'));
}
// 等待服务完全启动
@@ -178,14 +180,14 @@ export function CcrRouterManager({ onBack }: CcrRouterManagerProps) {
if (serviceStatus?.endpoint) {
open(`${serviceStatus.endpoint}/ui/`);
setToast({
message: "正在打开CCR管理界面...",
message: t('ccr.openingAdmin'),
type: "info"
});
}
} catch (error) {
console.error("Failed to open CCR UI in browser:", error);
setToast({
message: `打开管理界面失败: ${error}`,
message: t('ccr.openAdminFailed', { error: String(error) }),
type: "error"
});
setActionLoading(false);

View File

@@ -1519,7 +1519,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
</Button>
</TooltipTrigger>
<TooltipContent side="left">
<p></p>
<p>{t('claudeSession.scrollToTop', 'Scroll to top')}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -1540,7 +1540,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
</Button>
</TooltipTrigger>
<TooltipContent side="left">
<p></p>
<p>{t('claudeSession.scrollToBottom', 'Scroll to bottom')}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -1665,7 +1665,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
<div className="flex items-center gap-1.5 text-xs bg-muted/50 rounded-full px-2.5 py-1">
<Hash className="h-3 w-3 text-muted-foreground" />
<span className="font-mono">{totalTokens.toLocaleString()}</span>
<span className="text-muted-foreground">tokens</span>
<span className="text-muted-foreground">{t('usage.tokens')}</span>
</div>
)}
@@ -1705,7 +1705,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
</Button>
</TooltipTrigger>
<TooltipContent>
<p>File Explorer</p>
<p>{t('app.fileExplorer')}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -1726,7 +1726,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Git Panel</p>
<p>{t('app.gitPanel')}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
@@ -1747,7 +1747,7 @@ export const ClaudeCodeSession: React.FC<ClaudeCodeSessionProps> = ({
</Button>
</TooltipTrigger>
<TooltipContent>
<p>{isFileWatching ? '停止文件监控' : '启动文件监控'}</p>
<p>{isFileWatching ? t('claudeSession.stopFileWatch', 'Stop file watching') : t('claudeSession.startFileWatch', 'Start file watching')}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>

View File

@@ -136,7 +136,7 @@ export const Settings: React.FC<SettingsProps> = ({
setModelMappings(mappings);
} catch (err) {
console.error("Failed to load model mappings:", err);
setToast({ message: "加载模型映射失败", type: "error" });
setToast({ message: t('settings.modelMappings.loadFailed'), type: "error" });
} finally {
setLoadingMappings(false);
}
@@ -163,10 +163,10 @@ export const Settings: React.FC<SettingsProps> = ({
await api.updateModelMapping(mapping.alias, mapping.model_name);
}
setModelMappingsChanged(false);
setToast({ message: "模型映射已保存", type: "success" });
setToast({ message: t('settings.modelMappings.saved'), type: "success" });
} catch (err) {
console.error("Failed to save model mappings:", err);
setToast({ message: "保存模型映射失败", type: "error" });
setToast({ message: t('settings.modelMappings.saveFailed'), type: "error" });
}
};
@@ -696,9 +696,9 @@ export const Settings: React.FC<SettingsProps> = ({
{/* Model Mappings Configuration */}
<div className="space-y-4">
<div>
<Label className="text-sm font-medium mb-2 block"></Label>
<Label className="text-sm font-medium mb-2 block">{t('settings.modelMappings.title')}</Label>
<p className="text-xs text-muted-foreground mb-4">
sonnetopushaiku
{t('settings.modelMappings.description')}
</p>
</div>
@@ -720,29 +720,29 @@ export const Settings: React.FC<SettingsProps> = ({
className="font-mono text-sm"
/>
<p className="text-xs text-muted-foreground">
{mapping.alias === 'sonnet' && '平衡性能与成本的主力模型'}
{mapping.alias === 'opus' && '最强大的旗舰模型,适合复杂任务'}
{mapping.alias === 'haiku' && '快速响应的轻量级模型'}
{mapping.alias === 'sonnet' && t('settings.modelMappings.aliasDescriptions.sonnet')}
{mapping.alias === 'opus' && t('settings.modelMappings.aliasDescriptions.opus')}
{mapping.alias === 'haiku' && t('settings.modelMappings.aliasDescriptions.haiku')}
</p>
</div>
))}
{modelMappings.length === 0 && (
<div className="text-center py-8 text-muted-foreground">
<p className="text-sm"></p>
<p className="text-xs mt-2"></p>
<p className="text-sm">{t('settings.modelMappings.emptyTitle')}</p>
<p className="text-xs mt-2">{t('settings.modelMappings.emptySubtitle')}</p>
</div>
)}
{modelMappingsChanged && (
<p className="text-xs text-amber-600 dark:text-amber-400">
{t('settings.modelMappings.changedNotice')}
</p>
)}
<div className="pt-2">
<p className="text-xs text-muted-foreground">
<strong></strong>Agent执行时会根据这里的配置解析模型别名 sonnet claude-sonnet-4-20250514使 "sonnet" Agent都会调用该模型版本
<strong>{t('settings.modelMappings.note')}</strong> {t('settings.modelMappings.noteContent')}
</p>
</div>
</div>

View File

@@ -398,9 +398,11 @@ export const TabContent: React.FC = () => {
console.log('[TabContent] Handling create-smart-session-tab:', { tabId, sessionData });
// Update the existing tab with smart session data and switch immediately
const displayName = sessionData.display_name || t('smartSessionDefaultTitle');
updateTab(tabId, {
type: 'chat',
title: sessionData.display_name || 'Smart Session',
title: displayName,
initialProjectPath: sessionData.project_path,
sessionData: null, // No existing session, this is a new session workspace
});