-
Project Slash Commands
+
{t('slashCommands.projectSlashCommands')}
Custom commands that are specific to this project. These commands are stored in
.claude/slash-commands/
@@ -145,7 +147,7 @@ export const ProjectSettings: React.FC = ({
-
Project Hooks
+
{t('hooks.projectHooks', 'Project Hooks')}
These hooks apply to all users working on this project. They are stored in
.claude/settings.json
@@ -165,7 +167,7 @@ export const ProjectSettings: React.FC = ({
-
Local Hooks
+
{t('hooks.localHooks', 'Local Hooks')}
These hooks only apply to your machine. They are stored in
.claude/settings.local.json
@@ -177,7 +179,7 @@ export const ProjectSettings: React.FC = ({
- Local settings file is not in .gitignore
+ {t('projectSettings.gitignoreLocalWarning')}
)}
diff --git a/src/components/RunningClaudeSessions.tsx b/src/components/RunningClaudeSessions.tsx
index c0a1d96..df4039f 100644
--- a/src/components/RunningClaudeSessions.tsx
+++ b/src/components/RunningClaudeSessions.tsx
@@ -46,7 +46,7 @@ export const RunningClaudeSessions: React.FC
= ({
setError(null);
} catch (err) {
console.error("Failed to load running sessions:", err);
- setError("Failed to load running sessions");
+ setError(t('runningSessions.loadFailed'));
} finally {
setLoading(false);
}
@@ -101,10 +101,10 @@ export const RunningClaudeSessions: React.FC = ({
-
Active Claude Sessions
+
{t('runningSessions.title')}
- ({runningSessions.length} running)
+ {t('runningSessions.countRunning', { count: runningSessions.length })}
@@ -137,7 +137,7 @@ export const RunningClaudeSessions: React.FC = ({
{sessionId.substring(0, 20)}...
- Running
+ {t('runningSessions.running')}
@@ -163,7 +163,7 @@ export const RunningClaudeSessions: React.FC = ({
className="flex-shrink-0"
>
- Resume
+ {t('runningSessions.resume')}
diff --git a/src/components/SessionList.tsx b/src/components/SessionList.tsx
index 7b0a282..016ecd4 100644
--- a/src/components/SessionList.tsx
+++ b/src/components/SessionList.tsx
@@ -8,6 +8,7 @@ import { ClaudeMemoriesDropdown } from "@/components/ClaudeMemoriesDropdown";
import { cn } from "@/lib/utils";
import { formatUnixTimestamp, formatISOTimestamp, truncateText, getFirstLine } from "@/lib/date-utils";
import type { Session, ClaudeMdFile } from "@/lib/api";
+import { useTranslation } from "@/hooks/useTranslation";
interface SessionListProps {
/**
@@ -57,6 +58,7 @@ export const SessionList: React.FC
= ({
onEditClaudeFile,
className,
}) => {
+ const { t } = useTranslation();
const [currentPage, setCurrentPage] = useState(1);
// Calculate pagination
@@ -89,7 +91,7 @@ export const SessionList: React.FC = ({
{projectPath}
- {sessions.length} session{sessions.length !== 1 ? 's' : ''}
+ {t('projects.sessionCount', { count: sessions.length })}
@@ -149,7 +151,7 @@ export const SessionList: React.FC = ({
- First message:
+ {t('sessions.firstMessage')}
{truncateText(getFirstLine(session.first_message), 100)}
@@ -173,7 +175,7 @@ export const SessionList: React.FC = ({
{session.todo_data && (
- Has todo
+ {t('sessions.hasTodo')}
)}
diff --git a/src/components/SessionOutputViewer.tsx b/src/components/SessionOutputViewer.tsx
index 440eadf..4454333 100644
--- a/src/components/SessionOutputViewer.tsx
+++ b/src/components/SessionOutputViewer.tsx
@@ -189,7 +189,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
}
} catch (error) {
console.error('Failed to load session output:', error);
- setToast({ message: 'Failed to load session output', type: 'error' });
+ setToast({ message: t('app.failedToLoadSessionOutput'), type: 'error' });
} finally {
setLoading(false);
}
@@ -223,12 +223,12 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
});
const completeUnlisten = await listen(`agent-complete:${session.id}`, () => {
- setToast({ message: 'Agent execution completed', type: 'success' });
+ setToast({ message: t('app.agentExecutionCompleted'), type: 'success' });
// Don't set status here as the parent component should handle it
});
const cancelUnlisten = await listen(`agent-cancelled:${session.id}`, () => {
- setToast({ message: 'Agent execution was cancelled', type: 'error' });
+ setToast({ message: t('app.agentExecutionCancelled'), type: 'error' });
});
unlistenRefs.current = [outputUnlisten, errorUnlisten, completeUnlisten, cancelUnlisten];
@@ -242,7 +242,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
const jsonl = rawJsonlOutput.join('\n');
await navigator.clipboard.writeText(jsonl);
setCopyPopoverOpen(false);
- setToast({ message: 'Output copied as JSONL', type: 'success' });
+ setToast({ message: t('webview.sessionOutputCopiedJsonl'), type: 'success' });
};
const handleCopyAsMarkdown = async () => {
@@ -297,7 +297,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
await navigator.clipboard.writeText(markdown);
setCopyPopoverOpen(false);
- setToast({ message: 'Output copied as Markdown', type: 'success' });
+ setToast({ message: t('webview.sessionOutputCopiedMarkdown'), type: 'success' });
};
@@ -305,10 +305,10 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
setRefreshing(true);
try {
await loadOutput(true); // Skip cache when manually refreshing
- setToast({ message: 'Output refreshed', type: 'success' });
+ setToast({ message: t('app.outputRefreshed'), type: 'success' });
} catch (error) {
console.error('Failed to refresh output:', error);
- setToast({ message: 'Failed to refresh output', type: 'error' });
+ setToast({ message: t('app.failedToRefreshOutput'), type: 'error' });
} finally {
setRefreshing(false);
}
@@ -388,7 +388,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
{session.agent_icon}
-
{session.agent_name} - Output
+
{session.agent_name} - {t('app.output')}
{session.status}
@@ -396,7 +396,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
{session.status === 'running' && (
- Live
+ {t('agentRun.live')}
)}
@@ -459,7 +459,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
size="sm"
onClick={refreshOutput}
disabled={refreshing}
- title="Refresh output"
+ title={t('app.refresh')}
>
@@ -474,7 +474,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
- Loading output...
+ {t('app.loadingOutput')}
) : (
@@ -498,14 +498,14 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
{session.status === 'running' ? (
<>
- Waiting for output...
+ {t('app.waitingForOutput')}
- Agent is running but no output received yet
+ {t('app.agentRunningNoOutput')}
>
) : (
<>
- No output available
+ {t('app.noOutput')}
>
)}
@@ -551,11 +551,11 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
{session.agent_icon}
-
{session.agent_name} - Output
+
{session.agent_name} - {t('app.output')}
{session.status === 'running' && (
-
Running
+
{t('agents.statusRunning')}
)}
@@ -605,7 +605,7 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
className="flex items-center gap-2"
>
- Close
+ {t('app.close')}
@@ -632,14 +632,14 @@ export function SessionOutputViewer({ session, onClose, className }: SessionOutp
{session.status === 'running' ? (
<>
-
Waiting for output...
+
{t('app.waitingForOutput')}
- Agent is running but no output received yet
+ {t('app.agentRunningNoOutput')}
>
) : (
<>
-
No output available
+
{t('app.noOutput')}
>
)}
diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx
index c0dac16..fced1dd 100644
--- a/src/components/Settings.tsx
+++ b/src/components/Settings.tsx
@@ -658,19 +658,37 @@ export const Settings: React.FC
= ({
{/* Cleanup Period */}
-
{
- const value = e.target.value ? parseInt(e.target.value) : undefined;
- updateSetting("cleanupPeriodDays", value);
- }}
- />
+
+
{
+ const value = e.target.value ? parseInt(e.target.value) : undefined;
+ updateSetting("cleanupPeriodDays", value);
+ }}
+ disabled={settings?.cleanupPeriodDays === -1}
+ className="flex-1"
+ />
+
+ {
+ updateSetting("cleanupPeriodDays", checked ? -1 : undefined);
+ }}
+ />
+
+
+
- {t('settings.generalOptions.chatRetentionDesc')}
+ {settings?.cleanupPeriodDays === -1
+ ? t('settings.generalOptions.chatRetentionPermanent')
+ : t('settings.generalOptions.chatRetentionDesc')}
diff --git a/src/components/StorageTab.tsx b/src/components/StorageTab.tsx
index 71bd84b..bb808a6 100644
--- a/src/components/StorageTab.tsx
+++ b/src/components/StorageTab.tsx
@@ -133,7 +133,7 @@ export const StorageTab: React.FC = () => {
}
} catch (err) {
console.error("Failed to load tables:", err);
- setError("Failed to load tables");
+ setError(t('storageTab.loadTablesFailed'));
} finally {
setLoading(false);
}
@@ -158,7 +158,7 @@ export const StorageTab: React.FC = () => {
setCurrentPage(page);
} catch (err) {
console.error("Failed to load table data:", err);
- setError("Failed to load table data");
+ setError(t('storageTab.loadTableDataFailed'));
} finally {
setLoading(false);
}
@@ -205,7 +205,7 @@ export const StorageTab: React.FC = () => {
setEditingRow(null);
} catch (err) {
console.error("Failed to update row:", err);
- setError("Failed to update row");
+ setError(t('storageTab.updateRowFailed'));
} finally {
setLoading(false);
}
@@ -225,7 +225,7 @@ export const StorageTab: React.FC = () => {
setDeletingRow(null);
} catch (err) {
console.error("Failed to delete row:", err);
- setError("Failed to delete row");
+ setError(t('storageTab.deleteRowFailed'));
} finally {
setLoading(false);
}
@@ -244,7 +244,7 @@ export const StorageTab: React.FC = () => {
setNewRow(null);
} catch (err) {
console.error("Failed to insert row:", err);
- setError("Failed to insert row");
+ setError(t('storageTab.insertRowFailed'));
} finally {
setLoading(false);
}
@@ -269,7 +269,7 @@ export const StorageTab: React.FC = () => {
}
} catch (err) {
console.error("Failed to execute SQL:", err);
- setSqlError(err instanceof Error ? err.message : "Failed to execute SQL");
+ setSqlError(err instanceof Error ? err.message : t('storageTab.executeSqlFailed'));
} finally {
setLoading(false);
}
@@ -287,14 +287,14 @@ export const StorageTab: React.FC = () => {
setTableData(null);
setShowResetConfirm(false);
setToast({
- message: "Database Reset Complete: The database has been restored to its default state with empty tables (agents, agent_runs, app_settings).",
+ message: t('storageTab.resetSuccess'),
type: "success",
});
} catch (err) {
console.error("Failed to reset database:", err);
- setError("Failed to reset database");
+ setError(t('storageTab.resetDatabaseFailed'));
setToast({
- message: "Reset Failed: Failed to reset the database. Please try again.",
+ message: t('storageTab.resetFailed'),
type: "error",
});
} finally {
@@ -337,7 +337,7 @@ export const StorageTab: React.FC = () => {
-
Database Storage
+ {t('storageTab.title')}
@@ -365,7 +365,7 @@ export const StorageTab: React.FC = () => {