mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat(i18n): add internationalization support for 2FA setup and error messages
This commit is contained in:
parent
2bced3e9b6
commit
6df680e9da
@ -26,6 +26,7 @@ import { authClient } from "@/lib/auth-client";
|
||||
import { api } from "@/utils/api";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Fingerprint, QrCode } from "lucide-react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
import QRCode from "qrcode";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
@ -55,6 +56,7 @@ type PinForm = z.infer<typeof PinSchema>;
|
||||
|
||||
export const Enable2FA = () => {
|
||||
const utils = api.useUtils();
|
||||
const { t } = useTranslation("settings");
|
||||
const [data, setData] = useState<TwoFactorSetupData | null>(null);
|
||||
const [backupCodes, setBackupCodes] = useState<string[]>([]);
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
@ -86,16 +88,18 @@ export const Enable2FA = () => {
|
||||
});
|
||||
|
||||
setStep("verify");
|
||||
toast.success("Scan the QR code with your authenticator app");
|
||||
toast.success(t("settings.2fa.scanQrCode"));
|
||||
} else {
|
||||
throw new Error("No TOTP URI received from server");
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Error setting up 2FA",
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: t("settings.2fa.errorSettingUp")
|
||||
);
|
||||
passwordForm.setError("password", {
|
||||
message: "Error verifying password",
|
||||
message: t("settings.2fa.errorVerifyingPassword"),
|
||||
});
|
||||
} finally {
|
||||
setIsPasswordLoading(false);
|
||||
@ -111,9 +115,9 @@ export const Enable2FA = () => {
|
||||
if (result.error) {
|
||||
if (result.error.code === "INVALID_TWO_FACTOR_AUTHENTICATION") {
|
||||
pinForm.setError("pin", {
|
||||
message: "Invalid code. Please try again.",
|
||||
message: t("settings.2fa.invalidCode"),
|
||||
});
|
||||
toast.error("Invalid verification code");
|
||||
toast.error(t("settings.2fa.invalidVerificationCode"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -124,14 +128,14 @@ export const Enable2FA = () => {
|
||||
throw new Error("No response received from server");
|
||||
}
|
||||
|
||||
toast.success("2FA configured successfully");
|
||||
toast.success(t("settings.2fa.success"));
|
||||
utils.user.get.invalidate();
|
||||
setIsDialogOpen(false);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
const errorMessage =
|
||||
error.message === "Failed to fetch"
|
||||
? "Connection error. Please check your internet connection."
|
||||
? t("settings.2fa.connectionError")
|
||||
: error.message;
|
||||
|
||||
pinForm.setError("pin", {
|
||||
@ -140,9 +144,9 @@ export const Enable2FA = () => {
|
||||
toast.error(errorMessage);
|
||||
} else {
|
||||
pinForm.setError("pin", {
|
||||
message: "Error verifying code",
|
||||
message: t("settings.2fa.errorVerifyingCode"),
|
||||
});
|
||||
toast.error("Error verifying 2FA code");
|
||||
toast.error(t("settings.2fa.errorVerifying2faCode"));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -176,16 +180,16 @@ export const Enable2FA = () => {
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="ghost">
|
||||
<Fingerprint className="size-4 text-muted-foreground" />
|
||||
Enable 2FA
|
||||
{t("settings.2fa.enable2fa")}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>2FA Setup</DialogTitle>
|
||||
<DialogTitle>{t("settings.2fa.title")}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{step === "password"
|
||||
? "Enter your password to begin 2FA setup"
|
||||
: "Scan the QR code and verify with your authenticator app"}
|
||||
? t("settings.2fa.enterPassword")
|
||||
: t("settings.2fa.scanQrCodeAndVerify")}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
@ -201,16 +205,18 @@ export const Enable2FA = () => {
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Password</FormLabel>
|
||||
<FormLabel>
|
||||
{t("settings.2fa.password")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Enter your password"
|
||||
placeholder={t("settings.2fa.enterPasswordPlaceholder")}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Enter your password to enable 2FA
|
||||
{t("settings.2fa.enterPasswordDescription")}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -221,7 +227,7 @@ export const Enable2FA = () => {
|
||||
className="w-full"
|
||||
isLoading={isPasswordLoading}
|
||||
>
|
||||
Continue
|
||||
{t("settings.2fa.continue")}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
@ -238,16 +244,16 @@ export const Enable2FA = () => {
|
||||
<div className="flex flex-col items-center gap-4 p-6 border rounded-lg">
|
||||
<QrCode className="size-5 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">
|
||||
Scan this QR code with your authenticator app
|
||||
{t("settings.2fa.scanQrCode")}
|
||||
</span>
|
||||
<img
|
||||
src={data.qrCodeUrl}
|
||||
alt="2FA QR Code"
|
||||
alt={t("settings.2fa.qrCodeAlt")}
|
||||
className="rounded-lg w-48 h-48"
|
||||
/>
|
||||
<div className="flex flex-col gap-2 text-center">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Can't scan the QR code?
|
||||
{t("settings.2fa.cantScanQrCode")}
|
||||
</span>
|
||||
<span className="text-xs font-mono bg-muted p-2 rounded">
|
||||
{data.secret}
|
||||
@ -257,7 +263,9 @@ export const Enable2FA = () => {
|
||||
|
||||
{backupCodes && backupCodes.length > 0 && (
|
||||
<div className="w-full space-y-3 border rounded-lg p-4">
|
||||
<h4 className="font-medium">Backup Codes</h4>
|
||||
<h4 className="font-medium">
|
||||
{t("settings.2fa.backupCodes")}
|
||||
</h4>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{backupCodes.map((code, index) => (
|
||||
<code
|
||||
@ -269,9 +277,7 @@ export const Enable2FA = () => {
|
||||
))}
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Save these backup codes in a secure place. You can use
|
||||
them to access your account if you lose access to your
|
||||
authenticator device.
|
||||
{t("settings.2fa.saveBackupCodes")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
@ -288,7 +294,9 @@ export const Enable2FA = () => {
|
||||
name="pin"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-col justify-center items-center">
|
||||
<FormLabel>Verification Code</FormLabel>
|
||||
<FormLabel>
|
||||
{t("settings.2fa.verificationCode")}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<InputOTP maxLength={6} {...field}>
|
||||
<InputOTPGroup>
|
||||
@ -302,7 +310,7 @@ export const Enable2FA = () => {
|
||||
</InputOTP>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Enter the 6-digit code from your authenticator app
|
||||
{t("settings.2fa.enterVerificationCode")}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -314,7 +322,7 @@ export const Enable2FA = () => {
|
||||
className="w-full"
|
||||
isLoading={isPasswordLoading}
|
||||
>
|
||||
Enable 2FA
|
||||
{t("settings.2fa.enable2fa")}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
@ -43,6 +43,30 @@
|
||||
"settings.profile.password": "Password",
|
||||
"settings.profile.avatar": "Avatar",
|
||||
|
||||
"settings.2fa.enable2fa": "Enable 2FA",
|
||||
"settings.2fa.title": "2FA Setup",
|
||||
"settings.2fa.enterPassword": "Enter your password to begin 2FA setup",
|
||||
"settings.2fa.scanQrCodeAndVerify": "Scan the QR code and verify with your authenticator app",
|
||||
"settings.2fa.password": "Password",
|
||||
"settings.2fa.enterPasswordPlaceholder": "Enter your password",
|
||||
"settings.2fa.enterPasswordDescription": "Enter your password to enable 2FA",
|
||||
"settings.2fa.continue": "Continue",
|
||||
"settings.2fa.scanQrCode": "Scan this QR code with your authenticator app",
|
||||
"settings.2fa.qrCodeAlt": "2FA QR Code",
|
||||
"settings.2fa.cantScanQrCode": "Can't scan the QR code?",
|
||||
"settings.2fa.backupCodes": "Backup Codes",
|
||||
"settings.2fa.saveBackupCodes": "Save these backup codes in a secure place. You can use them to access your account if you lose access to your authenticator device.",
|
||||
"settings.2fa.verificationCode": "Verification Code",
|
||||
"settings.2fa.enterVerificationCode": "Enter the 6-digit code from your authenticator app",
|
||||
"settings.2fa.errorSettingUp": "Error setting up 2FA",
|
||||
"settings.2fa.errorVerifyingPassword": "Error verifying password",
|
||||
"settings.2fa.invalidCode": "Invalid code. Please try again.",
|
||||
"settings.2fa.invalidVerificationCode": "Invalid verification code",
|
||||
"settings.2fa.success": "2FA configured successfully",
|
||||
"settings.2fa.connectionError": "Connection error. Please check your internet connection.",
|
||||
"settings.2fa.errorVerifyingCode": "Error verifying code",
|
||||
"settings.2fa.errorVerifying2faCode": "Error verifying 2FA code",
|
||||
|
||||
"settings.appearance.title": "Appearance",
|
||||
"settings.appearance.description": "Customize the theme of your dashboard.",
|
||||
"settings.appearance.theme": "Theme",
|
||||
|
@ -43,6 +43,30 @@
|
||||
"settings.profile.password": "密码",
|
||||
"settings.profile.avatar": "头像",
|
||||
|
||||
"settings.2fa.enable2fa": "启用 2FA",
|
||||
"settings.2fa.title": "2FA 设置",
|
||||
"settings.2fa.enterPassword": "输入您的密码以开始 2FA 设置",
|
||||
"settings.2fa.scanQrCodeAndVerify": "扫描二维码并使用您的身份验证器应用程序进行验证",
|
||||
"settings.2fa.password": "密码",
|
||||
"settings.2fa.enterPasswordPlaceholder": "输入您的密码",
|
||||
"settings.2fa.enterPasswordDescription": "输入您的密码以启用 2FA",
|
||||
"settings.2fa.continue": "继续",
|
||||
"settings.2fa.scanQrCode": "使用您的身份验证器应用程序扫描此二维码",
|
||||
"settings.2fa.qrCodeAlt": "2FA 二维码",
|
||||
"settings.2fa.cantScanQrCode": "无法扫描二维码?",
|
||||
"settings.2fa.backupCodes": "备份代码",
|
||||
"settings.2fa.saveBackupCodes": "将这些备份代码保存在安全的地方。如果您丢失了身份验证设备,可以使用它们访问您的帐户。",
|
||||
"settings.2fa.verificationCode": "验证码",
|
||||
"settings.2fa.enterVerificationCode": "输入您的身份验证器应用程序中的 6 位数代码",
|
||||
"settings.2fa.errorSettingUp": "设置 2FA 时出错",
|
||||
"settings.2fa.errorVerifyingPassword": "验证密码时出错",
|
||||
"settings.2fa.invalidCode": "无效的代码。请再试一次。",
|
||||
"settings.2fa.invalidVerificationCode": "无效的验证码",
|
||||
"settings.2fa.success": "2FA 配置成功",
|
||||
"settings.2fa.connectionError": "连接错误。请检查您的互联网连接。",
|
||||
"settings.2fa.errorVerifyingCode": "验证代码时出错",
|
||||
"settings.2fa.errorVerifying2faCode": "验证 2FA 代码时出错",
|
||||
|
||||
"settings.appearance.title": "外观",
|
||||
"settings.appearance.description": "自定义面板主题",
|
||||
"settings.appearance.theme": "主题",
|
||||
|
Loading…
Reference in New Issue
Block a user