mirror of https://github.com/halo-dev/halo
refactor: update login-related page templates structure (#6813)
#### What type of PR is this? /area core /kind improvement /milestone 2.20.x #### What this PR does / why we need it: 重构登录、注册相关的模板结构,主要目的是为了解耦,修改页面时仅修改相关的模板和语言文件。 重构之后主题的引用方式如下: login.html ```html <div th:replace="~{gateway_fragments/login::form}"></div> ``` #### Special notes for your reviewer: 需要测试各个页面是否功能正常 #### Does this PR introduce a user-facing change? ```release-note None ```pull/6808/head^2
parent
01a781c54a
commit
2b3badc8e1
|
@ -1,14 +1,14 @@
|
||||||
<!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 = null, body = ~{::body})}"
|
th:replace="~{gateway_fragments/layout :: layout(title = |#{title} - ${site.title}|, head = null, body = ~{::body})}"
|
||||||
>
|
>
|
||||||
<th:block th:fragment="body">
|
<th:block th:fragment="body">
|
||||||
<div class="gateway-wrapper">
|
<div class="gateway-wrapper">
|
||||||
<div th:replace="~{gateway_modules/common_fragments::haloLogo}"></div>
|
<div th:replace="~{gateway_fragments/common::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>
|
||||||
<form th:replace="~{gateway_modules/form_fragments::totp}"></form>
|
<form th:replace="~{gateway_fragments/totp::form}"></form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<th:block th:fragment="basicStaticResources">
|
<th:block th:fragment="basicStaticResources">
|
||||||
<th:block th:replace="~{gateway_modules/common_fragments::basicStyleResources}"></th:block>
|
<th:block th:replace="~{gateway_fragments/common::basicStyleResources}"></th:block>
|
||||||
<th:block th:replace="~{gateway_modules/common_fragments::basicScriptResources}"></th:block>
|
<th:block th:replace="~{gateway_fragments/common::basicScriptResources}"></th:block>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|
||||||
<th:block th:fragment="basicScriptResources">
|
<th:block th:fragment="basicScriptResources">
|
|
@ -13,7 +13,7 @@
|
||||||
<link rel="preload" href="/images/wordmark.svg" as="image" type="image/svg+xml" />
|
<link rel="preload" href="/images/wordmark.svg" as="image" type="image/svg+xml" />
|
||||||
<link rel="preload" href="/images/logo.png" as="image" type="image/png" />
|
<link rel="preload" href="/images/logo.png" as="image" type="image/png" />
|
||||||
|
|
||||||
<th:block th:replace="~{gateway_modules/common_fragments::basicStaticResources}"></th:block>
|
<th:block th:replace="~{gateway_fragments/common::basicStaticResources}"></th:block>
|
||||||
|
|
||||||
<th:block th:if="${head != null}">
|
<th:block th:if="${head != null}">
|
||||||
<th:block th:replace="${head}" />
|
<th:block th:replace="${head}" />
|
|
@ -0,0 +1,57 @@
|
||||||
|
<form
|
||||||
|
th:fragment="form"
|
||||||
|
class="halo-form"
|
||||||
|
name="login-form"
|
||||||
|
id="login-form"
|
||||||
|
th:action="${authProvider.spec.authenticationUrl}"
|
||||||
|
th:method="${authProvider.spec.method}"
|
||||||
|
>
|
||||||
|
<div class="alert alert-error" role="alert" th:if="${param.error.size() > 0}" th:with="error = ${param.error[0]}">
|
||||||
|
<strong th:if="${error == 'invalid-credential'}">
|
||||||
|
<span th:text="#{form.error.invalidCredential}"></span>
|
||||||
|
</strong>
|
||||||
|
<strong th:if="${error == 'rate-limit-exceeded'}">
|
||||||
|
<span th:text="#{form.error.rateLimitExceeded}"></span>
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div class="alert" role="alert" th:if="${param.logout.size() > 0}">
|
||||||
|
<strong th:text="#{form.messages.logoutSuccess}"></strong>
|
||||||
|
</div>
|
||||||
|
<div class="alert" role="alert" th:if="${param.signup.size() > 0}">
|
||||||
|
<strong th:text="#{form.messages.signupSuccess}"></strong>
|
||||||
|
</div>
|
||||||
|
<div class="alert" role="alert" th:if="${param.oauth2_bind.size() > 0}">
|
||||||
|
<strong th:text="#{form.messages.oauth2Bind}"></strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div th:replace="~{__${fragmentTemplateName}__::form}"></div>
|
||||||
|
|
||||||
|
<div th:if="${authProvider.spec.rememberMeSupport}" class="form-item-compact">
|
||||||
|
<input type="checkbox" id="remember-me" name="remember-me" value="true" />
|
||||||
|
<label for="remember-me" th:text="#{form.rememberMe.label}"></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item">
|
||||||
|
<button type="submit" th:text="#{form.submit}"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div th:remove="tag" th:fragment="formAuthProviders">
|
||||||
|
<th:block th:unless="${#lists.isEmpty(formAuthProviders)}">
|
||||||
|
<div class="divider-wrapper">
|
||||||
|
<hr />
|
||||||
|
<th:block th:text="#{otherLogin.label}"></th:block>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
<ul class="pill-items">
|
||||||
|
<li th:each="provider : ${formAuthProviders}">
|
||||||
|
<a th:href="'/login?method=' + ${provider.metadata.name}">
|
||||||
|
<img th:src="${provider.spec.logo}" />
|
||||||
|
<span
|
||||||
|
th:text="${#messages.msgOrNull('formAuthProviders.' + provider.metadata.name + '.displayName') ?: provider.spec.displayName}"
|
||||||
|
></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</th:block>
|
||||||
|
</div>
|
|
@ -0,0 +1,12 @@
|
||||||
|
form.messages.logoutSuccess=登出成功。
|
||||||
|
form.messages.signupSuccess=恭喜!注册成功,请立即登录。
|
||||||
|
form.messages.oauth2Bind=当前登录未绑定账号,请尝试通过其他方式登录,登录成功后会自动绑定账号。
|
||||||
|
form.error.invalidCredential=无效的凭证。
|
||||||
|
form.error.rateLimitExceeded=请求过于频繁,请稍后再试。
|
||||||
|
form.rememberMe.label=保持登录会话
|
||||||
|
form.submit=登录
|
||||||
|
|
||||||
|
otherLogin.label=其他登录方式
|
||||||
|
|
||||||
|
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
||||||
|
formAuthProviders.local.displayName=账号密码登录
|
|
@ -0,0 +1,12 @@
|
||||||
|
form.messages.logoutSuccess=Logout successfully.
|
||||||
|
form.messages.signupSuccess=Congratulations! Sign up successfully, please login now.
|
||||||
|
form.messages.oauth2Bind=The current login is not bound to an account. Please try to log in through other methods. After successful login, the account will be automatically bound.
|
||||||
|
form.error.invalidCredential=Invalid credentials.
|
||||||
|
form.error.rateLimitExceeded=Too many requests, please try again later.
|
||||||
|
form.rememberMe.label=Remember me
|
||||||
|
form.submit=Login
|
||||||
|
|
||||||
|
otherLogin.label=Other Login
|
||||||
|
|
||||||
|
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
||||||
|
formAuthProviders.local.displayName=Login with credentials
|
|
@ -0,0 +1,12 @@
|
||||||
|
form.messages.logoutSuccess=Cierre de sesión exitoso.
|
||||||
|
form.messages.signupSuccess=¡Felicidades! Registro exitoso, por favor inicie sesión de inmediato.
|
||||||
|
form.messages.oauth2Bind=El inicio de sesión actual no está vinculado a una cuenta. Intente iniciar sesión a través de otros métodos. Después de un inicio de sesión exitoso, la cuenta se vinculará automáticamente.
|
||||||
|
form.error.invalidCredential=Credenciales inválidas.
|
||||||
|
form.error.rateLimitExceeded=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
|
||||||
|
|
||||||
|
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
||||||
|
formAuthProviders.local.displayName=Iniciar sesión con credenciales
|
|
@ -0,0 +1,12 @@
|
||||||
|
form.messages.logoutSuccess=登出成功。
|
||||||
|
form.messages.signupSuccess=恭喜!註冊成功,請立即登入。
|
||||||
|
form.messages.oauth2Bind=當前登入未綁定至帳戶。請嘗試通過其他方法登入。成功登入後,帳戶將自動綁定。
|
||||||
|
form.error.invalidCredential=無效的憑證。
|
||||||
|
form.error.rateLimitExceeded=請求過於頻繁,請稍後再試。
|
||||||
|
form.form.rememberMe.label=保持登入會話
|
||||||
|
form.form.submit=登入
|
||||||
|
|
||||||
|
otherLogin.label=其他登入方式
|
||||||
|
|
||||||
|
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
||||||
|
formAuthProviders.local.displayName=帳號密碼登入
|
|
@ -0,0 +1,5 @@
|
||||||
|
<form th:fragment="form" class="halo-form" id="logout-form" name="logout-form" th:action="@{/logout}" method="post">
|
||||||
|
<div class="form-item">
|
||||||
|
<button type="submit" th:text="#{form.submit}"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -0,0 +1 @@
|
||||||
|
form.submit=退出登录
|
|
@ -0,0 +1 @@
|
||||||
|
form.submit=Logout
|
|
@ -0,0 +1 @@
|
||||||
|
form.submit=Cerrar Sesión
|
|
@ -0,0 +1 @@
|
||||||
|
form.submit=退出登入
|
|
@ -0,0 +1,34 @@
|
||||||
|
<form
|
||||||
|
th:fragment="form"
|
||||||
|
class="halo-form"
|
||||||
|
th:action="@{/password-reset/email/{resetToken}(resetToken=${resetToken})}"
|
||||||
|
method="post"
|
||||||
|
>
|
||||||
|
<div class="alert alert-error" role="alert" th:if="${error}">
|
||||||
|
<strong th:text="${error}"></strong>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="password" th:text="#{form.password.label}">Password</label>
|
||||||
|
<th:block
|
||||||
|
th:replace="~{gateway_fragments/input :: password(id = 'password', name = 'password', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
||||||
|
></th:block>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="confirmPassword" th:text="#{form.confirmPassword.label}">Confirm Password</label>
|
||||||
|
<th:block
|
||||||
|
th:replace="~{gateway_fragments/input :: password(id = 'confirmPassword', name = 'confirmPassword', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
||||||
|
></th:block>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<div class="alert" th:text="#{form.password.tips}"></div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<button type="submit" th:text="#{form.submit}"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script th:inline="javascript">
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
setupPasswordConfirmation("password", "confirmPassword");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</form>
|
|
@ -0,0 +1,4 @@
|
||||||
|
form.password.label=密码
|
||||||
|
form.confirmPassword.label=确认密码
|
||||||
|
form.password.tips=密码必须至少包含 8 个字符,并且至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符。
|
||||||
|
form.submit=修改密码
|
|
@ -0,0 +1,4 @@
|
||||||
|
form.password.label=Password
|
||||||
|
form.confirmPassword.label=Confirm Password
|
||||||
|
form.password.tips=Password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one special character.
|
||||||
|
form.submit=Change password
|
|
@ -0,0 +1,4 @@
|
||||||
|
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
|
|
@ -0,0 +1,4 @@
|
||||||
|
form.password.label=密碼
|
||||||
|
form.confirmPassword.label=確認密碼
|
||||||
|
form.password.tips=密碼必須至少包含 8 個字元,並且至少包含一個大寫字母、一個小寫字母、一個數字和一個特殊字元。
|
||||||
|
form.submit=修改密碼
|
|
@ -0,0 +1,24 @@
|
||||||
|
<th:block th:fragment="form">
|
||||||
|
<form th:if="${sent}" method="get" action="/login" class="halo-form">
|
||||||
|
<div class="form-item">
|
||||||
|
<div class="alert" th:text="#{form.message.success}"></div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<button type="submit" th:text="#{form.sent.submit}"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form th:unless="${sent}" class="halo-form" th:action="@{/password-reset/email}" method="post">
|
||||||
|
<div class="alert alert-error" th:if="${error}">
|
||||||
|
<strong th:text="${error}"></strong>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="email" th:text="#{form.email.label}"></label>
|
||||||
|
<div class="form-input">
|
||||||
|
<input type="email" id="email" name="email" autofocus required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<button type="submit" th:text="#{form.submit}"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</th:block>
|
|
@ -0,0 +1,4 @@
|
||||||
|
form.email.label=电子邮箱
|
||||||
|
form.submit=提交
|
||||||
|
form.sent.submit=返回到登录页面
|
||||||
|
form.message.success=检查您的电子邮件中是否有重置密码的链接。如果几分钟内没有出现,请检查您的垃圾邮件文件夹。
|
|
@ -0,0 +1,4 @@
|
||||||
|
form.email.label=Email
|
||||||
|
form.submit=Submit
|
||||||
|
form.sent.submit=Return to login
|
||||||
|
form.message.success=Check your email for a link to reset your password. If it doesn’t appear within a few minutes, check your spam folder.
|
|
@ -0,0 +1,4 @@
|
||||||
|
form.email.label=Correo Electrónico
|
||||||
|
form.submit=Enviar
|
||||||
|
form.sent.submit=Volver a la Página de Inicio de Sesión
|
||||||
|
form.message.success=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.
|
|
@ -0,0 +1,4 @@
|
||||||
|
form.email.label=電子郵件
|
||||||
|
form.submit=提交
|
||||||
|
form.sent.submit=返回到登入頁面
|
||||||
|
form.message.success=檢查您的電子郵件中是否有重置密碼的連結。如果幾分鐘內沒有出現,請檢查您的垃圾郵件資料夾。
|
|
@ -0,0 +1,156 @@
|
||||||
|
<form
|
||||||
|
th:fragment="form"
|
||||||
|
class="halo-form"
|
||||||
|
name="signup-form"
|
||||||
|
id="signup-form"
|
||||||
|
th:action="@{/signup}"
|
||||||
|
th:object="${form}"
|
||||||
|
method="post"
|
||||||
|
>
|
||||||
|
<div class="alert alert-error" role="alert" th:if="${error == 'invalid-email-code'}">
|
||||||
|
<strong>
|
||||||
|
<span th:text="#{form.error.invalidEmailCode}"></span>
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-error" role="alert" th:if="${error == 'rate-limit-exceeded'}">
|
||||||
|
<strong>
|
||||||
|
<span th:text="#{form.error.rateLimitExceeded}"></span>
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-error" role="alert" th:if="${error == 'duplicate-username'}">
|
||||||
|
<strong>
|
||||||
|
<span th:text="#{form.error.duplicateUsername}"></span>
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
|
<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"
|
||||||
|
id="username"
|
||||||
|
name="username"
|
||||||
|
autocomplete="off"
|
||||||
|
spellcheck="false"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="off"
|
||||||
|
autofocus
|
||||||
|
required
|
||||||
|
th:field="*{username}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="alert alert-error" th:if="${#fields.hasErrors('username')}" th:errors="*{username}"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="displayName" th:text="#{form.displayName.label}"></label>
|
||||||
|
<div class="form-input">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="displayName"
|
||||||
|
name="displayName"
|
||||||
|
autocomplete="off"
|
||||||
|
spellcheck="false"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="off"
|
||||||
|
required
|
||||||
|
th:field="*{displayName}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="alert alert-error" th:if="${#fields.hasErrors('displayName')}" th:errors="*{displayName}"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item-group">
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="email" th:text="#{form.email.label}"></label>
|
||||||
|
<div class="form-input">
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
autocomplete="off"
|
||||||
|
spellcheck="false"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="off"
|
||||||
|
required
|
||||||
|
th:field="*{email}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="alert alert-error" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item" th:if="${globalInfo.mustVerifyEmailOnRegistration}">
|
||||||
|
<label for="emailCode" th:text="#{form.emailCode.label}"></label>
|
||||||
|
<div class="form-input-group">
|
||||||
|
<div class="form-input">
|
||||||
|
<input type="text" inputmode="numeric" pattern="\d*" id="emailCode" name="emailCode" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id="emailCodeSendButton" type="button" th:text="#{form.emailCode.sendButton}"></button>
|
||||||
|
</div>
|
||||||
|
<p class="alert alert-error" th:if="${#fields.hasErrors('emailCode')}" th:errors="*{emailCode}"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="password" th:text="#{form.password.label}"></label>
|
||||||
|
<th:block
|
||||||
|
th:replace="~{gateway_fragments/input :: password(id = 'password', name = 'password', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
||||||
|
></th:block>
|
||||||
|
<p class="alert alert-error" th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="confirmPassword" th:text="#{form.confirmPassword.label}"></label>
|
||||||
|
<th:block
|
||||||
|
th:replace="~{gateway_fragments/input :: password(id = 'confirmPassword', name = 'confirmPassword', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
||||||
|
></th:block>
|
||||||
|
<p class="alert alert-error" th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item">
|
||||||
|
<button type="submit" th:text="#{form.submit}"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script th:inline="javascript">
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
setupPasswordConfirmation("password", "confirmPassword");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script th:if="${globalInfo.mustVerifyEmailOnRegistration}" th:inline="javascript">
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
function sendRequest() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const email = document.getElementById("email").value;
|
||||||
|
|
||||||
|
if (!email) {
|
||||||
|
throw new Error(/*[[#{form.signup.emailCode.send.emptyValidation}]]*/"");
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch("/signup/send-email-code", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({ email: email }),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
[[${_csrf.headerName}]]: [[${_csrf.token}]],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
|
reject(response);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const emailCodeSendButton = document.getElementById("emailCodeSendButton");
|
||||||
|
sendVerificationCode(emailCodeSendButton, sendRequest);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</form>
|
|
@ -0,0 +1,12 @@
|
||||||
|
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=注册
|
||||||
|
form.error.invalidEmailCode=无效的邮箱验证码
|
||||||
|
form.error.duplicateUsername=用户名已经被注册
|
||||||
|
form.error.rateLimitExceeded=请求过于频繁,请稍后再试
|
|
@ -0,0 +1,12 @@
|
||||||
|
form.username.label=Username
|
||||||
|
form.displayName.label=Display Name
|
||||||
|
form.email.label=Email
|
||||||
|
form.emailCode.label=Email Verification Code
|
||||||
|
form.emailCode.sendButton=Send
|
||||||
|
form.emailCode.send.emptyValidation=Please enter your email address first
|
||||||
|
form.password.label=Password
|
||||||
|
form.confirmPassword.label=Confirm Password
|
||||||
|
form.submit=Sign Up
|
||||||
|
form.error.invalidEmailCode=Invalid Email Verification Code
|
||||||
|
form.error.duplicateUsername=Username is already taken
|
||||||
|
form.error.rateLimitExceeded=Too many requests, please try again later
|
|
@ -0,0 +1,12 @@
|
||||||
|
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
|
||||||
|
form.error.invalidEmailCode=Código de verificación del correo inválido
|
||||||
|
form.error.duplicateUsername=El nombre de usuario ya está registrado
|
||||||
|
form.error.rateLimitExceeded=Demasiadas solicitudes, por favor intente nuevamente más tarde
|
|
@ -0,0 +1,12 @@
|
||||||
|
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=註冊
|
||||||
|
form.error.invalidEmailCode=無效的郵箱驗證碼
|
||||||
|
form.error.duplicateUsername=使用者名稱已經被註冊
|
||||||
|
form.error.rateLimitExceeded=請求過於頻繁,請稍後再試
|
|
@ -0,0 +1,30 @@
|
||||||
|
<form
|
||||||
|
th:fragment="form"
|
||||||
|
class="halo-form"
|
||||||
|
th:action="@{/challenges/two-factor/totp}"
|
||||||
|
name="two-factor-form"
|
||||||
|
id="two-factor-form"
|
||||||
|
method="post"
|
||||||
|
>
|
||||||
|
<div class="alert alert-error" role="alert" th:if="${param.error.size() > 0}">
|
||||||
|
<strong th:text="#{form.messages.invalidError}"></strong>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<label for="code" th:text="#{form.code.label}"></label>
|
||||||
|
<div class="form-input">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
inputmode="numeric"
|
||||||
|
id="code"
|
||||||
|
name="code"
|
||||||
|
autocomplete="one-time-code"
|
||||||
|
pattern="\d{6}"
|
||||||
|
autofocus
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<button type="submit" th:text="#{form.submit}"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -0,0 +1,3 @@
|
||||||
|
form.messages.invalidError=错误的验证码
|
||||||
|
form.code.label=验证码
|
||||||
|
form.submit=验证
|
|
@ -0,0 +1,3 @@
|
||||||
|
form.messages.invalidError=Invalid TOTP code
|
||||||
|
form.code.label=TOTP Code
|
||||||
|
form.submit=Verify
|
|
@ -0,0 +1,3 @@
|
||||||
|
form.messages.invalidError=Código de verificación incorrecto
|
||||||
|
form.code.label=Código de Verificación
|
||||||
|
form.submit=Verificar
|
|
@ -0,0 +1,3 @@
|
||||||
|
form.messages.invalidError=錯誤的驗證碼
|
||||||
|
form.code.label=驗證碼
|
||||||
|
form.submit=驗證
|
|
@ -1,291 +0,0 @@
|
||||||
<form
|
|
||||||
th:fragment="login"
|
|
||||||
class="halo-form"
|
|
||||||
name="login-form"
|
|
||||||
id="login-form"
|
|
||||||
th:action="${authProvider.spec.authenticationUrl}"
|
|
||||||
th:method="${authProvider.spec.method}"
|
|
||||||
>
|
|
||||||
<div class="alert alert-error" role="alert" th:if="${param.error.size() > 0}" th:with="error = ${param.error[0]}">
|
|
||||||
<strong th:if="${error == 'invalid-credential'}">
|
|
||||||
<span th:text="#{form.login.error.invalidCredential}"></span>
|
|
||||||
</strong>
|
|
||||||
<strong th:if="${error == 'rate-limit-exceeded'}">
|
|
||||||
<span th:text="#{form.login.error.rateLimitExceeded}"></span>
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div class="alert" role="alert" th:if="${param.logout.size() > 0}">
|
|
||||||
<strong th:text="#{form.login.messages.logoutSuccess}"></strong>
|
|
||||||
</div>
|
|
||||||
<div class="alert" role="alert" th:if="${param.signup.size() > 0}">
|
|
||||||
<strong th:text="#{form.login.messages.signupSuccess}"></strong>
|
|
||||||
</div>
|
|
||||||
<div class="alert" role="alert" th:if="${param.oauth2_bind.size() > 0}">
|
|
||||||
<strong th:text="#{form.login.messages.oauth2Bind}"></strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div th:replace="~{__${fragmentTemplateName}__::form}"></div>
|
|
||||||
|
|
||||||
<div th:if="${authProvider.spec.rememberMeSupport}" class="form-item-compact">
|
|
||||||
<input type="checkbox" id="remember-me" name="remember-me" value="true" />
|
|
||||||
<label for="remember-me" th:text="#{form.login.rememberMe.label}"></label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-item">
|
|
||||||
<button type="submit" th:text="#{form.login.submit}"></button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form
|
|
||||||
th:fragment="signup"
|
|
||||||
class="halo-form"
|
|
||||||
name="signup-form"
|
|
||||||
id="signup-form"
|
|
||||||
th:action="@{/signup}"
|
|
||||||
th:object="${form}"
|
|
||||||
method="post"
|
|
||||||
>
|
|
||||||
<div class="alert alert-error" role="alert" th:if="${error == 'invalid-email-code'}">
|
|
||||||
<strong>
|
|
||||||
<span th:text="#{form.signup.error.invalidEmailCode}"></span>
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div class="alert alert-error" role="alert" th:if="${error == 'rate-limit-exceeded'}">
|
|
||||||
<strong>
|
|
||||||
<span th:text="#{form.signup.error.rateLimitExceeded}"></span>
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div class="alert alert-error" role="alert" th:if="${error == 'duplicate-username'}">
|
|
||||||
<strong>
|
|
||||||
<span th:text="#{form.signup.error.duplicateUsername}"></span>
|
|
||||||
</strong>
|
|
||||||
</div>
|
|
||||||
<div class="form-item-group">
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="username" th:text="#{form.signup.username.label}"></label>
|
|
||||||
<div class="form-input">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="username"
|
|
||||||
name="username"
|
|
||||||
autocomplete="off"
|
|
||||||
spellcheck="false"
|
|
||||||
autocorrect="off"
|
|
||||||
autocapitalize="off"
|
|
||||||
autofocus
|
|
||||||
required
|
|
||||||
th:field="*{username}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p class="alert alert-error" th:if="${#fields.hasErrors('username')}" th:errors="*{username}"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="displayName" th:text="#{form.signup.displayName.label}"></label>
|
|
||||||
<div class="form-input">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="displayName"
|
|
||||||
name="displayName"
|
|
||||||
autocomplete="off"
|
|
||||||
spellcheck="false"
|
|
||||||
autocorrect="off"
|
|
||||||
autocapitalize="off"
|
|
||||||
required
|
|
||||||
th:field="*{displayName}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p class="alert alert-error" th:if="${#fields.hasErrors('displayName')}" th:errors="*{displayName}"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-item-group">
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="email" th:text="#{form.signup.email.label}"></label>
|
|
||||||
<div class="form-input">
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
id="email"
|
|
||||||
name="email"
|
|
||||||
autocomplete="off"
|
|
||||||
spellcheck="false"
|
|
||||||
autocorrect="off"
|
|
||||||
autocapitalize="off"
|
|
||||||
required
|
|
||||||
th:field="*{email}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p class="alert alert-error" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-item" th:if="${globalInfo.mustVerifyEmailOnRegistration}">
|
|
||||||
<label for="emailCode" th:text="#{form.signup.emailCode.label}"></label>
|
|
||||||
<div class="form-input-group">
|
|
||||||
<div class="form-input">
|
|
||||||
<input type="text" inputmode="numeric" pattern="\d*" id="emailCode" name="emailCode" required />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button id="emailCodeSendButton" type="button" th:text="#{form.signup.emailCode.sendButton}"></button>
|
|
||||||
</div>
|
|
||||||
<p class="alert alert-error" th:if="${#fields.hasErrors('emailCode')}" th:errors="*{emailCode}"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="password" th:text="#{form.signup.password.label}"></label>
|
|
||||||
<th:block
|
|
||||||
th:replace="~{gateway_modules/input_fragments :: password(id = 'password', name = 'password', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
|
||||||
></th:block>
|
|
||||||
<p class="alert alert-error" th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="confirmPassword" th:text="#{form.signup.confirmPassword.label}"></label>
|
|
||||||
<th:block
|
|
||||||
th:replace="~{gateway_modules/input_fragments :: password(id = 'confirmPassword', name = 'confirmPassword', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
|
||||||
></th:block>
|
|
||||||
<p class="alert alert-error" th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-item">
|
|
||||||
<button type="submit" th:text="#{form.signup.submit}"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script th:inline="javascript">
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
|
||||||
setupPasswordConfirmation("password", "confirmPassword");
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script th:if="${globalInfo.mustVerifyEmailOnRegistration}" th:inline="javascript">
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
|
||||||
function sendRequest() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const email = document.getElementById("email").value;
|
|
||||||
|
|
||||||
if (!email) {
|
|
||||||
throw new Error(/*[[#{form.signup.emailCode.send.emptyValidation}]]*/"");
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch("/signup/send-email-code", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({ email: email }),
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
[[${_csrf.headerName}]]: [[${_csrf.token}]],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
resolve(response);
|
|
||||||
}
|
|
||||||
reject(response);
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
reject(e);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailCodeSendButton = document.getElementById("emailCodeSendButton");
|
|
||||||
sendVerificationCode(emailCodeSendButton, sendRequest);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form
|
|
||||||
th:fragment="totp"
|
|
||||||
class="halo-form"
|
|
||||||
th:action="@{/challenges/two-factor/totp}"
|
|
||||||
name="two-factor-form"
|
|
||||||
id="two-factor-form"
|
|
||||||
method="post"
|
|
||||||
>
|
|
||||||
<div class="alert alert-error" role="alert" th:if="${param.error.size() > 0}">
|
|
||||||
<strong th:text="#{form.totp.messages.invalidError}"></strong>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="code" th:text="#{form.totp.code.label}"></label>
|
|
||||||
<div class="form-input">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
inputmode="numeric"
|
|
||||||
id="code"
|
|
||||||
name="code"
|
|
||||||
autocomplete="one-time-code"
|
|
||||||
pattern="\d{6}"
|
|
||||||
autofocus
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<button type="submit" th:text="#{form.totp.submit}"></button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form th:fragment="logout" class="halo-form" id="logout-form" name="logout-form" th:action="@{/logout}" method="post">
|
|
||||||
<div class="form-item">
|
|
||||||
<button type="submit" th:text="#{form.logout.submit}"></button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form
|
|
||||||
th:fragment="passwordResetLink"
|
|
||||||
class="halo-form"
|
|
||||||
th:action="@{/password-reset/email/{resetToken}(resetToken=${resetToken})}"
|
|
||||||
method="post"
|
|
||||||
>
|
|
||||||
<div class="alert alert-error" role="alert" th:if="${error}">
|
|
||||||
<strong th:text="${error}"></strong>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="password" th:text="#{form.passwordResetLink.password.label}">Password</label>
|
|
||||||
<th:block
|
|
||||||
th:replace="~{gateway_modules/input_fragments :: password(id = 'password', name = 'password', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
|
||||||
></th:block>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="confirmPassword" th:text="#{form.passwordResetLink.confirmPassword.label}">Confirm Password</label>
|
|
||||||
<th:block
|
|
||||||
th:replace="~{gateway_modules/input_fragments :: password(id = 'confirmPassword', name = 'confirmPassword', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
|
||||||
></th:block>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<div class="alert" th:text="#{form.passwordResetLink.password.tips}"></div>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<button type="submit" th:text="#{form.passwordResetLink.submit}"></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script th:inline="javascript">
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
|
||||||
setupPasswordConfirmation("password", "confirmPassword");
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<th:block th:fragment="passwordReset">
|
|
||||||
<form th:if="${sent}" method="get" action="/login" class="halo-form">
|
|
||||||
<div class="form-item">
|
|
||||||
<div class="alert" th:text="#{form.passwordReset.message.success}"></div>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<button type="submit" th:text="#{form.passwordReset.sent.submit}"></button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<form th:unless="${sent}" class="halo-form" th:action="@{/password-reset/email}" method="post">
|
|
||||||
<div class="alert alert-error" th:if="${error}">
|
|
||||||
<strong th:text="${error}"></strong>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<label for="email" th:text="#{form.passwordReset.email.label}"></label>
|
|
||||||
<div class="form-input">
|
|
||||||
<input type="email" id="email" name="email" autofocus required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-item">
|
|
||||||
<button type="submit" th:text="#{form.passwordReset.submit}"></button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</th:block>
|
|
|
@ -1,36 +0,0 @@
|
||||||
form.login.messages.logoutSuccess=登出成功。
|
|
||||||
form.login.messages.signupSuccess=恭喜!注册成功,请立即登录。
|
|
||||||
form.login.messages.oauth2Bind=当前登录未绑定账号,请尝试通过其他方式登录,登录成功后会自动绑定账号。
|
|
||||||
form.login.error.invalidCredential=无效的凭证。
|
|
||||||
form.login.error.rateLimitExceeded=请求过于频繁,请稍后再试。
|
|
||||||
form.login.rememberMe.label=保持登录会话
|
|
||||||
form.login.submit=登录
|
|
||||||
|
|
||||||
form.signup.username.label=用户名
|
|
||||||
form.signup.displayName.label=名称
|
|
||||||
form.signup.email.label=电子邮箱
|
|
||||||
form.signup.emailCode.label=邮箱验证码
|
|
||||||
form.signup.emailCode.sendButton=发送
|
|
||||||
form.signup.emailCode.send.emptyValidation=请先输入邮箱地址
|
|
||||||
form.signup.password.label=密码
|
|
||||||
form.signup.confirmPassword.label=确认密码
|
|
||||||
form.signup.submit=注册
|
|
||||||
form.signup.error.invalidEmailCode=无效的邮箱验证码
|
|
||||||
form.signup.error.duplicateUsername=用户名已经被注册
|
|
||||||
form.signup.error.rateLimitExceeded=请求过于频繁,请稍后再试
|
|
||||||
|
|
||||||
form.totp.messages.invalidError=错误的验证码
|
|
||||||
form.totp.code.label=验证码
|
|
||||||
form.totp.submit=验证
|
|
||||||
|
|
||||||
form.logout.submit=退出登录
|
|
||||||
|
|
||||||
form.passwordResetLink.password.label=密码
|
|
||||||
form.passwordResetLink.confirmPassword.label=确认密码
|
|
||||||
form.passwordResetLink.password.tips=密码必须至少包含 8 个字符,并且至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符。
|
|
||||||
form.passwordResetLink.submit=修改密码
|
|
||||||
|
|
||||||
form.passwordReset.email.label=电子邮箱
|
|
||||||
form.passwordReset.submit=提交
|
|
||||||
form.passwordReset.sent.submit=返回到登录页面
|
|
||||||
form.passwordReset.message.success=检查您的电子邮件中是否有重置密码的链接。如果几分钟内没有出现,请检查您的垃圾邮件文件夹。
|
|
|
@ -1,36 +0,0 @@
|
||||||
form.login.messages.logoutSuccess=Logout successfully.
|
|
||||||
form.login.messages.signupSuccess=Congratulations! Sign up successfully, please login now.
|
|
||||||
form.login.messages.oauth2Bind=The current login is not bound to an account. Please try to log in through other methods. After successful login, the account will be automatically bound.
|
|
||||||
form.login.error.invalidCredential=Invalid credentials.
|
|
||||||
form.login.error.rateLimitExceeded=Too many requests, please try again later.
|
|
||||||
form.login.rememberMe.label=Remember me
|
|
||||||
form.login.submit=Login
|
|
||||||
|
|
||||||
form.signup.username.label=Username
|
|
||||||
form.signup.displayName.label=Display Name
|
|
||||||
form.signup.email.label=Email
|
|
||||||
form.signup.emailCode.label=Email Verification Code
|
|
||||||
form.signup.emailCode.sendButton=Send
|
|
||||||
form.signup.emailCode.send.emptyValidation=Please enter your email address first
|
|
||||||
form.signup.password.label=Password
|
|
||||||
form.signup.confirmPassword.label=Confirm Password
|
|
||||||
form.signup.submit=Sign Up
|
|
||||||
form.signup.error.invalidEmailCode=Invalid Email Verification Code
|
|
||||||
form.signup.error.duplicateUsername=Username is already taken
|
|
||||||
form.signup.error.rateLimitExceeded=Too many requests, please try again later
|
|
||||||
|
|
||||||
form.totp.messages.invalidError=Invalid TOTP code
|
|
||||||
form.totp.code.label=TOTP Code
|
|
||||||
form.totp.submit=Verify
|
|
||||||
|
|
||||||
form.logout.submit=Logout
|
|
||||||
|
|
||||||
form.passwordResetLink.password.label=Password
|
|
||||||
form.passwordResetLink.confirmPassword.label=Confirm Password
|
|
||||||
form.passwordResetLink.password.tips=Password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one special character.
|
|
||||||
form.passwordResetLink.submit=Change password
|
|
||||||
|
|
||||||
form.passwordReset.email.label=Email
|
|
||||||
form.passwordReset.submit=Submit
|
|
||||||
form.passwordReset.sent.submit=Return to login
|
|
||||||
form.passwordReset.message.success=Check your email for a link to reset your password. If it doesn’t appear within a few minutes, check your spam folder.
|
|
|
@ -1,36 +0,0 @@
|
||||||
form.login.messages.logoutSuccess=Cierre de sesión exitoso.
|
|
||||||
form.login.messages.signupSuccess=¡Felicidades! Registro exitoso, por favor inicie sesión de inmediato.
|
|
||||||
form.login.messages.oauth2Bind=El inicio de sesión actual no está vinculado a una cuenta. Intente iniciar sesión a través de otros métodos. Después de un inicio de sesión exitoso, la cuenta se vinculará automáticamente.
|
|
||||||
form.login.error.invalidCredential=Credenciales inválidas.
|
|
||||||
form.login.error.rateLimitExceeded=Demasiadas solicitudes, por favor intente nuevamente más tarde.
|
|
||||||
form.login.rememberMe.label=Mantener sesión iniciada
|
|
||||||
form.login.submit=Iniciar sesión
|
|
||||||
|
|
||||||
form.signup.username.label=Nombre de Usuario
|
|
||||||
form.signup.displayName.label=Nombre
|
|
||||||
form.signup.email.label=Correo Electrónico
|
|
||||||
form.signup.emailCode.label=Código de Verificación
|
|
||||||
form.signup.emailCode.sendButton=Enviar
|
|
||||||
form.signup.emailCode.send.emptyValidation=Por favor, introduce tu dirección de correo electrónico primero
|
|
||||||
form.signup.password.label=Contraseña
|
|
||||||
form.signup.confirmPassword.label=Confirmar Contraseña
|
|
||||||
form.signup.submit=Registrarse
|
|
||||||
form.signup.error.invalidEmailCode=Código de verificación del correo inválido
|
|
||||||
form.signup.error.duplicateUsername=El nombre de usuario ya está registrado
|
|
||||||
form.signup.error.rateLimitExceeded=Demasiadas solicitudes, por favor intente nuevamente más tarde
|
|
||||||
|
|
||||||
form.totp.messages.invalidError=Código de verificación incorrecto
|
|
||||||
form.totp.code.label=Código de Verificación
|
|
||||||
form.totp.submit=Verificar
|
|
||||||
|
|
||||||
form.logout.submit=Cerrar Sesión
|
|
||||||
|
|
||||||
form.passwordResetLink.password.label=Contraseña
|
|
||||||
form.passwordResetLink.confirmPassword.label=Confirmar Contraseña
|
|
||||||
form.passwordResetLink.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.passwordResetLink.submit=Cambiar Contraseña
|
|
||||||
|
|
||||||
form.passwordReset.email.label=Correo Electrónico
|
|
||||||
form.passwordReset.submit=Enviar
|
|
||||||
form.passwordReset.sent.submit=Volver a la Página de Inicio de Sesión
|
|
||||||
form.passwordReset.message.success=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.
|
|
|
@ -1,36 +0,0 @@
|
||||||
form.login.messages.logoutSuccess=登出成功。
|
|
||||||
form.login.messages.signupSuccess=恭喜!註冊成功,請立即登入。
|
|
||||||
form.login.messages.oauth2Bind=當前登入未綁定至帳戶。請嘗試通過其他方法登入。成功登入後,帳戶將自動綁定。
|
|
||||||
form.login.error.invalidCredential=無效的憑證。
|
|
||||||
form.login.error.rateLimitExceeded=請求過於頻繁,請稍後再試。
|
|
||||||
form.login.form.rememberMe.label=保持登入會話
|
|
||||||
form.login.form.submit=登入
|
|
||||||
|
|
||||||
form.signup.username.label=使用者名稱
|
|
||||||
form.signup.displayName.label=名稱
|
|
||||||
form.signup.email.label=電子郵件
|
|
||||||
form.signup.emailCode.label=郵箱驗證碼
|
|
||||||
form.signup.emailCode.sendButton=發送
|
|
||||||
form.signup.emailCode.send.emptyValidation=請先輸入電子郵件地址
|
|
||||||
form.signup.password.label=密碼
|
|
||||||
form.signup.confirmPassword.label=確認密碼
|
|
||||||
form.signup.submit=註冊
|
|
||||||
form.signup.error.invalidEmailCode=無效的郵箱驗證碼
|
|
||||||
form.signup.error.duplicateUsername=使用者名稱已經被註冊
|
|
||||||
form.signup.error.rateLimitExceeded=請求過於頻繁,請稍後再試
|
|
||||||
|
|
||||||
form.totp.messages.invalidError=錯誤的驗證碼
|
|
||||||
form.totp.code.label=驗證碼
|
|
||||||
form.totp.submit=驗證
|
|
||||||
|
|
||||||
form.logout.submit=退出登入
|
|
||||||
|
|
||||||
form.passwordResetLink.password.label=密碼
|
|
||||||
form.passwordResetLink.confirmPassword.label=確認密碼
|
|
||||||
form.passwordResetLink.password.tips=密碼必須至少包含 8 個字元,並且至少包含一個大寫字母、一個小寫字母、一個數字和一個特殊字元。
|
|
||||||
form.passwordResetLink.submit=修改密碼
|
|
||||||
|
|
||||||
form.passwordReset.email.label=電子郵件
|
|
||||||
form.passwordReset.submit=提交
|
|
||||||
form.passwordReset.sent.submit=返回到登入頁面
|
|
||||||
form.passwordReset.message.success=檢查您的電子郵件中是否有重置密碼的連結。如果幾分鐘內沒有出現,請檢查您的垃圾郵件資料夾。
|
|
|
@ -1,20 +0,0 @@
|
||||||
<!-- Those fragments are only for login template-->
|
|
||||||
<div th:remove="tag" th:fragment="formAuthProviders">
|
|
||||||
<th:block th:unless="${#lists.isEmpty(formAuthProviders)}">
|
|
||||||
<div class="divider-wrapper">
|
|
||||||
<hr />
|
|
||||||
<th:block th:text="#{otherLogin.label}"></th:block>
|
|
||||||
<hr />
|
|
||||||
</div>
|
|
||||||
<ul class="pill-items">
|
|
||||||
<li th:each="provider : ${formAuthProviders}">
|
|
||||||
<a th:href="'/login?method=' + ${provider.metadata.name}">
|
|
||||||
<img th:src="${provider.spec.logo}" />
|
|
||||||
<span
|
|
||||||
th:text="${#messages.msgOrNull('formAuthProviders.' + provider.metadata.name + '.displayName') ?: provider.spec.displayName}"
|
|
||||||
></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</th:block>
|
|
||||||
</div>
|
|
|
@ -1,4 +0,0 @@
|
||||||
otherLogin.label=其他登录方式
|
|
||||||
|
|
||||||
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
|
||||||
formAuthProviders.local.displayName=账号密码登录
|
|
|
@ -1,4 +0,0 @@
|
||||||
otherLogin.label=Other Login
|
|
||||||
|
|
||||||
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
|
||||||
formAuthProviders.local.displayName=Login with credentials
|
|
|
@ -1,4 +0,0 @@
|
||||||
otherLogin.label=Otras formas de inicio de sesión
|
|
||||||
|
|
||||||
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
|
||||||
formAuthProviders.local.displayName=Iniciar sesión con credenciales
|
|
|
@ -1,4 +0,0 @@
|
||||||
otherLogin.label=其他登入方式
|
|
||||||
|
|
||||||
# Rule: `formAuthProviders.${provider.metadata.name}.displayName`
|
|
||||||
formAuthProviders.local.displayName=帳號密碼登入
|
|
|
@ -1,21 +1,21 @@
|
||||||
<!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 = null, body = ~{::body})}"
|
th:replace="~{gateway_fragments/layout :: layout(title = |#{title} - ${site.title}|, head = null, body = ~{::body})}"
|
||||||
>
|
>
|
||||||
<th:block th:fragment="body">
|
<th:block th:fragment="body">
|
||||||
<div class="gateway-wrapper">
|
<div class="gateway-wrapper">
|
||||||
<div th:replace="~{gateway_modules/common_fragments::haloLogo}"></div>
|
<div th:replace="~{gateway_fragments/common::haloLogo}"></div>
|
||||||
|
|
||||||
<div class="halo-form-wrapper">
|
<div class="halo-form-wrapper">
|
||||||
<form th:replace="~{gateway_modules/form_fragments::login}"></form>
|
<div th:replace="~{gateway_fragments/login::form}"></div>
|
||||||
<div th:replace="~{gateway_modules/login_fragments::formAuthProviders}"></div>
|
<div th:replace="~{gateway_fragments/login::formAuthProviders}"></div>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::socialAuthProviders}"></div>
|
<div th:replace="~{gateway_fragments/common::socialAuthProviders}"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:replace="~{gateway_modules/common_fragments::signupNoticeContent}"></div>
|
<div th:replace="~{gateway_fragments/common::signupNoticeContent}"></div>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::returnToSiteContent}"></div>
|
<div th:replace="~{gateway_fragments/common::returnToSiteContent}"></div>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
|
<div th:replace="~{gateway_fragments/common::languageSwitcher}"></div>
|
||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<th:block
|
<th:block
|
||||||
th:replace="~{gateway_modules/input_fragments :: password(id = 'plainPassword', name = null, required = 'true', minlength = null, maxlength = 257, enableToggle = true)}"
|
th:replace="~{gateway_fragments/input :: password(id = 'plainPassword', name = null, required = 'true', minlength = null, maxlength = 257, enableToggle = true)}"
|
||||||
></th:block>
|
></th:block>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,13 +1,13 @@
|
||||||
<!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 = null, body = ~{::body})}"
|
th:replace="~{gateway_fragments/layout:: layout(title = |#{title} - ${site.title}|, head = null, body = ~{::body})}"
|
||||||
>
|
>
|
||||||
<th:block th:fragment="body">
|
<th:block th:fragment="body">
|
||||||
<div class="gateway-wrapper">
|
<div class="gateway-wrapper">
|
||||||
<div class="halo-form-wrapper">
|
<div class="halo-form-wrapper">
|
||||||
<h1 class="form-title" th:text="#{form.title}"></h1>
|
<h1 class="form-title" th:text="#{form.title}"></h1>
|
||||||
<form th:replace="~{gateway_modules/form_fragments::logout}"></form>
|
<form th:replace="~{gateway_fragments/logout::form}"></form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<!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(${username})} - ${site.title}|, head = null, body = ~{::body})}"
|
th:replace="~{gateway_fragments/layout:: layout(title = |#{title(${username})} - ${site.title}|, head = null, body = ~{::body})}"
|
||||||
>
|
>
|
||||||
<th:block th:fragment="body">
|
<th:block th:fragment="body">
|
||||||
<div class="gateway-wrapper">
|
<div class="gateway-wrapper">
|
||||||
<div th:replace="~{gateway_modules/common_fragments::haloLogo}"></div>
|
<div th:replace="~{gateway_fragments/common::haloLogo}"></div>
|
||||||
<div class="halo-form-wrapper">
|
<div class="halo-form-wrapper">
|
||||||
<h1 class="form-title" th:text="#{title(${username})}"></h1>
|
<h1 class="form-title" th:text="#{title(${username})}"></h1>
|
||||||
<form th:replace="~{gateway_modules/form_fragments::passwordResetLink}"></form>
|
<form th:replace="~{gateway_fragments/password_reset_email_reset::form}"></form>
|
||||||
</div>
|
</div>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
|
<div th:replace="~{gateway_fragments/common::languageSwitcher}"></div>
|
||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
<!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 = null, body = ~{::body})}"
|
th:replace="~{gateway_fragments/layout:: layout(title = |#{title} - ${site.title}|, head = null, body = ~{::body})}"
|
||||||
>
|
>
|
||||||
<th:block th:fragment="body">
|
<th:block th:fragment="body">
|
||||||
<div class="gateway-wrapper">
|
<div class="gateway-wrapper">
|
||||||
<div th:replace="~{gateway_modules/common_fragments::haloLogo}"></div>
|
<div th:replace="~{gateway_fragments/common::haloLogo}"></div>
|
||||||
<div class="halo-form-wrapper">
|
<div class="halo-form-wrapper">
|
||||||
<h1 class="form-title" th:text="${sent} ? #{sent.title} : #{title}"></h1>
|
<h1 class="form-title" th:text="${sent} ? #{sent.title} : #{title}"></h1>
|
||||||
<form th:replace="~{gateway_modules/form_fragments::passwordReset}"></form>
|
<form th:replace="~{gateway_fragments/password_reset_email_send::form}"></form>
|
||||||
|
|
||||||
<div th:replace="~{gateway_modules/common_fragments::passwordResetMethods}"></div>
|
<div th:replace="~{gateway_fragments/common::passwordResetMethods}"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
|
<div th:replace="~{gateway_fragments/common::languageSwitcher}"></div>
|
||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!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} - Halo|, head = ~{::head}, body = ~{::body})}"
|
th:replace="~{gateway_fragments/layout :: layout(title = |#{title} - Halo|, head = ~{::head}, body = ~{::body})}"
|
||||||
>
|
>
|
||||||
<th:block th:fragment="head">
|
<th:block th:fragment="head">
|
||||||
<style>
|
<style>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
</th:block>
|
</th:block>
|
||||||
<th:block th:fragment="body">
|
<th:block th:fragment="body">
|
||||||
<div class="gateway-wrapper setup-page-wrapper">
|
<div class="gateway-wrapper setup-page-wrapper">
|
||||||
<div th:replace="~{gateway_modules/common_fragments::haloLogo}"></div>
|
<div th:replace="~{gateway_fragments/common::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>
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
<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 = 5, maxlength = 257, enableToggle = true)}"
|
th:replace="~{gateway_fragments/input :: password(id = 'password', name = 'password', required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
||||||
></th:block>
|
></th:block>
|
||||||
<p
|
<p
|
||||||
class="alert alert-error"
|
class="alert alert-error"
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
<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 = 5, maxlength = 257, enableToggle = true)}"
|
th:replace="~{gateway_fragments/input :: password(id = 'confirmPassword', name = null, required = 'true', minlength = 5, maxlength = 257, enableToggle = true)}"
|
||||||
></th:block>
|
></th:block>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
|
<div th:replace="~{gateway_fragments/common::languageSwitcher}"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script th:inline="javascript">
|
<script th:inline="javascript">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!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_fragments/layout :: layout(title = |#{title} - ${site.title}|, head = ~{::head}, body = ~{::body})}"
|
||||||
>
|
>
|
||||||
<th:block th:fragment="head">
|
<th:block th:fragment="head">
|
||||||
<style>
|
<style>
|
||||||
|
@ -12,15 +12,15 @@
|
||||||
</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_fragments/common::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>
|
||||||
<form th:replace="~{gateway_modules/form_fragments::signup}"></form>
|
<form th:replace="~{gateway_fragments/signup::form}"></form>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::socialAuthProviders}"></div>
|
<div th:replace="~{gateway_fragments/common::socialAuthProviders}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::loginNoticeContent}"></div>
|
<div th:replace="~{gateway_fragments/common::loginNoticeContent}"></div>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::returnToSiteContent}"></div>
|
<div th:replace="~{gateway_fragments/common::returnToSiteContent}"></div>
|
||||||
<div th:replace="~{gateway_modules/common_fragments::languageSwitcher}"></div>
|
<div th:replace="~{gateway_fragments/common::languageSwitcher}"></div>
|
||||||
</div>
|
</div>
|
||||||
</th:block>
|
</th:block>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue