feat: refine i18n resources for login-related page (#6726)

#### What type of PR is this?

/area core
/kind improvement
/milestone 2.20.x

#### What this PR does / why we need it:

完善新登录相关页面的多语言资源文件。

#### Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/6721

#### Does this PR introduce a user-facing change?

```release-note
None 
```
pull/6730/head^2
Ryan Wang 2024-09-29 16:15:46 +08:00 committed by GitHub
parent 2c849d8361
commit 1947a544f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 293 additions and 162 deletions

View File

@ -96,14 +96,14 @@ function sendVerificationCode(button, sendRequest) {
sendRequest() sendRequest()
.then(() => { .then(() => {
startCountdown(); startCountdown();
Toast.success("发送成功"); Toast.success(i18nResources.sendVerificationCodeSuccess);
}) })
.catch((e) => { .catch((e) => {
button.disabled = false; button.disabled = false;
if (e instanceof Error) { if (e instanceof Error) {
Toast.error(e.message); Toast.error(e.message);
} else { } else {
Toast.error("发送失败,请稍后再试"); Toast.error(i18nResources.sendVerificationCodeFailed);
} }
}); });
}); });
@ -151,4 +151,3 @@ document.addEventListener("DOMContentLoaded", () => {
} }
}); });
}); });

View File

@ -0,0 +1,4 @@
title=Autenticación en Dos Pasos
messages.invalidError=Código de verificación incorrecto
form.code.label=Código de Verificación
form.submit=Verificar

View File

@ -0,0 +1,4 @@
title=兩步驗證
messages.invalidError=錯誤的驗證碼
form.code.label=驗證碼
form.submit=驗證

View File

@ -1,13 +1,14 @@
<th:block th:fragment="basicStaticResources"> <th:block th:fragment="basicStaticResources">
<script th:inline="javascript">
const resources = {
title: `[(#{title})]`,
};
</script>
<link rel="stylesheet" href="/webjars/normalize.css/8.0.1/normalize.css" /> <link rel="stylesheet" href="/webjars/normalize.css/8.0.1/normalize.css" />
<link rel="stylesheet" th:href="|/styles/main.css?v=${site.version}|" /> <link rel="stylesheet" th:href="|/styles/main.css?v=${site.version}|" />
<script th:inline="javascript">
const i18nResources = {
sendVerificationCodeSuccess: `[(#{js.sendVerificationCode.success})]`,
sendVerificationCodeFailed: `[(#{js.sendVerificationCode.failed})]`,
};
</script>
<script src="/js/main.js"></script> <script src="/js/main.js"></script>
</th:block> </th:block>
@ -67,7 +68,10 @@
const selectedLanguage = document.getElementById("language-select").value; const selectedLanguage = document.getElementById("language-select").value;
const currentURL = new URL(window.location.href); const currentURL = new URL(window.location.href);
currentURL.searchParams.set("language", selectedLanguage); currentURL.searchParams.set("language", selectedLanguage);
window.location.href = currentURL.toString();
history.replaceState(null, "", currentURL.toString());
window.location.reload();
} }
</script> </script>
</div> </div>

View File

@ -1 +1,3 @@
socialLogin.label=社交登录 socialLogin.label=社交登录
js.sendVerificationCode.success=发送成功
js.sendVerificationCode.failed=发送失败,请稍后再试

View File

@ -1 +1,3 @@
socialLogin.label=Social Login socialLogin.label=Social Login
js.sendVerificationCode.success=Sent Successfully
js.sendVerificationCode.failed=Sending Failed, Please Try Again Later

View File

@ -0,0 +1,3 @@
socialLogin.label=Inicio de Sesión Social
js.sendVerificationCode.success=Enviado con éxito
js.sendVerificationCode.failed=Error al enviar, por favor intente nuevamente más tarde

View File

@ -0,0 +1,3 @@
socialLogin.label=社交登入
js.sendVerificationCode.success=發送成功
js.sendVerificationCode.failed=發送失敗,請稍後再試

View File

@ -1,6 +1,6 @@
messages.loginError=Invalid credentials. messages.loginError=Invalid credentials.
messages.logoutSuccess=Logout successfully. messages.logoutSuccess=Logout successfully.
messages.signupSuccess=Congratulations! Sign up successfully, please sign in now. messages.signupSuccess=Congratulations! Sign up successfully, please login now.
error.invalid-credential=Invalid credentials. error.invalid-credential=Invalid credentials.
error.rate-limit-exceeded=Too many requests, please try again later. error.rate-limit-exceeded=Too many requests, please try again later.

View File

@ -0,0 +1,13 @@
messages.loginError=Credenciales inválidas.
messages.logoutSuccess=Cierre de sesión exitoso.
messages.signupSuccess=¡Felicidades! Registro exitoso, por favor inicie sesión de inmediato.
error.invalid-credential=Credenciales inválidas.
error.rate-limit-exceeded=Demasiadas solicitudes, por favor intente nuevamente más tarde.
form.rememberMe.label=Mantener sesión iniciada
form.submit=Iniciar sesión
otherLogin.label=Otras formas de inicio de sesión
signup.description=¿No tienes una cuenta?
signup.link=Regístrate ahora
returnToSite=Volver al sitio

View File

@ -0,0 +1,13 @@
messages.loginError=無效的憑證。
messages.logoutSuccess=登出成功。
messages.signupSuccess=恭喜!註冊成功,請立即登入。
error.invalid-credential=無效的憑證。
error.rate-limit-exceeded=請求過於頻繁,請稍後再試。
form.rememberMe.label=保持登入會話
form.submit=登入
otherLogin.label=其他登入方式
signup.description=沒有帳號?
signup.link=立即註冊
returnToSite=返回網站

View File

@ -0,0 +1 @@
title=Iniciar Sesión

View File

@ -0,0 +1,3 @@
form.username.label=Nombre de Usuario
form.password.label=Contraseña
form.password.forgot=¿Olvidaste tu contraseña?

View File

@ -0,0 +1,3 @@
form.username.label=使用者名稱
form.password.label=密碼
form.password.forgot=忘記密碼?

View File

@ -0,0 +1 @@
title=登入

View File

@ -0,0 +1,3 @@
title=Cerrar Sesión
form.title=¿Estás seguro de que deseas cerrar sesión?
form.submit=Cerrar Sesión

View File

@ -0,0 +1,3 @@
title=退出登入
form.title=確定要退出登入嗎?
form.submit=退出登入

View File

@ -34,6 +34,8 @@
</div> </div>
</form> </form>
</div> </div>
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
</div> </div>
</th:block> </th:block>
</html> </html>

View File

@ -0,0 +1,5 @@
title=Cambiar Contraseña para {0}
form.password.label=Contraseña
form.confirmPassword.label=Confirmar Contraseña
form.password.tips=La contraseña debe tener al menos 8 caracteres e incluir al menos una letra mayúscula, una letra minúscula, un número y un carácter especial.
form.submit=Cambiar Contraseña

View File

@ -0,0 +1,5 @@
title=為 {0} 修改密碼
form.password.label=密碼
form.confirmPassword.label=確認密碼
form.password.tips=密碼必須至少包含 8 個字元,並且至少包含一個大寫字母、一個小寫字母、一個數字和一個特殊字元。
form.submit=修改密碼

View File

@ -31,6 +31,8 @@
</div> </div>
</form> </form>
</div> </div>
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
</div> </div>
</th:block> </th:block>
</html> </html>

View File

@ -0,0 +1,6 @@
title=Restablecer Contraseña
form.email.label=Correo Electrónico
form.submit=Enviar
sent.form.submit=Volver a la Página de Inicio de Sesión
sent.form.message=Revisa tu correo electrónico para ver el enlace de restablecimiento de contraseña. Si no aparece en unos minutos, revisa tu carpeta de spam.
sent.title=Correo de Restablecimiento de Contraseña Enviado

View File

@ -0,0 +1,6 @@
title=重置密碼
form.email.label=電子郵件
form.submit=提交
sent.form.submit=返回到登入頁面
sent.form.message=檢查您的電子郵件中是否有重置密碼的連結。如果幾分鐘內沒有出現,請檢查您的垃圾郵件資料夾。
sent.title=已發送重置密碼的郵件

View File

@ -1,36 +1,42 @@
<!doctype html> <!doctype html>
<html <html
xmlns:th="https://www.thymeleaf.org" xmlns:th="https://www.thymeleaf.org"
th:replace="~{gateway_modules/layout :: layout(title = |#{title} - ${site.title}|, head = ~{::head}, body = ~{::body})}" th:replace="~{gateway_modules/layout :: layout(title = |#{title} - ${site.title}|, head = ~{::head}, body = ~{::body})}"
> >
<th:block th:fragment="head"> <th:block th:fragment="head">
<style> <style>
.signup-page-wrapper { .signup-page-wrapper {
max-width: 35em; max-width: 35em;
} }
</style> </style>
</th:block> </th:block>
<th:block th:fragment="body"> <th:block th:fragment="body">
<div class="gateway-wrapper signup-page-wrapper"> <div class="gateway-wrapper signup-page-wrapper">
<div th:replace="~{gateway_modules/common_fragments::haloLogo}"></div> <div th:replace="~{gateway_modules/common_fragments::haloLogo}"></div>
<div class="halo-form-wrapper"> <div class="halo-form-wrapper">
<h1 class="form-title" th:text="#{title}"></h1> <h1 class="form-title" th:text="#{title}"></h1>
<p class="alert alert=erro" role="alert" th:if="${error == 'invalid-email-code'}"> <p class="alert alert=erro" role="alert" th:if="${error == 'invalid-email-code'}">
<span th:text="#{error.invalid-email-code}">Invalid email code</span> <span th:text="#{error.invalid-email-code}">Invalid email code</span>
</p> </p>
<p class="alert alert=erro" role="alert" th:if="${error == 'rate-limit-exceeded'}"> <p class="alert alert=erro" role="alert" th:if="${error == 'rate-limit-exceeded'}">
<span th:text="#{error.rate-limit-exceeded}">Rate limit exceeded</span> <span th:text="#{error.rate-limit-exceeded}">Rate limit exceeded</span>
</p> </p>
<p class="alert alert=erro" role="alert" th:if="${error == 'duplicate-name'}"> <p class="alert alert=erro" role="alert" th:if="${error == 'duplicate-name'}">
<span th:text="#{error.duplicate-name}">Duplicate name</span> <span th:text="#{error.duplicate-name}">Duplicate name</span>
</p> </p>
<form class="halo-form" name="signup-form" id="signup-form" th:action="@{/signup}" th:object="${form}" <form
method="post"> class="halo-form"
<div class="form-item-group"> name="signup-form"
<div class="form-item"> id="signup-form"
<label for="username" th:text="#{form.username.label}"></label> th:action="@{/signup}"
<div class="form-input"> th:object="${form}"
<input method="post"
>
<div class="form-item-group">
<div class="form-item">
<label for="username" th:text="#{form.username.label}"></label>
<div class="form-input">
<input
type="text" type="text"
id="username" id="username"
name="username" name="username"
@ -41,18 +47,19 @@
autofocus autofocus
required required
th:field="*{username}" th:field="*{username}"
/> />
</div>
<p
class="alert alert-error"
th:if="${#fields.hasErrors('username')}"
th:errors="*{username}"
></p>
</div> </div>
<p class="alert alert-error"
th:if="${#fields.hasErrors('username')}"
th:errors="*{username}">
</p>
</div>
<div class="form-item"> <div class="form-item">
<label for="displayName" th:text="#{form.displayName.label}"></label> <label for="displayName" th:text="#{form.displayName.label}"></label>
<div class="form-input"> <div class="form-input">
<input <input
type="text" type="text"
id="displayName" id="displayName"
name="displayName" name="displayName"
@ -62,20 +69,21 @@
autocapitalize="off" autocapitalize="off"
required required
th:field="*{displayName}" th:field="*{displayName}"
/> />
</div>
<p
class="alert alert-error"
th:if="${#fields.hasErrors('displayName')}"
th:errors="*{displayName}"
></p>
</div> </div>
<p class="alert alert-error"
th:if="${#fields.hasErrors('displayName')}"
th:errors="*{displayName}">
</p>
</div> </div>
</div>
<div class="form-item-group"> <div class="form-item-group">
<div class="form-item"> <div class="form-item">
<label for="email" th:text="#{form.email.label}"></label> <label for="email" th:text="#{form.email.label}"></label>
<div class="form-input"> <div class="form-input">
<input <input
type="email" type="email"
id="email" id="email"
name="email" name="email"
@ -85,118 +93,120 @@
autocapitalize="off" autocapitalize="off"
required required
th:field="*{email}" th:field="*{email}"
/> />
</div>
<p class="alert alert-error" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></p>
</div> </div>
<p class="alert alert-error"
th:if="${#fields.hasErrors('email')}"
th:errors="*{email}">
</p>
</div>
<div class="form-item" th:if="${globalInfo.mustVerifyEmailOnRegistration}"> <div class="form-item" th:if="${globalInfo.mustVerifyEmailOnRegistration}">
<label for="emailCode" th:text="#{form.emailCode.label}"></label> <label for="emailCode" th:text="#{form.emailCode.label}"></label>
<div class="form-input-group"> <div class="form-input-group">
<div class="form-input"> <div class="form-input">
<input <input
type="text" type="text"
inputmode="numeric" inputmode="numeric"
pattern="\d*" pattern="\d*"
id="emailCode" id="emailCode"
name="emailCode" name="emailCode"
required required
/> />
</div> </div>
<button <button
id="emailCodeSendButton" id="emailCodeSendButton"
type="button" type="button"
th:text="#{form.emailCode.sendButton}" th:text="#{form.emailCode.sendButton}"
></button> ></button>
</div>
<p
class="alert alert-error"
th:if="${#fields.hasErrors('emailCode')}"
th:errors="*{emailCode}"
></p>
</div> </div>
<p class="alert alert-error"
th:if="${#fields.hasErrors('emailCode')}"
th:errors="*{emailCode}">
</p>
</div> </div>
</div>
<div class="form-item"> <div class="form-item">
<label for="password" th:text="#{form.password.label}"></label> <label for="password" th:text="#{form.password.label}"></label>
<th:block <th:block
th:replace="~{gateway_modules/input_fragments :: password(id = 'password', name = 'password', required = 'true', minlength = 6, enableToggle = true)}" th:replace="~{gateway_modules/input_fragments :: password(id = 'password', name = 'password', required = 'true', minlength = 6, enableToggle = true)}"
></th:block> ></th:block>
<p class="alert alert-error" <p
th:if="${#fields.hasErrors('password')}" class="alert alert-error"
th:errors="*{password}"> th:if="${#fields.hasErrors('password')}"
</p> th:errors="*{password}"
</div> ></p>
</div>
<div class="form-item"> <div class="form-item">
<label for="confirmPassword" th:text="#{form.confirmPassword.label}"></label> <label for="confirmPassword" th:text="#{form.confirmPassword.label}"></label>
<th:block <th:block
th:replace="~{gateway_modules/input_fragments :: password(id = 'confirmPassword', name = null, required = 'true', minlength = 6, enableToggle = true)}" th:replace="~{gateway_modules/input_fragments :: password(id = 'confirmPassword', name = null, required = 'true', minlength = 6, enableToggle = true)}"
></th:block> ></th:block>
<p class="alert alert-error" <!-- <p -->
th:if="${#fields.hasErrors('confirmPassword')}" <!-- class="alert alert-error" -->
th:errors="*{confirmPassword}"> <!-- th:if="${#fields.hasErrors('confirmPassword')}" -->
</p> <!-- th:errors="*{confirmPassword}" -->
</div> <!-- ></p> -->
</div>
<div class="form-item"> <div class="form-item">
<button type="submit" th:text="#{form.submit}"></button> <button type="submit" th:text="#{form.submit}"></button>
</div> </div>
</form> </form>
<div th:replace="~{gateway_modules/common_fragments::socialAuthProviders}"></div> <div th:replace="~{gateway_modules/common_fragments::socialAuthProviders}"></div>
</div>
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
</div> </div>
</div> <script th:inline="javascript">
<script th:inline="javascript"> document.addEventListener("DOMContentLoaded", function () {
document.addEventListener("DOMContentLoaded", function () { function sendRequest() {
function sendRequest() { return new Promise((resolve, reject) => {
return new Promise((resolve, reject) => { const email = document.getElementById("email").value;
const email = document.getElementById("email").value;
if (!email) { if (!email) {
throw new Error("请先输入邮箱地址"); throw new Error(/*[[#{form.emailCode.send.emptyValidation}]]*/);
} }
fetch("/signup/send-email-code", { fetch("/signup/send-email-code", {
method: "POST", method: "POST",
body: JSON.stringify({ email: email }), body: JSON.stringify({ email: email }),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
[[${_csrf.headerName}]]: [[${_csrf.token}]], [[${_csrf.headerName}]]: [[${_csrf.token}]],
}, },
})
.then((response) => {
if (response.ok) {
resolve(response);
}
reject(response);
}) })
.catch((e) => { .then((response) => {
reject(e); if (response.ok) {
}); resolve(response);
}); }
} reject(response);
})
const emailCodeSendButton = document.getElementById("emailCodeSendButton"); .catch((e) => {
sendVerificationCode(emailCodeSendButton, sendRequest); reject(e);
});
var password = document.getElementById("password"), });
confirm_password = document.getElementById("confirmPassword");
function validatePassword() {
if (password.value != confirm_password.value) {
confirm_password.setCustomValidity("Passwords Don't Match");
} else {
confirm_password.setCustomValidity("");
} }
}
password.onchange = validatePassword; const emailCodeSendButton = document.getElementById("emailCodeSendButton");
confirm_password.onkeyup = validatePassword; sendVerificationCode(emailCodeSendButton, sendRequest);
});
</script> var password = document.getElementById("password"),
</th:block> confirm_password = document.getElementById("confirmPassword");
function validatePassword() {
if (password.value != confirm_password.value) {
confirm_password.setCustomValidity("Passwords Don't Match");
} else {
confirm_password.setCustomValidity("");
}
}
password.onchange = validatePassword;
confirm_password.onkeyup = validatePassword;
});
</script>
</th:block>
</html> </html>

View File

@ -4,6 +4,7 @@ form.displayName.label=名称
form.email.label=电子邮箱 form.email.label=电子邮箱
form.emailCode.label=邮箱验证码 form.emailCode.label=邮箱验证码
form.emailCode.sendButton=发送 form.emailCode.sendButton=发送
form.emailCode.send.emptyValidation=请先输入邮箱地址
form.password.label=密码 form.password.label=密码
form.confirmPassword.label=确认密码 form.confirmPassword.label=确认密码
form.submit=注册 form.submit=注册

View File

@ -1,9 +1,14 @@
title=Sign up title=Sign Up
form.username.label=Username form.username.label=Username
form.displayName.label=Display name form.displayName.label=Display Name
form.email.label=Email form.email.label=Email
form.emailCode.label=Email Code form.emailCode.label=Email Verification Code
form.emailCode.sendButton=Send form.emailCode.sendButton=Send
form.emailCode.send.emptyValidation=Please enter your email address first
form.password.label=Password form.password.label=Password
form.confirmPassword.label=Confirm password form.confirmPassword.label=Confirm Password
form.submit=Sign up form.submit=Sign Up
error.invalid-email-code=Invalid Email Verification Code
error.duplicate-name=Username is already taken
error.rate-limit-exceeded=Too many requests, please try again later

View File

@ -0,0 +1,14 @@
title=Registrarse
form.username.label=Nombre de Usuario
form.displayName.label=Nombre
form.email.label=Correo Electrónico
form.emailCode.label=Código de Verificación
form.emailCode.sendButton=Enviar
form.emailCode.send.emptyValidation=Por favor, introduce tu dirección de correo electrónico primero
form.password.label=Contraseña
form.confirmPassword.label=Confirmar Contraseña
form.submit=Registrarse
error.invalid-email-code=Código de verificación del correo inválido
error.duplicate-name=El nombre de usuario ya está registrado
error.rate-limit-exceeded=Demasiadas solicitudes, por favor intente nuevamente más tarde

View File

@ -0,0 +1,14 @@
title=註冊
form.username.label=使用者名稱
form.displayName.label=名稱
form.email.label=電子郵件
form.emailCode.label=郵箱驗證碼
form.emailCode.sendButton=發送
form.emailCode.send.emptyValidation=請先輸入電子郵件地址
form.password.label=密碼
form.confirmPassword.label=確認密碼
form.submit=註冊
error.invalid-email-code=無效的郵箱驗證碼
error.duplicate-name=使用者名稱已經被註冊
error.rate-limit-exceeded=請求過於頻繁,請稍後再試