From 3ddc8f165adc4d33a46fac1b7ad10a01621aa1de Mon Sep 17 00:00:00 2001 From: xintaofei Date: Sat, 7 Mar 2026 13:12:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81folder=E4=B8=BB=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E5=A4=9A=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../conversation-detail-panel.tsx | 15 +- .../conversations/search-command-dialog.tsx | 21 +- .../sidebar-conversation-card.tsx | 42 ++-- .../sidebar-conversation-list.tsx | 55 +++-- src/components/files/file-workspace-panel.tsx | 58 ++--- .../files/file-workspace-tab-bar.tsx | 12 +- .../layout/aux-panel-session-files-tab.tsx | 37 ++-- src/components/layout/aux-panel.tsx | 26 ++- .../layout/folder-name-dropdown.tsx | 12 +- src/components/layout/folder-title-bar.tsx | 50 ++++- src/components/layout/sidebar.tsx | 12 +- src/components/layout/status-bar-alerts.tsx | 6 +- .../layout/status-bar-connection.tsx | 31 ++- src/components/layout/status-bar-stats.tsx | 12 +- src/components/layout/status-bar-tasks.tsx | 4 +- src/components/layout/status-bar-tokens.tsx | 31 +-- src/components/layout/window-controls.tsx | 14 +- src/components/tabs/tab-item.tsx | 12 +- src/components/terminal/terminal-tab-bar.tsx | 19 +- src/i18n/messages/en.json | 200 ++++++++++++++++++ src/i18n/messages/zh-CN.json | 200 ++++++++++++++++++ src/i18n/messages/zh-TW.json | 200 ++++++++++++++++++ 22 files changed, 902 insertions(+), 167 deletions(-) diff --git a/src/components/conversations/conversation-detail-panel.tsx b/src/components/conversations/conversation-detail-panel.tsx index 36f0523..bf85234 100644 --- a/src/components/conversations/conversation-detail-panel.tsx +++ b/src/components/conversations/conversation-detail-panel.tsx @@ -2,6 +2,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react" import { Plus, RefreshCw, X } from "lucide-react" +import { useTranslations } from "next-intl" import { toast } from "sonner" import { useFolderContext } from "@/contexts/folder-context" import { useTabContext } from "@/contexts/tab-context" @@ -41,6 +42,7 @@ const ExistingConversationView = memo(function ExistingConversationView({ isActive, reloadSignal, }: ExistingConversationViewProps) { + const t = useTranslations("Folder.conversation") const { refreshConversations, folder } = useFolderContext() const contextKey = `conv-${agentType}-${conversationId}` @@ -193,12 +195,12 @@ const ExistingConversationView = memo(function ExistingConversationView({ pendingReloadState.current = null if (detailError) { - toast.error(`会话重新加载失败:${detailError}`) + toast.error(t("reloadFailed", { message: detailError })) return } - toast.success("当前会话已重新加载") - }, [detailLoading, detailError]) + toast.success(t("reloaded")) + }, [detailLoading, detailError, t]) return ( - 重新加载 + {t("reload")} - 新建会话 + {t("newConversation")} - 关闭会话 + {t("closeConversation")} diff --git a/src/components/conversations/search-command-dialog.tsx b/src/components/conversations/search-command-dialog.tsx index b35d090..4e87f7b 100644 --- a/src/components/conversations/search-command-dialog.tsx +++ b/src/components/conversations/search-command-dialog.tsx @@ -2,6 +2,8 @@ import { useState, useEffect, useRef, useCallback } from "react" import { formatDistanceToNow } from "date-fns" +import { enUS, zhCN, zhTW } from "date-fns/locale" +import { useLocale, useTranslations } from "next-intl" import { useFolderContext } from "@/contexts/folder-context" import { useTabContext } from "@/contexts/tab-context" import { listFolderConversations } from "@/lib/tauri" @@ -31,6 +33,10 @@ export function SearchCommandDialog({ open, onOpenChange, }: SearchCommandDialogProps) { + const t = useTranslations("Folder.search") + const locale = useLocale() + const dateFnsLocale = + locale === "zh-CN" ? zhCN : locale === "zh-TW" ? zhTW : enUS const { folderId, conversations } = useFolderContext() const { openTab } = useTabContext() @@ -96,12 +102,12 @@ export function SearchCommandDialog({ return ( @@ -116,7 +122,7 @@ export function SearchCommandDialog({ : "text-muted-foreground hover:text-foreground" )} > - All + {t("allAgents")} {availableAgents.map((at) => ( - + @@ -222,17 +230,17 @@ export const SidebarConversationCard = memo(function SidebarConversationCard({ - Delete conversation? + {t("deleteConversationTitle")} - This will delete “ - {conversation.title || "Untitled conversation"}”. This - action cannot be undone. + {t("deleteConversationDescription", { + title: conversation.title || t("untitledConversation"), + })} - Cancel + {t("cancel")} - Delete + {t("delete")} diff --git a/src/components/conversations/sidebar-conversation-list.tsx b/src/components/conversations/sidebar-conversation-list.tsx index 8c1bff0..9a46a3f 100644 --- a/src/components/conversations/sidebar-conversation-list.tsx +++ b/src/components/conversations/sidebar-conversation-list.tsx @@ -8,6 +8,7 @@ import { useState, type Ref, } from "react" +import { useTranslations } from "next-intl" import { toast } from "sonner" import { CheckCheck, ChevronRight, Download, Loader2, Plus } from "lucide-react" import { useFolderContext } from "@/contexts/folder-context" @@ -20,7 +21,7 @@ import { deleteConversation, } from "@/lib/tauri" import type { ConversationStatus, DbConversationSummary } from "@/lib/types" -import { STATUS_ORDER, STATUS_LABELS, STATUS_COLORS } from "@/lib/types" +import { STATUS_ORDER, STATUS_COLORS } from "@/lib/types" import { SidebarConversationCard } from "./sidebar-conversation-card" import { Button } from "@/components/ui/button" import { Skeleton } from "@/components/ui/skeleton" @@ -79,6 +80,9 @@ export function SidebarConversationList({ }: { ref?: Ref }) { + const t = useTranslations("Folder.sidebar") + const tStatus = useTranslations("Folder.statusLabels") + const tCommon = useTranslations("Folder.common") const { folder, conversations, @@ -225,7 +229,7 @@ export function SidebarConversationList({ if (importing) return setImporting(true) const taskId = `import-${folderId}-${Date.now()}` - addTask(taskId, "Importing local sessions") + addTask(taskId, t("importLocalSessions")) updateTask(taskId, { status: "running" }) try { const result = await importLocalConversations(folderId) @@ -233,19 +237,22 @@ export function SidebarConversationList({ refreshConversations() if (result.imported > 0) { toast.success( - `Imported ${result.imported} session(s), skipped ${result.skipped}` + t("toasts.importedSessions", { + imported: result.imported, + skipped: result.skipped, + }) ) } else { - toast.info(`No new sessions found (skipped ${result.skipped})`) + toast.info(t("toasts.noNewSessionsFound", { skipped: result.skipped })) } } catch (e) { const msg = e instanceof Error ? e.message : String(e) updateTask(taskId, { status: "failed", error: msg }) - toast.error(`Import failed: ${msg}`) + toast.error(t("toasts.importFailed", { message: msg })) } finally { setImporting(false) } - }, [importing, folderId, addTask, updateTask, refreshConversations]) + }, [importing, folderId, addTask, updateTask, refreshConversations, t]) const handleCompleteAllReview = useCallback(async () => { if (completingReview || reviewConversationCount === 0) return @@ -258,12 +265,12 @@ export function SidebarConversationList({ ) refreshConversations() toast.success( - `Marked ${reviewConversationCount} review session(s) as completed` + t("toasts.reviewCompleted", { count: reviewConversationCount }) ) setCompleteReviewOpen(false) } catch (e) { const msg = e instanceof Error ? e.message : String(e) - toast.error(`Failed to complete review sessions: ${msg}`) + toast.error(t("toasts.completeReviewFailed", { message: msg })) } finally { setCompletingReview(false) } @@ -272,6 +279,7 @@ export function SidebarConversationList({ reviewConversationCount, reviewConversations, refreshConversations, + t, ]) return ( @@ -290,14 +298,16 @@ export function SidebarConversationList({ ) : error ? (
-

Error: {error}

+

+ {t("error", { message: error })} +

) : conversations.length === 0 ? (

- No conversations found. + {t("noConversationsFound")}

- New Conversation + {t("newConversation")} - {importing ? "Importing..." : "Import local sessions"} + {importing ? t("importing") : t("importLocalSessions")}
@@ -356,7 +366,7 @@ export function SidebarConversationList({ STATUS_COLORS[status] )} /> - {STATUS_LABELS[status]} + {tStatus(status)} {items.length} @@ -381,7 +391,7 @@ export function SidebarConversationList({ onSelect={() => setCompleteReviewOpen(true)} > - Complete all sessions + {t("completeAllSessions")} @@ -421,12 +431,12 @@ export function SidebarConversationList({ - New Conversation + {t("newConversation")} - {importing ? "Importing..." : "Import local sessions"} + {importing ? t("importing") : t("importLocalSessions")} @@ -439,21 +449,22 @@ export function SidebarConversationList({ > - Complete all review sessions? + {t("completeAllReviewTitle")} - This will mark all {reviewConversationCount} session(s) in Review - as completed. + {t("completeAllReviewDescription", { + count: reviewConversationCount, + })} - Cancel + {tCommon("cancel")} - {completingReview ? "Completing..." : "Confirm"} + {completingReview ? t("completing") : tCommon("confirm")} diff --git a/src/components/files/file-workspace-panel.tsx b/src/components/files/file-workspace-panel.tsx index 452023d..567ba49 100644 --- a/src/components/files/file-workspace-panel.tsx +++ b/src/components/files/file-workspace-panel.tsx @@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react" import dynamic from "next/dynamic" import { ChevronDown, ChevronRight, FileCode2, FileIcon } from "lucide-react" import type { editor as MonacoEditorNs } from "monaco-editor" +import { useTranslations } from "next-intl" import { useWorkspaceContext } from "@/contexts/workspace-context" import { DiffViewer } from "@/components/diff/diff-viewer" import { UnifiedDiffPreview } from "@/components/diff/unified-diff-preview" @@ -490,6 +491,7 @@ function DiffFileList({ onOpenDiff: (path: string) => Promise openFilePreview: (path: string) => Promise }) { + const t = useTranslations("Folder.fileWorkspacePanel") return (
@@ -499,10 +501,7 @@ function DiffFileList({ {badge} )} - - {diffOutline.files.length}{" "} - {diffOutline.files.length === 1 ? "file" : "files"} - + {t("fileCount", { count: diffOutline.files.length })} +{diffOutline.totalAdditions} @@ -553,14 +552,14 @@ function DiffFileList({ void onOpenDiff(file.path) }} > - 查看差异 + {t("viewDiff")} { void openFilePreview(file.path) }} > - 打开文件 + {t("openFile")} @@ -572,6 +571,7 @@ function DiffFileList({ } export function FileWorkspacePanel() { + const t = useTranslations("Folder.fileWorkspacePanel") const { activeFileTab, openBranchDiff, @@ -999,9 +999,7 @@ export function FileWorkspacePanel() { return (
-

- Open a file or diff from the right panel -

+

{t("openFileOrDiff")}

) } @@ -1017,19 +1015,19 @@ export function FileWorkspacePanel() { const origLabel = isCommitDiff ? `${commitHash}~1` : isExternalConflictDiff - ? "Disk" - : "HEAD" + ? t("disk") + : t("head") const modLabel = isCommitDiff ? commitHash : isExternalConflictDiff - ? "Unsaved" - : "Working Tree" + ? t("unsaved") + : t("workingTree") return (
{activeFileTab.loading && (
- Loading... + {t("loading")}
)} {!activeFileTab.loading && ( @@ -1055,7 +1053,7 @@ export function FileWorkspacePanel() {
{activeFileTab.loading && (
- Loading... + {t("loading")}
)} { @@ -1101,7 +1102,7 @@ export function FileWorkspacePanel() {
{activeFileTab.loading && (
- Loading... + {t("loading")}
)} {!activeFileTab.loading && ( @@ -1121,17 +1122,14 @@ export function FileWorkspacePanel() {
{activeFileTab.loading && (
- Loading... + {t("loading")}
)}
{diffOutline && (
- - {diffOutline.files.length}{" "} - {diffOutline.files.length === 1 ? "file" : "files"} - + {t("fileCount", { count: diffOutline.files.length })} +{diffOutline.totalAdditions} @@ -1139,7 +1137,7 @@ export function FileWorkspacePanel() { -{diffOutline.totalDeletions} {diffOutline.totalHunks > 0 && ( - {diffOutline.totalHunks} hunks + {t("hunkCount", { count: diffOutline.totalHunks })} )} {allHunks.length > 0 && (
@@ -1150,7 +1148,7 @@ export function FileWorkspacePanel() { className="rounded border border-border bg-background px-2 py-0.5 text-[10px] disabled:opacity-40 hover:bg-muted transition-colors inline-flex items-center gap-1" > - Prev + {t("prev")}
@@ -1245,7 +1243,9 @@ export function FileWorkspacePanel() { type="button" onClick={() => jumpToLine(hunk.startLine)} className="shrink-0 rounded border border-border bg-background px-1.5 py-0.5 hover:bg-muted transition-colors" - title={`Jump to line ${hunk.startLine}`} + title={t("jumpToLine", { + line: hunk.startLine, + })} > L{hunk.startLine} @@ -1259,7 +1259,7 @@ export function FileWorkspacePanel() { })} {diffOutline.files.length === 0 && (
- No parsed diff sections + {t("noParsedDiffSections")}
)}
@@ -1279,7 +1279,7 @@ export function FileWorkspacePanel() { theme={editorTheme} loading={
- Loading editor... + {t("loadingEditor")}
} options={{ diff --git a/src/components/files/file-workspace-tab-bar.tsx b/src/components/files/file-workspace-tab-bar.tsx index b9fc6db..686f599 100644 --- a/src/components/files/file-workspace-tab-bar.tsx +++ b/src/components/files/file-workspace-tab-bar.tsx @@ -3,6 +3,7 @@ import { useCallback, useEffect, useRef, useState } from "react" import { Reorder } from "motion/react" import { FileText, GitCompare, X } from "lucide-react" +import { useTranslations } from "next-intl" import { useWorkspaceContext } from "@/contexts/workspace-context" import { useShortcutSettings } from "@/hooks/use-shortcut-settings" import { matchShortcutEvent } from "@/lib/keyboard-shortcuts" @@ -16,6 +17,7 @@ import { } from "@/components/ui/context-menu" export function FileWorkspaceTabBar() { + const t = useTranslations("Folder.fileWorkspace") const { mode, activePane, @@ -80,7 +82,7 @@ export function FileWorkspaceTabBar() { if (fileTabs.length === 0) { return (
- Files + {t("files")}
) } @@ -159,7 +161,7 @@ export function FileWorkspaceTabBar() { event.stopPropagation() closeFileTab(tab.id) }} - aria-label="Close file tab" + aria-label={t("closeFileTab")} > @@ -167,14 +169,14 @@ export function FileWorkspaceTabBar() { closeFileTab(tab.id)}> - 关闭 + {t("close")} closeOtherFileTabs(tab.id)}> - 关闭其它 + {t("closeOthers")} - 关闭所有 + {t("closeAll")} diff --git a/src/components/layout/aux-panel-session-files-tab.tsx b/src/components/layout/aux-panel-session-files-tab.tsx index 50a9ef4..11d9ca6 100644 --- a/src/components/layout/aux-panel-session-files-tab.tsx +++ b/src/components/layout/aux-panel-session-files-tab.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react" import { ChevronRight, FileIcon } from "lucide-react" +import { useTranslations } from "next-intl" import { useFolderContext } from "@/contexts/folder-context" import { useTabContext } from "@/contexts/tab-context" import type { LiveMessage } from "@/contexts/acp-connections-context" @@ -77,8 +78,15 @@ function mergeLiveTurns(params: { liveMessage: LiveMessage | null connStatus: ConnectionStatus | null pendingPromptText: string | null + fallbackPromptText: string }): MessageTurn[] { - const { turns, liveMessage, connStatus, pendingPromptText } = params + const { + turns, + liveMessage, + connStatus, + pendingPromptText, + fallbackPromptText, + } = params if (!liveMessage || connStatus !== "prompting") return turns const liveBlocks = liveMessage.content.flatMap((block) => { @@ -118,7 +126,7 @@ function mergeLiveTurns(params: { id: `live-user-${liveMessage.id}`, role: "user", blocks: [ - { type: "text", text: pendingPromptText?.trim() || "Current response" }, + { type: "text", text: pendingPromptText?.trim() || fallbackPromptText }, ], timestamp: now, }) @@ -145,6 +153,7 @@ function SessionFilesContent({ connStatus: ConnectionStatus | null pendingPromptText: string | null }) { + const t = useTranslations("Folder.sessionFiles") const { detail, loading, refetch } = useDbMessageDetail(conversationId) const { openSessionFileDiff } = useWorkspaceContext() const { folder } = useFolderContext() @@ -166,8 +175,9 @@ function SessionFilesContent({ liveMessage, connStatus, pendingPromptText, + fallbackPromptText: t("currentResponse"), }), - [detail?.turns, liveMessage, connStatus, pendingPromptText] + [detail?.turns, liveMessage, connStatus, pendingPromptText, t] ) const groups = useMemo( () => (turns.length > 0 ? extractSessionFilesGrouped(turns) : []), @@ -182,7 +192,7 @@ function SessionFilesContent({ ) => { openSessionFileDiff( filePath, - diffContent ?? `No diff data available for ${filePath}`, + diffContent ?? t("noDiffDataAvailable", { filePath }), `msg-${groupIndex + 1}-chg-${changeIndex + 1}` ) } @@ -190,7 +200,9 @@ function SessionFilesContent({ if (loading) { return (
-

Loading...

+

+ {t("loading")} +

) } @@ -199,7 +211,7 @@ function SessionFilesContent({ return (

- No file changes found in this conversation + {t("noFileChangesInConversation")}

) @@ -258,12 +270,10 @@ function SessionFilesContent({

- {group.files.length}{" "} - {group.files.length === 1 ? "change" : "changes"} + {t("changeCount", { count: group.files.length })} - {uniqueFileCount}{" "} - {uniqueFileCount === 1 ? "File" : "Files"} + {t("fileCount", { count: uniqueFileCount })} {isRemoved ? ( - Remove + {t("remove")} ) : ( @@ -366,6 +376,7 @@ function SessionFilesContent({ } export function SessionFilesTab() { + const t = useTranslations("Folder.sessionFiles") const { tabs, activeTabId } = useTabContext() const activeTab = tabs.find((t) => t.id === activeTabId) @@ -378,7 +389,7 @@ export function SessionFilesTab() { return (

- Open a conversation to see its file changes + {t("openConversationToSeeChanges")}

) @@ -388,7 +399,7 @@ export function SessionFilesTab() { return (

- No file changes found in this conversation + {t("noFileChangesInConversation")}

) diff --git a/src/components/layout/aux-panel.tsx b/src/components/layout/aux-panel.tsx index a08f6d1..21db2d8 100644 --- a/src/components/layout/aux-panel.tsx +++ b/src/components/layout/aux-panel.tsx @@ -2,6 +2,7 @@ import { useCallback, useState } from "react" import { FileDiff, Folder, FolderPen, GitCommit } from "lucide-react" +import { useTranslations } from "next-intl" import { useAuxPanelContext, type AuxPanelTab, @@ -13,6 +14,7 @@ import { GitLogTab } from "./aux-panel-git-log-tab" import { SessionFilesTab } from "./aux-panel-session-files-tab" export function AuxPanel() { + const t = useTranslations("Folder.auxPanel.tabs") const { isOpen, activeTab, setActiveTab } = useAuxPanelContext() const [hasMountedFileTree, setHasMountedFileTree] = useState( activeTab === "file_tree" @@ -54,16 +56,32 @@ export function AuxPanel() { variant="line" className="h-10 w-full shrink-0 justify-start border-b border-border px-3 group-data-horizontal/tabs:h-10" > - + - + - + - + diff --git a/src/components/layout/folder-name-dropdown.tsx b/src/components/layout/folder-name-dropdown.tsx index 0d21b16..14abc8e 100644 --- a/src/components/layout/folder-name-dropdown.tsx +++ b/src/components/layout/folder-name-dropdown.tsx @@ -3,6 +3,7 @@ import { useState } from "react" import { ChevronDown, Folder, FolderOpen, GitBranch } from "lucide-react" import { open } from "@tauri-apps/plugin-dialog" +import { useTranslations } from "next-intl" import { DropdownMenu, DropdownMenuContent, @@ -22,13 +23,14 @@ import { CloneDialog } from "@/components/welcome/clone-dialog" import type { FolderHistoryEntry } from "@/lib/types" export function FolderNameDropdown() { + const t = useTranslations("Folder.folderNameDropdown") const { folder } = useFolderContext() const [openFolders, setOpenFolders] = useState([]) const [history, setHistory] = useState([]) const [cloneOpen, setCloneOpen] = useState(false) const folderPath = folder?.path ?? "" - const folderName = folder?.name ?? "文件夹" + const folderName = folder?.name ?? t("fallbackFolderName") async function handleOpenChange(open: boolean) { if (open) { @@ -77,16 +79,16 @@ export function FolderNameDropdown() { - Open Folder + {t("openFolder")} setCloneOpen(true)}> - Clone Repository + {t("cloneRepository")} {openFolders.length > 0 && ( <> - 已打开 + {t("opened")} {openFolders.map((entry) => ( 0 && ( <> - 最近打开 + {t("recentOpen")} {history.map((entry) => (
{ const Icon = item.icon const isActive = mode === item.mode + const title = tModes(item.titleKey) return (
setMode(item.mode)} onKeyDown={(event) => handleModeKeyDown(event, item.mode)} onMouseDown={(event) => event.preventDefault()} - title={item.title} - aria-label={item.title} + title={title} + aria-label={title} aria-selected={isActive} > @@ -268,7 +278,13 @@ export function FolderTitleBar() { size="icon" className={`h-6 w-6 hover:text-foreground/80 ${terminalOpen ? "bg-accent" : ""}`} onClick={() => toggleTerminal()} - title={`Toggle Terminal (${formatShortcutLabel(shortcuts.toggle_terminal, isMac)})`} + title={tTitleBar("withShortcut", { + label: tTitleBar("toggleTerminal"), + shortcut: formatShortcutLabel( + shortcuts.toggle_terminal, + isMac + ), + })} > @@ -277,7 +293,13 @@ export function FolderTitleBar() { size="icon" className={`h-6 w-6 hover:text-foreground/80 ${auxPanelOpen ? "bg-accent" : ""}`} onClick={toggleAuxPanel} - title={`Toggle Auxiliary Panel (${formatShortcutLabel(shortcuts.toggle_aux_panel, isMac)})`} + title={tTitleBar("withShortcut", { + label: tTitleBar("toggleAuxPanel"), + shortcut: formatShortcutLabel( + shortcuts.toggle_aux_panel, + isMac + ), + })} > @@ -286,7 +308,10 @@ export function FolderTitleBar() { size="icon" className="h-6 w-6 hover:text-foreground/80" onClick={() => setSearchOpen(true)} - title={`Search (${formatShortcutLabel(shortcuts.toggle_search, isMac)})`} + title={tTitleBar("withShortcut", { + label: tTitleBar("search"), + shortcut: formatShortcutLabel(shortcuts.toggle_search, isMac), + })} > @@ -295,7 +320,10 @@ export function FolderTitleBar() { size="icon" className="h-6 w-6 hover:text-foreground/80" onClick={handleOpenSettings} - title={`Open Settings (${formatShortcutLabel(shortcuts.open_settings, isMac)})`} + title={tTitleBar("withShortcut", { + label: tTitleBar("openSettings"), + shortcut: formatShortcutLabel(shortcuts.open_settings, isMac), + })} > diff --git a/src/components/layout/sidebar.tsx b/src/components/layout/sidebar.tsx index e66fc09..a0014d2 100644 --- a/src/components/layout/sidebar.tsx +++ b/src/components/layout/sidebar.tsx @@ -2,6 +2,7 @@ import { useCallback, useRef } from "react" import { ChevronsDownUp, ChevronsUpDown, Crosshair, Plus } from "lucide-react" +import { useTranslations } from "next-intl" import { useFolderContext } from "@/contexts/folder-context" import { useTabContext } from "@/contexts/tab-context" import { useSidebarContext } from "@/contexts/sidebar-context" @@ -12,6 +13,7 @@ import { import { Button } from "@/components/ui/button" export function Sidebar() { + const t = useTranslations("Folder.sidebar") const { folder } = useFolderContext() const { openNewConversationTab } = useTabContext() const { isOpen } = useSidebarContext() @@ -27,14 +29,14 @@ export function Sidebar() { return (