feat: add internationalization support with next-intl

This commit is contained in:
beilunyang
2025-10-13 00:57:32 +08:00
parent 0fcc4b9e85
commit d175017b51
46 changed files with 1436 additions and 432 deletions
+20 -16
View File
@@ -1,6 +1,7 @@
"use client"
import { useState } from "react"
import { useTranslations } from "next-intl"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
@@ -21,6 +22,9 @@ interface SendDialogProps {
}
export function SendDialog({ emailId, fromAddress, onSendSuccess }: SendDialogProps) {
const t = useTranslations("emails.send")
const tList = useTranslations("emails.list")
const tCommon = useTranslations("common.actions")
const [open, setOpen] = useState(false)
const [loading, setLoading] = useState(false)
const [to, setTo] = useState("")
@@ -31,8 +35,8 @@ export function SendDialog({ emailId, fromAddress, onSendSuccess }: SendDialogPr
const handleSend = async () => {
if (!to.trim() || !subject.trim() || !content.trim()) {
toast({
title: "错误",
description: "收件人、主题和内容都是必填项",
title: tList("error"),
description: t("toPlaceholder") + ", " + t("subjectPlaceholder") + ", " + t("contentPlaceholder"),
variant: "destructive"
})
return
@@ -49,7 +53,7 @@ export function SendDialog({ emailId, fromAddress, onSendSuccess }: SendDialogPr
if (!response.ok) {
const data = await response.json()
toast({
title: "错误",
title: tList("error"),
description: (data as { error: string }).error,
variant: "destructive"
})
@@ -57,8 +61,8 @@ export function SendDialog({ emailId, fromAddress, onSendSuccess }: SendDialogPr
}
toast({
title: "成功",
description: "邮件已发送"
title: tList("success"),
description: t("success")
})
setOpen(false)
setTo("")
@@ -69,8 +73,8 @@ export function SendDialog({ emailId, fromAddress, onSendSuccess }: SendDialogPr
} catch {
toast({
title: "错误",
description: "发送邮件失败",
title: tList("error"),
description: t("failed"),
variant: "destructive"
})
} finally {
@@ -90,46 +94,46 @@ export function SendDialog({ emailId, fromAddress, onSendSuccess }: SendDialogPr
className="h-8 gap-2 hover:bg-primary/10 hover:text-primary transition-colors"
>
<Send className="h-4 w-4" />
<span className="hidden sm:inline"></span>
<span className="hidden sm:inline">{t("title")}</span>
</Button>
</TooltipTrigger>
</DialogTrigger>
<TooltipContent className="sm:hidden">
<p>使</p>
<p>{t("title")}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<DialogContent>
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogTitle>{t("title")}</DialogTitle>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="text-sm text-muted-foreground">
: {fromAddress}
{t("from")}: {fromAddress}
</div>
<Input
value={to}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setTo(e.target.value)}
placeholder="收件人邮箱地址"
placeholder={t("toPlaceholder")}
/>
<Input
value={subject}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSubject(e.target.value)}
placeholder="邮件主题"
placeholder={t("subjectPlaceholder")}
/>
<Textarea
value={content}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setContent(e.target.value)}
placeholder="邮件内容"
placeholder={t("contentPlaceholder")}
rows={6}
/>
</div>
<div className="flex justify-end gap-2">
<Button variant="outline" onClick={() => setOpen(false)} disabled={loading}>
{tCommon("cancel")}
</Button>
<Button onClick={handleSend} disabled={loading}>
{loading ? "发送中..." : "发送"}
{loading ? t("sending") : t("send")}
</Button>
</div>
</DialogContent>