Skip to content

Commit 5cf4cfc

Browse files
committed
feat(i18n): 添加个人资料和OAuth页面的多语言支持
1 parent 43716da commit 5cf4cfc

7 files changed

Lines changed: 131 additions & 28 deletions

File tree

web/src/locales/en-US/oauth.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"error": {
3+
"title": "OAuth2 Login Issue",
4+
"loginFailed": "Login Failed",
5+
"errorDetails": "Error Details",
6+
"provider": "Provider",
7+
"providers": {
8+
"github": "GitHub",
9+
"cloudflare": "Cloudflare"
10+
},
11+
"reasons": {
12+
"title": "Possible reasons:",
13+
"reason1": "• System is already bound to another OAuth2 account",
14+
"reason2": "• Each system can only bind one OAuth2 user",
15+
"reason3": "• Please contact the administrator or log in with the bound account"
16+
},
17+
"actions": {
18+
"retryLogin": "Retry Login",
19+
"goHome": "Go Home"
20+
},
21+
"help": "If you need help, please contact the system administrator",
22+
"defaultError": "OAuth2 login failed"
23+
},
24+
"success": {
25+
"processing": "Completing authentication..."
26+
}
27+
}

web/src/locales/en-US/settings.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,27 @@
9595
"resetSuccessDesc": "Settings have been restored to default values"
9696
}
9797
},
98+
"profile": {
99+
"title": "Personal Profile",
100+
"description": "Manage your personal information and account settings",
101+
"avatar": {
102+
"title": "Avatar",
103+
"description": "Upload your avatar image, square images recommended",
104+
"uploadButton": "Upload New Avatar"
105+
},
106+
"fields": {
107+
"username": "Username",
108+
"usernamePlaceholder": "Enter username",
109+
"email": "Email Address",
110+
"emailPlaceholder": "Enter email address",
111+
"password": "Change Password",
112+
"passwordPlaceholder": "Enter new password"
113+
},
114+
"actions": {
115+
"reset": "Reset",
116+
"save": "Save Changes"
117+
}
118+
},
98119
"security": {
99120
"basic": {
100121
"title": "Basic Security Settings",

web/src/locales/zh-CN/oauth.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"error": {
3+
"title": "OAuth2 登录遇到问题",
4+
"loginFailed": "登录失败",
5+
"errorDetails": "错误详情",
6+
"provider": "提供者",
7+
"providers": {
8+
"github": "GitHub",
9+
"cloudflare": "Cloudflare"
10+
},
11+
"reasons": {
12+
"title": "可能的原因:",
13+
"reason1": "• 可能的原因:系统已绑定其他 OAuth2 账户",
14+
"reason2": "• 每个系统只能绑定一个 OAuth2 用户",
15+
"reason3": "• 请联系管理员或使用已绑定的账户登录"
16+
},
17+
"actions": {
18+
"retryLogin": "重新登录",
19+
"goHome": "返回首页"
20+
},
21+
"help": "如需帮助,请联系系统管理员",
22+
"defaultError": "OAuth2 登录失败"
23+
},
24+
"success": {
25+
"processing": "正在完成认证..."
26+
}
27+
}

web/src/locales/zh-CN/settings.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,27 @@
9595
"resetSuccessDesc": "设置已恢复默认值"
9696
}
9797
},
98+
"profile": {
99+
"title": "个人资料",
100+
"description": "管理您的个人资料信息和账户设置",
101+
"avatar": {
102+
"title": "头像",
103+
"description": "上传您的头像图片,建议使用正方形图片",
104+
"uploadButton": "上传新头像"
105+
},
106+
"fields": {
107+
"username": "用户名",
108+
"usernamePlaceholder": "请输入用户名",
109+
"email": "邮箱地址",
110+
"emailPlaceholder": "请输入邮箱地址",
111+
"password": "修改密码",
112+
"passwordPlaceholder": "输入新密码"
113+
},
114+
"actions": {
115+
"reset": "重置",
116+
"save": "保存更改"
117+
}
118+
},
98119
"security": {
99120
"basic": {
100121
"title": "基础安全设置",

web/src/pages/oauth-error/index.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useNavigate, useSearchParams } from "react-router-dom";
44
import { useTheme } from "next-themes";
55
import { useIsSSR } from "@react-aria/ssr";
66
import { motion } from "framer-motion";
7+
import { useTranslation } from "react-i18next";
78
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
89
import {
910
faShieldAlt,
@@ -14,6 +15,7 @@ import {
1415

1516
export default function OAuthErrorPage() {
1617
const navigate = useNavigate();
18+
const { t } = useTranslation("oauth");
1719
const [searchParams] = useSearchParams();
1820
const [errorMessage, setErrorMessage] = useState("");
1921
const [provider, setProvider] = useState("");
@@ -25,12 +27,12 @@ export default function OAuthErrorPage() {
2527

2628
useEffect(() => {
2729
// 从 URL 参数获取错误信息
28-
const error = searchParams.get("error") || "OAuth2 登录失败";
30+
const error = searchParams.get("error") || t("error.defaultError");
2931
const providerParam = searchParams.get("provider") || "";
3032

3133
setErrorMessage(decodeURIComponent(error));
3234
setProvider(providerParam);
33-
}, [searchParams]);
35+
}, [searchParams, t]);
3436

3537
const handleRetryLogin = () => {
3638
navigate("/login");
@@ -66,7 +68,7 @@ export default function OAuthErrorPage() {
6668
<h1 className="text-2xl font-bold text-foreground">
6769
NodePassDash
6870
</h1>
69-
<p className="text-small text-default-500">OAuth2 登录遇到问题</p>
71+
<p className="text-small text-default-500">{t("error.title")}</p>
7072
</CardHeader>
7173

7274
<CardBody className="px-8 pb-8">
@@ -89,32 +91,32 @@ export default function OAuthErrorPage() {
8991
{/* 错误信息 */}
9092
<div className="text-center space-y-3">
9193
<h2 className="text-xl font-semibold text-danger">
92-
登录失败
94+
{t("error.loginFailed")}
9395
</h2>
9496

9597
<div className="p-4 bg-danger-50 border border-danger-200 rounded-lg">
9698
<p className="text-danger text-sm font-medium mb-2">
97-
错误详情
99+
{t("error.errorDetails")}
98100
</p>
99101
<p className="text-danger-600 text-xs break-words">
100102
{errorMessage}
101103
</p>
102104
{provider && (
103105
<p className="text-danger-500 text-xs mt-2">
104-
提供者:{" "}
106+
{t("error.provider")}:{" "}
105107
{provider === "github"
106-
? "GitHub"
108+
? t("error.providers.github")
107109
: provider === "cloudflare"
108-
? "Cloudflare"
110+
? t("error.providers.cloudflare")
109111
: provider}
110112
</p>
111113
)}
112114
</div>
113115

114116
<div className="text-small text-default-500 space-y-1">
115-
<p>• 可能的原因:系统已绑定其他 OAuth2 账户</p>
116-
<p>• 每个系统只能绑定一个 OAuth2 用户</p>
117-
<p>• 请联系管理员或使用已绑定的账户登录</p>
117+
<p>{t("error.reasons.reason1")}</p>
118+
<p>{t("error.reasons.reason2")}</p>
119+
<p>{t("error.reasons.reason3")}</p>
118120
</div>
119121
</div>
120122

@@ -127,7 +129,7 @@ export default function OAuthErrorPage() {
127129
startContent={<FontAwesomeIcon icon={faRedo} />}
128130
onPress={handleRetryLogin}
129131
>
130-
重新登录
132+
{t("error.actions.retryLogin")}
131133
</Button>
132134

133135
<Button
@@ -138,15 +140,15 @@ export default function OAuthErrorPage() {
138140
variant="bordered"
139141
onPress={handleGoHome}
140142
>
141-
返回首页
143+
{t("error.actions.goHome")}
142144
</Button>
143145
</div>
144146

145147
{/* 帮助信息 */}
146148
<div className="text-center">
147149
<div className="inline-flex items-center gap-2 text-xs text-default-400">
148150
<FontAwesomeIcon icon={faInfoCircle} />
149-
<span>如需帮助,请联系系统管理员</span>
151+
<span>{t("error.help")}</span>
150152
</div>
151153
</div>
152154
</motion.div>

web/src/pages/oauth-success/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useEffect } from "react";
22
import { useNavigate, useSearchParams } from "react-router-dom";
33
import { Spinner } from "@heroui/react";
4+
import { useTranslation } from "react-i18next";
45

56
import { useAuth } from "@/components/auth/auth-provider";
67

@@ -10,6 +11,7 @@ import { useAuth } from "@/components/auth/auth-provider";
1011
*/
1112
export default function OAuthSuccessPage() {
1213
const navigate = useNavigate();
14+
const { t } = useTranslation("oauth");
1315
const [searchParams] = useSearchParams();
1416
const { setToken, setUserDirectly } = useAuth();
1517

@@ -55,7 +57,7 @@ export default function OAuthSuccessPage() {
5557
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-background to-default-100">
5658
<div className="text-center">
5759
<Spinner size="lg" />
58-
<p className="mt-4 text-default-500">正在完成认证...</p>
60+
<p className="mt-4 text-default-500">{t("success.processing")}</p>
5961
</div>
6062
</div>
6163
);

web/src/pages/settings/components/profile-settings.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Button,
88
Avatar,
99
} from "@heroui/react";
10+
import { useTranslation } from "react-i18next";
1011
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
1112
import {
1213
faUser,
@@ -16,13 +17,15 @@ import {
1617
} from "@fortawesome/free-solid-svg-icons";
1718

1819
export function ProfileSettings() {
20+
const { t } = useTranslation("settings");
21+
1922
return (
2023
<Card>
2124
<CardHeader>
2225
<div className="flex flex-col gap-1">
23-
<h3 className="text-xl font-semibold text-foreground">个人资料</h3>
26+
<h3 className="text-xl font-semibold text-foreground">{t("profile.title")}</h3>
2427
<p className="text-small text-default-500">
25-
管理您的个人资料信息和账户设置
28+
{t("profile.description")}
2629
</p>
2730
</div>
2831
</CardHeader>
@@ -35,12 +38,12 @@ export function ProfileSettings() {
3538
src="https://ui.shadcn.com/avatars/01.png"
3639
/>
3740
<div>
38-
<h4 className="text-lg font-medium text-foreground">头像</h4>
41+
<h4 className="text-lg font-medium text-foreground">{t("profile.avatar.title")}</h4>
3942
<p className="text-small text-default-500">
40-
上传您的头像图片,建议使用正方形图片
43+
{t("profile.avatar.description")}
4144
</p>
4245
<Button className="mt-2" color="primary" size="sm" variant="light">
43-
上传新头像
46+
{t("profile.avatar.uploadButton")}
4447
</Button>
4548
</div>
4649
</div>
@@ -56,8 +59,8 @@ export function ProfileSettings() {
5659
icon={faCircleCheck}
5760
/>
5861
}
59-
label="用户名"
60-
placeholder="请输入用户名"
62+
label={t("profile.fields.username")}
63+
placeholder={t("profile.fields.usernamePlaceholder")}
6164
startContent={
6265
<FontAwesomeIcon
6366
className="text-default-400 pointer-events-none flex-shrink-0"
@@ -71,8 +74,8 @@ export function ProfileSettings() {
7174
<div className="space-y-2">
7275
<Input
7376
defaultValue="admin@example.com"
74-
label="邮箱地址"
75-
placeholder="请输入邮箱地址"
77+
label={t("profile.fields.email")}
78+
placeholder={t("profile.fields.emailPlaceholder")}
7679
startContent={
7780
<FontAwesomeIcon
7881
className="text-default-400 pointer-events-none flex-shrink-0"
@@ -86,8 +89,8 @@ export function ProfileSettings() {
8689
{/* Password */}
8790
<div className="space-y-2">
8891
<Input
89-
label="修改密码"
90-
placeholder="输入新密码"
92+
label={t("profile.fields.password")}
93+
placeholder={t("profile.fields.passwordPlaceholder")}
9194
startContent={
9295
<FontAwesomeIcon
9396
className="text-default-400 pointer-events-none flex-shrink-0"
@@ -102,9 +105,9 @@ export function ProfileSettings() {
102105
{/* Actions */}
103106
<div className="flex justify-end gap-3 pt-4">
104107
<Button color="danger" variant="light">
105-
重置
108+
{t("profile.actions.reset")}
106109
</Button>
107-
<Button color="primary">保存更改</Button>
110+
<Button color="primary">{t("profile.actions.save")}</Button>
108111
</div>
109112
</CardBody>
110113
</Card>

0 commit comments

Comments
 (0)