欢迎页面支持多语言

This commit is contained in:
xintaofei
2026-03-07 12:17:57 +08:00
parent aeecc4769c
commit 6c48be023c
15 changed files with 685 additions and 72 deletions

View File

@@ -1,12 +1,15 @@
"use client"
import { useState } from "react"
import { useMemo, useState } from "react"
import { Search, X, FolderOpen } from "lucide-react"
import { formatDistanceToNow } from "date-fns"
import { zhCN } from "date-fns/locale"
import { enUS, zhCN, zhTW } from "date-fns/locale"
import { useLocale, useTranslations } from "next-intl"
import { toast } from "sonner"
import { openFolderWindow, removeFolderFromHistory } from "@/lib/tauri"
import type { FolderHistoryEntry } from "@/lib/types"
import { Input } from "@/components/ui/input"
import { resolveWelcomeError } from "@/components/welcome/error-utils"
interface FolderListProps {
history: FolderHistoryEntry[]
@@ -15,21 +18,32 @@ interface FolderListProps {
}
export function FolderList({ history, loading, onRefresh }: FolderListProps) {
const t = useTranslations("WelcomePage")
const locale = useLocale()
const [search, setSearch] = useState("")
const dateFnsLocale =
locale === "zh-CN" ? zhCN : locale === "zh-TW" ? zhTW : enUS
const filtered = search
? history.filter(
(h) =>
h.name.toLowerCase().includes(search.toLowerCase()) ||
h.path.toLowerCase().includes(search.toLowerCase())
)
: history
const filtered = useMemo(() => {
if (!search) return history
const lowerCaseSearch = search.toLowerCase()
return history.filter(
(h) =>
h.name.toLowerCase().includes(lowerCaseSearch) ||
h.path.toLowerCase().includes(lowerCaseSearch)
)
}, [history, search])
const handleOpen = async (path: string) => {
try {
await openFolderWindow(path)
} catch (e) {
console.error("Failed to open folder:", e)
} catch (err) {
console.error("Failed to open folder:", err)
const resolvedError = resolveWelcomeError(err)
toast.error(t("toasts.openFolderFailed"), {
description: resolvedError.detail ?? t(resolvedError.key),
})
}
}
@@ -40,6 +54,10 @@ export function FolderList({ history, loading, onRefresh }: FolderListProps) {
onRefresh()
} catch (err) {
console.error("Failed to remove folder:", err)
const resolvedError = resolveWelcomeError(err)
toast.error(t("toasts.removeFromHistoryFailed"), {
description: resolvedError.detail ?? t(resolvedError.key),
})
}
}
@@ -48,7 +66,7 @@ export function FolderList({ history, loading, onRefresh }: FolderListProps) {
<div className="relative mb-4">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
placeholder="搜索文件夹..."
placeholder={t("searchPlaceholder")}
value={search}
onChange={(e) => setSearch(e.target.value)}
className="pl-9 h-9"
@@ -58,12 +76,12 @@ export function FolderList({ history, loading, onRefresh }: FolderListProps) {
<div className="flex-1 overflow-y-auto">
{loading ? (
<div className="flex items-center justify-center h-32 text-sm text-muted-foreground">
Loading...
{t("loading")}
</div>
) : filtered.length === 0 ? (
<div className="flex flex-col items-center justify-center h-32 text-sm text-muted-foreground gap-2">
<FolderOpen className="h-8 w-8" />
<span></span>
<span>{t("emptyFolders")}</span>
</div>
) : (
filtered.map((entry) => (
@@ -93,7 +111,7 @@ export function FolderList({ history, loading, onRefresh }: FolderListProps) {
<span className="text-xs text-muted-foreground">
{formatDistanceToNow(new Date(entry.last_opened_at), {
addSuffix: true,
locale: zhCN,
locale: dateFnsLocale,
})}
</span>
</div>
@@ -101,7 +119,9 @@ export function FolderList({ history, loading, onRefresh }: FolderListProps) {
<button
className="opacity-0 group-hover:opacity-100 transition-opacity p-1 hover:bg-destructive/10 rounded shrink-0 mt-0.5"
onClick={(e) => handleRemove(e, entry.path)}
title="从历史中移除"
title={t("removeFromHistory")}
aria-label={t("removeFromHistory")}
type="button"
>
<X className="h-3.5 w-3.5 text-muted-foreground hover:text-destructive" />
</button>