folder页面全量多语言处理

This commit is contained in:
xintaofei
2026-03-07 13:44:40 +08:00
parent 3ddc8f165a
commit a356b813a6
10 changed files with 1533 additions and 343 deletions

View File

@@ -10,6 +10,7 @@ import {
} from "react"
import { listen, type UnlistenFn } from "@tauri-apps/api/event"
import { ChevronsDownUp, ChevronsUpDown } from "lucide-react"
import { useTranslations } from "next-intl"
import { toast } from "sonner"
import {
CommitFileAdditions,
@@ -423,6 +424,8 @@ function toWorkingTreeChanges(
}
export function GitChangesTab() {
const t = useTranslations("Folder.gitChangesTab")
const tCommon = useTranslations("Folder.common")
const { folder } = useFolderContext()
const { activeTab } = useAuxPanelContext()
const { openFilePreview, openWorkingTreeDiff } = useWorkspaceContext()
@@ -466,8 +469,8 @@ export function GitChangesTab() {
const folderName = useMemo(() => {
const path = folder?.path ?? ""
const parts = path.split(/[\\/]/).filter(Boolean)
return (parts[parts.length - 1] ?? path) || "workspace"
}, [folder?.path])
return (parts[parts.length - 1] ?? path) || t("workspace")
}, [folder?.path, t])
const trackedChanges = useMemo(
() => changes.filter((change) => !isUntrackedStatus(change.status)),
@@ -712,8 +715,8 @@ export function GitChangesTab() {
resetDirectoryGitActionDialog()
toast.info(
action === "add"
? "该目录下没有可添加到VCS的变更文件"
: "该目录下没有可回滚的变更文件"
? t("toasts.noAddableFilesInDir")
: t("toasts.noRollbackFilesInDir")
)
return
}
@@ -729,7 +732,7 @@ export function GitChangesTab() {
setDirectoryGitLoading(false)
}
},
[folder?.path, resetDirectoryGitActionDialog]
[folder?.path, resetDirectoryGitActionDialog, t]
)
const handleRequestRollback = useCallback(
@@ -753,14 +756,14 @@ export function GitChangesTab() {
if (!folder?.path) return
try {
await gitAddFiles(folder.path, [target.path])
toast.success(`已添加 ${target.name} 到VCS`)
toast.success(t("toasts.addedToVcs", { name: target.name }))
await fetchChanges({ inline: true })
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
toast.error("添加到VCS失败", { description: message })
toast.error(t("toasts.addToVcsFailed"), { description: message })
}
},
[fetchChanges, folder?.path, openDirectoryGitActionDialog]
[fetchChanges, folder?.path, openDirectoryGitActionDialog, t]
)
const handleRollbackConfirm = useCallback(async () => {
@@ -769,16 +772,16 @@ export function GitChangesTab() {
setRollingBack(true)
try {
await gitRollbackFile(folder.path, rollbackTarget.path)
toast.success(`已回滚 ${rollbackTarget.name}`)
toast.success(t("toasts.rolledBack", { name: rollbackTarget.name }))
setRollbackTarget(null)
await fetchChanges({ inline: true })
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
toast.error("回滚失败", { description: message })
toast.error(t("toasts.rollbackFailed"), { description: message })
} finally {
setRollingBack(false)
}
}, [fetchChanges, folder?.path, rollbackTarget])
}, [fetchChanges, folder?.path, rollbackTarget, t])
const directoryGitAllFilePaths = useMemo(
() => directoryGitCandidates.map((entry) => entry.path),
@@ -830,12 +833,20 @@ export function GitChangesTab() {
try {
if (directoryGitActionType === "add") {
await gitAddFiles(folder.path, selectedPaths)
toast.success(`已添加 ${selectedPaths.length} 个文件到VCS`)
toast.success(
t("toasts.addedFilesToVcs", {
count: selectedPaths.length,
})
)
} else {
for (const filePath of selectedPaths) {
await gitRollbackFile(folder.path, filePath)
}
toast.success(`已回滚 ${selectedPaths.length} 个文件`)
toast.success(
t("toasts.rolledBackFiles", {
count: selectedPaths.length,
})
)
}
resetDirectoryGitActionDialog()
@@ -844,7 +855,9 @@ export function GitChangesTab() {
const message = error instanceof Error ? error.message : String(error)
setDirectoryGitError(message)
toast.error(
directoryGitActionType === "add" ? "添加到VCS失败" : "回滚失败",
directoryGitActionType === "add"
? t("toasts.addToVcsFailed")
: t("toasts.rollbackFailed"),
{
description: message,
}
@@ -858,6 +871,7 @@ export function GitChangesTab() {
fetchChanges,
folder?.path,
resetDirectoryGitActionDialog,
t,
])
useEffect(() => {
@@ -893,7 +907,7 @@ export function GitChangesTab() {
void openWorkingTreeDiff(node.path, { mode: "overview" })
}}
>
{tCommon("viewDiff")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -901,14 +915,14 @@ export function GitChangesTab() {
}}
variant="destructive"
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
void handleAddToVcs(target)
}}
>
VCS
{t("actions.addToVcs")}
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
@@ -959,14 +973,14 @@ export function GitChangesTab() {
void openFilePreview(file.path)
}}
>
{tCommon("openFile")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
void openWorkingTreeDiff(file.path)
}}
>
{tCommon("viewDiff")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -974,14 +988,14 @@ export function GitChangesTab() {
}}
variant="destructive"
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
void handleAddToVcs(target)
}}
>
VCS
{t("actions.addToVcs")}
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
@@ -992,6 +1006,8 @@ export function GitChangesTab() {
handleRequestRollback,
openFilePreview,
openWorkingTreeDiff,
t,
tCommon,
]
)
@@ -1023,7 +1039,7 @@ export function GitChangesTab() {
void openWorkingTreeDiff(node.path, { mode: "overview" })
}}
>
{tCommon("viewDiff")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -1031,14 +1047,14 @@ export function GitChangesTab() {
}}
variant="destructive"
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
void handleAddToVcs(target)
}}
>
VCS
{t("actions.addToVcs")}
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
@@ -1079,14 +1095,14 @@ export function GitChangesTab() {
void openFilePreview(file.path)
}}
>
{tCommon("openFile")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
void openWorkingTreeDiff(file.path)
}}
>
{tCommon("viewDiff")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
@@ -1094,14 +1110,14 @@ export function GitChangesTab() {
}}
variant="destructive"
>
{t("actions.rollback")}
</ContextMenuItem>
<ContextMenuItem
onSelect={() => {
void handleAddToVcs(target)
}}
>
VCS
{t("actions.addToVcs")}
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
@@ -1112,6 +1128,8 @@ export function GitChangesTab() {
handleRequestRollback,
openFilePreview,
openWorkingTreeDiff,
t,
tCommon,
]
)
@@ -1139,14 +1157,16 @@ export function GitChangesTab() {
<div className="h-full min-h-0 overflow-y-auto">
{trackedChanges.length === 0 && untrackedChanges.length === 0 ? (
<div className="px-2 py-2 text-xs text-muted-foreground">
{t("noChanges")}
</div>
) : (
<div className="space-y-2 pb-2">
{trackedChanges.length > 0 && (
<section className="space-y-1">
<div className="flex items-center justify-between px-2 py-1 text-[11px] text-muted-foreground">
<span> ({trackedChanges.length})</span>
<span>
{t("trackedChanges", { count: trackedChanges.length })}
</span>
<Button
variant="ghost"
size="icon"
@@ -1154,10 +1174,14 @@ export function GitChangesTab() {
onClick={toggleTrackedExpanded}
disabled={!trackedCanExpand && !trackedCanCollapse}
title={
trackedCanExpand ? "展开已跟踪改动" : "折叠已跟踪改动"
trackedCanExpand
? t("expandTracked")
: t("collapseTracked")
}
aria-label={
trackedCanExpand ? "展开已跟踪改动" : "折叠已跟踪改动"
trackedCanExpand
? t("expandTracked")
: t("collapseTracked")
}
>
{trackedCanExpand ? (
@@ -1188,7 +1212,9 @@ export function GitChangesTab() {
{untrackedChanges.length > 0 && (
<section className="space-y-1">
<div className="flex items-center justify-between px-2 py-1 text-[11px] text-muted-foreground">
<span> ({untrackedChanges.length})</span>
<span>
{t("untrackedFiles", { count: untrackedChanges.length })}
</span>
<Button
variant="ghost"
size="icon"
@@ -1196,10 +1222,14 @@ export function GitChangesTab() {
onClick={toggleUntrackedExpanded}
disabled={!untrackedCanExpand && !untrackedCanCollapse}
title={
untrackedCanExpand ? "展开未跟踪文件" : "折叠未跟踪文件"
untrackedCanExpand
? t("expandUntracked")
: t("collapseUntracked")
}
aria-label={
untrackedCanExpand ? "展开未跟踪文件" : "折叠未跟踪文件"
untrackedCanExpand
? t("expandUntracked")
: t("collapseUntracked")
}
>
{untrackedCanExpand ? (
@@ -1240,19 +1270,29 @@ export function GitChangesTab() {
<DialogContent className="sm:max-w-2xl">
<DialogHeader>
<DialogTitle>
{directoryGitActionType === "add" ? "添加到VCS" : "回滚"}
{directoryGitActionType === "add"
? t("actions.addToVcs")
: t("actions.rollback")}
</DialogTitle>
<DialogDescription>
{directoryGitActionTarget
? `选择目录 ${directoryGitActionTarget.path} 下要${directoryGitActionType === "add" ? "添加到VCS" : "回滚"}的文件。`
: "选择要操作的文件。"}
? directoryGitActionType === "add"
? t("directoryDialog.descriptionAdd", {
path: directoryGitActionTarget.path,
})
: t("directoryDialog.descriptionRollback", {
path: directoryGitActionTarget.path,
})
: t("directoryDialog.descriptionFallback")}
</DialogDescription>
</DialogHeader>
<div className="space-y-3">
<div className="flex items-center justify-between gap-2 text-xs">
<span className="text-muted-foreground">
{directoryGitSelectedPaths.size} /{" "}
{directoryGitAllFilePaths.length}
{t("directoryDialog.selectionCount", {
selected: directoryGitSelectedPaths.size,
total: directoryGitAllFilePaths.length,
})}
</span>
<Button
type="button"
@@ -1261,13 +1301,15 @@ export function GitChangesTab() {
disabled={directoryGitLoading || directoryGitSubmitting}
onClick={handleToggleDirectoryGitSelectAll}
>
{directoryGitAllSelected ? "取消全选" : "全选"}
{directoryGitAllSelected
? t("directoryDialog.unselectAll")
: t("directoryDialog.selectAll")}
</Button>
</div>
<div className="max-h-80 overflow-auto rounded-md border">
{directoryGitLoading ? (
<div className="py-8 text-center text-xs text-muted-foreground">
...
{t("directoryDialog.loadingCandidates")}
</div>
) : directoryGitError ? (
<div className="p-3 text-xs text-destructive">
@@ -1309,7 +1351,7 @@ export function GitChangesTab() {
</div>
) : (
<div className="py-8 text-center text-xs text-muted-foreground">
{t("directoryDialog.noOperableFiles")}
</div>
)}
</div>
@@ -1320,7 +1362,7 @@ export function GitChangesTab() {
disabled={directoryGitSubmitting}
onClick={resetDirectoryGitActionDialog}
>
{tCommon("cancel")}
</Button>
<Button
type="button"
@@ -1338,7 +1380,9 @@ export function GitChangesTab() {
void handleDirectoryGitActionConfirm()
}}
>
{directoryGitActionType === "add" ? "添加到VCS" : "回滚"}
{directoryGitActionType === "add"
? t("actions.addToVcs")
: t("actions.rollback")}
</Button>
</DialogFooter>
</div>
@@ -1354,15 +1398,23 @@ export function GitChangesTab() {
>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle></AlertDialogTitle>
<AlertDialogTitle>{t("rollbackConfirm.title")}</AlertDialogTitle>
<AlertDialogDescription>
{rollbackTarget
? `确定回滚${rollbackTarget.kind === "dir" ? "目录" : "文件"} "${rollbackTarget.name}" 的本地修改吗?`
: "确定回滚本地修改吗?"}
? t("rollbackConfirm.descriptionWithTarget", {
kind:
rollbackTarget.kind === "dir"
? t("rollbackConfirm.kindDirectory")
: t("rollbackConfirm.kindFile"),
name: rollbackTarget.name,
})
: t("rollbackConfirm.descriptionFallback")}
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel disabled={rollingBack}></AlertDialogCancel>
<AlertDialogCancel disabled={rollingBack}>
{tCommon("cancel")}
</AlertDialogCancel>
<AlertDialogAction
variant="destructive"
disabled={rollingBack}
@@ -1370,7 +1422,7 @@ export function GitChangesTab() {
void handleRollbackConfirm()
}}
>
{t("actions.rollback")}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>