From 1d0b74136f5abe1ba9e379b0f095132e37b13e0f Mon Sep 17 00:00:00 2001 From: cfngc4594 Date: Wed, 16 Apr 2025 00:40:36 +0800 Subject: [PATCH] refactor(i18n): replace hardcoded texts with i18n message keys for auth --- messages/en.json | 46 +++++++++++++++++++++ messages/zh.json | 46 +++++++++++++++++++++ src/actions/auth.ts | 17 +++++--- src/components/avatar-button.tsx | 4 +- src/components/credentials-sign-in-form.tsx | 14 ++++--- src/components/credentials-sign-up-form.tsx | 16 +++---- src/components/github-sign-in-form.tsx | 4 +- src/components/settings-button.tsx | 4 +- src/components/sign-in-form.tsx | 12 +++--- src/components/sign-up-form.tsx | 12 +++--- 10 files changed, 141 insertions(+), 34 deletions(-) diff --git a/messages/en.json b/messages/en.json index 483f0db..9294c07 100644 --- a/messages/en.json +++ b/messages/en.json @@ -25,6 +25,27 @@ "open": "Open Bot", "close": "Close Bot" }, + "CredentialsSignInForm": { + "email": "Email", + "password": "Password", + "signIn": "Sign In", + "signingIn": "Signing In...", + "signInSuccess": "Signed In Successfully", + "signInFailed": "Sign In Failed", + "showPassword": "Show password", + "hidePassword": "Hide password" + }, + "CredentialsSignUpForm": { + "email": "Email", + "password": "Password", + "signUp": "Sign Up", + "creatingAccount": "Creating Account...", + "signUpSuccess": "Account Created", + "signUpSuccessDescription": "You can now sign in with your credentials", + "signUpFailed": "Registration Failed", + "showPassword": "Show password", + "hidePassword": "Hide password" + }, "DetailsPage": { "BackButton": "All Submissions", "Time": "Submitted on", @@ -38,6 +59,7 @@ "MEDIUM": "MEDIUM", "HARD": "HARD" }, + "GithubSignInForm": "Continue with GitHub", "LanguageSettings": { "en": { "flag": "🇺🇸", @@ -82,6 +104,30 @@ "Advanced": "Advanced" } }, + "SignInForm": { + "title": "Sign in to your account", + "description": "Enter your email below to sign in to your account", + "or": "Or", + "noAccount": "Don't have an account?", + "signUp": "Sign up" + }, + "signInWithCredentials": { + "userNotFound": "User not found.", + "invalidCredentials": "Invalid credentials.", + "incorrectPassword": "Incorrect password.", + "signInFailedFallback": "Failed to sign in. Please try again." + }, + "signUpWithCredentials": { + "userAlreadyExists": "User already exists.", + "registrationFailedFallback": "Registration failed. Please try again." + }, + "SignUpForm": { + "title": "Sign up to your account", + "description": "Enter your email below to sign up to your account", + "or": "Or", + "haveAccount": "Already have an account?", + "signIn": "Sign in" + }, "StatusMessage": { "PD": "Pending", "QD": "Queued", diff --git a/messages/zh.json b/messages/zh.json index f15991d..ec17cf9 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -25,6 +25,27 @@ "open": "打开AI助手", "close": "关闭AI助手" }, + "CredentialsSignInForm": { + "email": "邮箱", + "password": "密码", + "signIn": "登录", + "signingIn": "正在登录...", + "signInSuccess": "登录成功", + "signInFailed": "登录失败", + "showPassword": "显示密码", + "hidePassword": "隐藏密码" + }, + "CredentialsSignUpForm": { + "email": "邮箱", + "password": "密码", + "signUp": "注册", + "creatingAccount": "正在创建账户...", + "signUpSuccess": "账户创建成功", + "signUpSuccessDescription": "你现在可以使用凭据登录", + "signUpFailed": "注册失败", + "showPassword": "显示密码", + "hidePassword": "隐藏密码" + }, "DetailsPage": { "BackButton": "所有提交记录", "Time": "提交于", @@ -38,6 +59,7 @@ "MEDIUM": "中等", "HARD": "困难" }, + "GithubSignInForm": "使用 GitHub 登录", "LanguageSettings": { "en": { "flag": "🇺🇸", @@ -82,6 +104,30 @@ "Advanced": "高级设置" } }, + "SignInForm": { + "title": "登录到你的账户", + "description": "请输入你的邮箱以登录账户", + "or": "或者", + "noAccount": "还没有账户?", + "signUp": "注册" + }, + "signInWithCredentials": { + "userNotFound": "未找到用户。", + "invalidCredentials": "凭据无效。", + "incorrectPassword": "密码错误。", + "signInFailedFallback": "登录失败,请重试。" + }, + "signUpWithCredentials": { + "userAlreadyExists": "用户已存在。", + "registrationFailedFallback": "注册失败,请重试。" + }, + "SignUpForm": { + "title": "注册你的账户", + "description": "请输入你的邮箱以注册账户", + "or": "或者", + "haveAccount": "已经有账户了?", + "signIn": "登录" + }, "StatusMessage": { "PD": "待处理", "QD": "排队中", diff --git a/src/actions/auth.ts b/src/actions/auth.ts index 4f9c9c6..ceb5340 100644 --- a/src/actions/auth.ts +++ b/src/actions/auth.ts @@ -4,12 +4,15 @@ import bcrypt from "bcrypt"; import prisma from "@/lib/prisma"; import { signIn } from "@/lib/auth"; import { authSchema } from "@/lib/zod"; +import { getTranslations } from "next-intl/server"; import { CredentialsSignInFormValues } from "@/components/credentials-sign-in-form"; import { CredentialsSignUpFormValues } from "@/components/credentials-sign-up-form"; const saltRounds = 10; export async function signInWithCredentials(formData: CredentialsSignInFormValues, redirectTo?: string) { + const t = await getTranslations("signInWithCredentials"); + try { // Parse credentials using authSchema for validation const { email, password } = await authSchema.parseAsync(formData); @@ -19,35 +22,37 @@ export async function signInWithCredentials(formData: CredentialsSignInFormValue // Check if the user exists if (!user) { - throw new Error("User not found."); + throw new Error(t("userNotFound")); } // Check if the user has a password if (!user.password) { - throw new Error("Invalid credentials."); + throw new Error(t("invalidCredentials")); } // Check if the password matches const passwordMatch = await bcrypt.compare(password, user.password); if (!passwordMatch) { - throw new Error("Incorrect password."); + throw new Error(t("incorrectPassword")); } await signIn("credentials", { ...formData, redirectTo, redirect: !!redirectTo }); return { success: true }; } catch (error) { - return { error: error instanceof Error ? error.message : "Failed to sign in. Please try again." }; + return { error: error instanceof Error ? error.message : t("signInFailedFallback") }; } } export async function signUpWithCredentials(formData: CredentialsSignUpFormValues) { + const t = await getTranslations("signUpWithCredentials"); + try { const validatedData = await authSchema.parseAsync(formData); // Check if user already exists const existingUser = await prisma.user.findUnique({ where: { email: validatedData.email } }); if (existingUser) { - throw new Error("User already exists"); + throw new Error(t("userAlreadyExists")); } // Hash password and create user @@ -64,7 +69,7 @@ export async function signUpWithCredentials(formData: CredentialsSignUpFormValue return { success: true }; } catch (error) { - return { error: error instanceof Error ? error.message : "Registration failed. Please try again." }; + return { error: error instanceof Error ? error.message : t("registrationFailedFallback") }; } } diff --git a/src/components/avatar-button.tsx b/src/components/avatar-button.tsx index 62853e3..943aaa9 100644 --- a/src/components/avatar-button.tsx +++ b/src/components/avatar-button.tsx @@ -1,4 +1,3 @@ -import { LogOut } from "lucide-react"; import { DropdownMenu, DropdownMenuContent, @@ -8,6 +7,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { LogOutIcon } from "lucide-react"; import { auth, signOut } from "@/lib/auth"; import { getTranslations } from "next-intl/server"; import { Skeleton } from "@/components/ui/skeleton"; @@ -65,7 +65,7 @@ export async function AvatarButton() { - + {t("LogOut")} diff --git a/src/components/credentials-sign-in-form.tsx b/src/components/credentials-sign-in-form.tsx index 4984e0b..84e370d 100644 --- a/src/components/credentials-sign-in-form.tsx +++ b/src/components/credentials-sign-in-form.tsx @@ -12,6 +12,7 @@ import { import { toast } from "sonner"; import { authSchema } from "@/lib/zod"; import { useForm } from "react-hook-form"; +import { useTranslations } from "next-intl"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { useState, useTransition } from "react"; @@ -26,6 +27,7 @@ export function CredentialsSignInForm() { const router = useRouter(); const searchParams = useSearchParams(); const redirectTo = searchParams.get("redirectTo"); + const t = useTranslations("CredentialsSignInForm"); const [isPending, startTransition] = useTransition(); const [isVisible, setIsVisible] = useState(false); @@ -44,11 +46,11 @@ export function CredentialsSignInForm() { const result = await signInWithCredentials(data); if (result?.error) { - toast.error("Sign In Failed", { + toast.error(t("signInFailed"), { description: result.error, }); } else { - toast.success("Signed In Successfully"); + toast.success(t("signInSuccess")); router.push(redirectTo || "/"); } }); @@ -62,7 +64,7 @@ export function CredentialsSignInForm() { name="email" render={({ field }) => ( - Email + {t("email")}
@@ -81,7 +83,7 @@ export function CredentialsSignInForm() { name="password" render={({ field }) => ( - Password + {t("password")}
@@ -111,7 +113,7 @@ export function CredentialsSignInForm() { /> diff --git a/src/components/credentials-sign-up-form.tsx b/src/components/credentials-sign-up-form.tsx index 3d7b34f..af9750c 100644 --- a/src/components/credentials-sign-up-form.tsx +++ b/src/components/credentials-sign-up-form.tsx @@ -12,6 +12,7 @@ import { import { toast } from "sonner"; import { authSchema } from "@/lib/zod"; import { useForm } from "react-hook-form"; +import { useTranslations } from "next-intl"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { useState, useTransition } from "react"; @@ -26,6 +27,7 @@ export function CredentialsSignUpForm() { const router = useRouter(); const searchParams = useSearchParams(); const redirectTo = searchParams.get("redirectTo"); + const t = useTranslations("CredentialsSignUpForm"); const [isPending, startTransition] = useTransition(); const [isVisible, setIsVisible] = useState(false); @@ -44,12 +46,12 @@ export function CredentialsSignUpForm() { const result = await signUpWithCredentials(data); if (result?.error) { - toast.error("Registration Failed", { + toast.error(t("signUpFailed"), { description: result.error, }); } else { - toast.success("Account Created", { - description: "You can now sign in with your credentials", + toast.success(t("signUpSuccess"), { + description: t("signUpSuccessDescription"), }); router.push(`/sign-in?${redirectTo}`) } @@ -64,7 +66,7 @@ export function CredentialsSignUpForm() { name="email" render={({ field }) => ( - Email + {t("email")}
@@ -83,7 +85,7 @@ export function CredentialsSignUpForm() { name="password" render={({ field }) => ( - Password + {t("password")}
@@ -113,7 +115,7 @@ export function CredentialsSignUpForm() { /> diff --git a/src/components/github-sign-in-form.tsx b/src/components/github-sign-in-form.tsx index 984a855..30d2022 100644 --- a/src/components/github-sign-in-form.tsx +++ b/src/components/github-sign-in-form.tsx @@ -1,10 +1,12 @@ "use client"; +import { useTranslations } from "next-intl"; import { Button } from "@/components/ui/button"; import { signInWithGithub } from "@/actions/auth"; import { useSearchParams } from "next/navigation"; export function GithubSignInForm() { + const t = useTranslations(); const searchParams = useSearchParams(); const redirectTo = searchParams.get("redirectTo"); const signInAction = signInWithGithub.bind(null, redirectTo || "/"); @@ -18,7 +20,7 @@ export function GithubSignInForm() { fill="currentColor" /> - Continue with GitHub + {t("GithubSignInForm")} ); diff --git a/src/components/settings-button.tsx b/src/components/settings-button.tsx index b0b2511..382fa6c 100644 --- a/src/components/settings-button.tsx +++ b/src/components/settings-button.tsx @@ -1,6 +1,6 @@ "use client"; -import { Settings } from "lucide-react"; +import { SettingsIcon } from "lucide-react"; import { useTranslations } from "next-intl"; import { useSettingsStore } from "@/stores/useSettingsStore"; import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; @@ -11,7 +11,7 @@ export function SettingsButton() { return ( setDialogOpen(true)}> - + {t("Settings")} ); diff --git a/src/components/sign-in-form.tsx b/src/components/sign-in-form.tsx index b792e4a..db8213c 100644 --- a/src/components/sign-in-form.tsx +++ b/src/components/sign-in-form.tsx @@ -1,5 +1,6 @@ "use client"; +import { useTranslations } from "next-intl"; import { useRouter, useSearchParams } from "next/navigation"; import { GithubSignInForm } from "@/components/github-sign-in-form"; import { CredentialsSignInForm } from "@/components/credentials-sign-in-form"; @@ -7,6 +8,7 @@ import { CredentialsSignInForm } from "@/components/credentials-sign-in-form"; export function SignInForm() { const router = useRouter(); const searchParams = useSearchParams(); + const t = useTranslations("SignInForm"); const handleSignUp = () => { const params = new URLSearchParams(searchParams.toString()); @@ -16,25 +18,25 @@ export function SignInForm() { return (
-

Sign in to your account

+

{t("title")}

- Enter your email below to sign in to your account + {t("description")}

- Or + {t("or")}
- Don't have an account?{" "} + {t("noAccount")}{" "}
diff --git a/src/components/sign-up-form.tsx b/src/components/sign-up-form.tsx index ac44a2f..5a54453 100644 --- a/src/components/sign-up-form.tsx +++ b/src/components/sign-up-form.tsx @@ -1,5 +1,6 @@ "use client"; +import { useTranslations } from "next-intl"; import { useRouter, useSearchParams } from "next/navigation"; import { GithubSignInForm } from "@/components/github-sign-in-form"; import { CredentialsSignUpForm } from "@/components/credentials-sign-up-form"; @@ -7,6 +8,7 @@ import { CredentialsSignUpForm } from "@/components/credentials-sign-up-form"; export function SignUpForm() { const router = useRouter(); const searchParams = useSearchParams(); + const t = useTranslations("SignUpForm"); const handleSignIn = () => { const params = new URLSearchParams(searchParams.toString()); @@ -16,25 +18,25 @@ export function SignUpForm() { return (
-

Sign up to your account

+

{t("title")}

- Enter your email below to sign up to your account + {t("description")}

- Or + {t("or")}
- Already have an account?{" "} + {t("haveAccount")}{" "}