From 7c1525fd21783509bce3bf5c71ff400b0e89f68c Mon Sep 17 00:00:00 2001 From: QianRj <14974713+qianrj@user.noreply.gitee.com> Date: 星期三, 27 十一月 2024 17:25:09 +0800 Subject: [PATCH] refactor: 补充登录页与注册页的国际化内容并添加切换语言按钮 --- src/views/register.vue | 79 ++++++++--- src/lang/zh_CN.ts | 62 ++++++++ src/views/login.vue | 76 +++++++--- src/lang/zh_CN.json | 60 ++++++++ src/lang/en_US.json | 58 ++++++++ src/lang/en_US.ts | 59 ++++++++ 6 files changed, 343 insertions(+), 51 deletions(-) diff --git a/src/lang/en_US.json b/src/lang/en_US.json index 17b472e..f465aa6 100644 --- a/src/lang/en_US.json +++ b/src/lang/en_US.json @@ -4,11 +4,67 @@ "document": "Document" }, "login": { + "selectPlaceholder": "Please select/enter a company name", "username": "Username", "password": "Password", "login": "Login", + "logging": "Logging...", "code": "Verification Code", - "copyright": "" + "rememberPassword": "Remember me", + "switchRegisterPage": "Sign up now", + "rule": { + "tenantId": { + "required": "Please enter your tenant id" + }, + "username": { + "required": "Please enter your account" + }, + "password": { + "required": "Please enter your password" + }, + "code": { + "required": "Please enter a verification code" + } + }, + "social": { + "wechat": "Wechat Login", + "maxkey": "MaxKey Login", + "topiam": "TopIam Login", + "gitee": "Gitee Login", + "github": "Github Login" + } + }, + "register": { + "selectPlaceholder": "Please select/enter a company name", + "username": "Username", + "password": "Password", + "confirmPassword": "Confirm Password", + "register": "Register", + "registering": "Registering...", + "registerSuccess": "Congratulations, your {username} account has been registered!", + "code": "Verification Code", + "switchLoginPage": "Log in with an existing account", + "rule": { + "tenantId": { + "required": "Please enter your tenant id" + }, + "username": { + "required": "Please enter your account", + "length": "The length of the user account must be between {min} and {max}" + }, + "password": { + "required": "Please enter your password", + "length": "The user password must be between {min} and {max} in length", + "pattern": "Can't contain illegal characters: {strings}" + }, + "code": { + "required": "Please enter a verification code" + }, + "confirmPassword": { + "required": "Please enter your password again", + "equalToPassword": "The password entered twice is inconsistent" + } + } }, "navbar": { "full": "Full Screen", diff --git a/src/lang/en_US.ts b/src/lang/en_US.ts index 034ea91..b090d3e 100644 --- a/src/lang/en_US.ts +++ b/src/lang/en_US.ts @@ -6,11 +6,68 @@ }, // 鐧诲綍椤甸潰鍥介檯鍖� login: { + selectPlaceholder: 'Please select/enter a company name', username: 'Username', password: 'Password', login: 'Login', + logging: 'Logging...', code: 'Verification Code', - copyright: '' + rememberPassword: 'Remember me', + switchRegisterPage: 'Sign up now', + rule: { + tenantId: { + required: 'Please enter your tenant id' + }, + username: { + required: 'Please enter your account' + }, + password: { + required: 'Please enter your password' + }, + code: { + required: 'Please enter a verification code' + } + }, + social: { + wechat: 'Wechat Login', + maxkey: 'MaxKey Login', + topiam: 'TopIam Login', + gitee: 'Gitee Login', + github: 'Github Login' + } + }, + // 娉ㄥ唽椤甸潰鍥介檯鍖� + register: { + selectPlaceholder: 'Please select/enter a company name', + username: 'Username', + password: 'Password', + confirmPassword: 'Confirm Password', + register: 'Register', + registering: 'Registering...', + registerSuccess: 'Congratulations, your {username} account has been registered!', + code: 'Verification Code', + switchLoginPage: 'Log in with an existing account', + rule: { + tenantId: { + required: 'Please enter your tenant id' + }, + username: { + required: 'Please enter your account', + length: 'The length of the user account must be between {min} and {max}' + }, + password: { + required: 'Please enter your password', + length: 'The user password must be between {min} and {max} in length', + pattern: "Can't contain illegal characters: {strings}" + }, + code: { + required: 'Please enter a verification code' + }, + confirmPassword: { + required: 'Please enter your password again', + equalToPassword: 'The password entered twice is inconsistent' + } + } }, // 瀵艰埅鏍忓浗闄呭寲 navbar: { diff --git a/src/lang/zh_CN.json b/src/lang/zh_CN.json index 071598d..14138b5 100644 --- a/src/lang/zh_CN.json +++ b/src/lang/zh_CN.json @@ -4,11 +4,67 @@ "document": "椤圭洰鏂囨。" }, "login": { + "selectPlaceholder": "璇烽�夋嫨/杈撳叆鍏徃鍚嶇О", "username": "鐢ㄦ埛鍚�", "password": "瀵嗙爜", "login": "鐧� 褰�", - "code": "璇疯緭鍏ラ獙璇佺爜", - "copyright": "" + "logging": "鐧� 褰� 涓�...", + "code": "楠岃瘉鐮�", + "rememberPassword": "璁颁綇鎴�", + "switchRegisterPage": "绔嬪嵆娉ㄥ唽", + "rule": { + "tenantId": { + "required": "璇疯緭鍏ユ偍鐨勭鎴风紪鍙�" + }, + "username": { + "required": "璇疯緭鍏ユ偍鐨勮处鍙�" + }, + "password": { + "required": "璇疯緭鍏ユ偍鐨勫瘑鐮�" + }, + "code": { + "required": "璇疯緭鍏ラ獙璇佺爜" + } + }, + "social": { + "wechat": "寰俊鐧诲綍", + "maxkey": "MaxKey鐧诲綍", + "topiam": "TopIam鐧诲綍", + "gitee": "Gitee鐧诲綍", + "github": "Github鐧诲綍" + } + }, + "register": { + "selectPlaceholder": "璇烽�夋嫨/杈撳叆鍏徃鍚嶇О", + "username": "鐢ㄦ埛鍚�", + "password": "瀵嗙爜", + "confirmPassword": "纭瀵嗙爜", + "register": "娉� 鍐�", + "registering": "娉� 鍐� 涓�...", + "registerSuccess": "鎭枩浣狅紝鎮ㄧ殑璐﹀彿 {username} 娉ㄥ唽鎴愬姛锛�", + "code": "楠岃瘉鐮�", + "switchLoginPage": "浣跨敤宸叉湁璐︽埛鐧诲綍", + "rule": { + "tenantId": { + "required": "璇疯緭鍏ユ偍鐨勭鎴风紪鍙�" + }, + "username": { + "required": "璇疯緭鍏ユ偍鐨勮处鍙�", + "length": "鐢ㄦ埛璐﹀彿闀垮害蹇呴』浠嬩簬 {min} 鍜� {max} 涔嬮棿" + }, + "password": { + "required": "璇疯緭鍏ユ偍鐨勫瘑鐮�", + "length": "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 {min} 鍜� {max} 涔嬮棿", + "pattern": "涓嶈兘鍖呭惈闈炴硶瀛楃锛歿strings}" + }, + "code": { + "required": "璇疯緭鍏ラ獙璇佺爜" + }, + "confirmPassword": { + "required": "璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�", + "equalToPassword": "涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�" + } + } }, "navbar": { "full": "鍏ㄥ睆", diff --git a/src/lang/zh_CN.ts b/src/lang/zh_CN.ts index 666a400..3cc9872 100644 --- a/src/lang/zh_CN.ts +++ b/src/lang/zh_CN.ts @@ -6,12 +6,70 @@ }, // 鐧诲綍椤甸潰鍥介檯鍖� login: { + selectPlaceholder: '璇烽�夋嫨/杈撳叆鍏徃鍚嶇О', username: '鐢ㄦ埛鍚�', password: '瀵嗙爜', login: '鐧� 褰�', - code: '璇疯緭鍏ラ獙璇佺爜', - copyright: '' + logging: '鐧� 褰� 涓�...', + code: '楠岃瘉鐮�', + rememberPassword: '璁颁綇鎴�', + switchRegisterPage: '绔嬪嵆娉ㄥ唽', + rule: { + tenantId: { + required: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' + }, + username: { + required: '璇疯緭鍏ユ偍鐨勮处鍙�' + }, + password: { + required: '璇疯緭鍏ユ偍鐨勫瘑鐮�' + }, + code: { + required: '璇疯緭鍏ラ獙璇佺爜' + } + }, + social: { + wechat: '寰俊鐧诲綍', + maxkey: 'MaxKey鐧诲綍', + topiam: 'TopIam鐧诲綍', + gitee: 'Gitee鐧诲綍', + github: 'Github鐧诲綍' + } }, + // 娉ㄥ唽椤甸潰鍥介檯鍖� + register: { + selectPlaceholder: '璇烽�夋嫨/杈撳叆鍏徃鍚嶇О', + username: '鐢ㄦ埛鍚�', + password: '瀵嗙爜', + confirmPassword: '纭瀵嗙爜', + register: '娉� 鍐�', + registering: '娉� 鍐� 涓�...', + registerSuccess: '鎭枩浣狅紝鎮ㄧ殑璐﹀彿 {username} 娉ㄥ唽鎴愬姛锛�', + code: '楠岃瘉鐮�', + switchLoginPage: '浣跨敤宸叉湁璐︽埛鐧诲綍', + rule: { + tenantId: { + required: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' + }, + username: { + required: '璇疯緭鍏ユ偍鐨勮处鍙�', + length: '鐢ㄦ埛璐﹀彿闀垮害蹇呴』浠嬩簬 {min} 鍜� {max} 涔嬮棿' + }, + password: { + required: '璇疯緭鍏ユ偍鐨勫瘑鐮�', + length: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 {min} 鍜� {max} 涔嬮棿', + pattern: '涓嶈兘鍖呭惈闈炴硶瀛楃锛歿strings}' + }, + code: { + required: '璇疯緭鍏ラ獙璇佺爜' + }, + confirmPassword: { + required: '璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�', + equalToPassword: '涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�' + } + } + }, + // 瀵艰埅鏍忓浗闄呭寲 navbar: { full: '鍏ㄥ睆', language: '璇█', diff --git a/src/views/login.vue b/src/views/login.vue index 71d5dcd..7f7ae6b 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -1,56 +1,73 @@ <template> <div class="login"> <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form"> - <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <div class="title-box"> + <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <lang-select class="lang-select hover-effect" /> + </div> <el-form-item v-if="tenantEnabled" prop="tenantId"> - <el-select v-model="loginForm.tenantId" filterable placeholder="璇烽�夋嫨/杈撳叆鍏徃鍚嶇О" style="width: 100%"> + <el-select v-model="loginForm.tenantId" filterable :placeholder="$t('tenant.selectPlaceholder')" style="width: 100%"> <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option> <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> </el-select> </el-form-item> <el-form-item prop="username"> - <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="璐﹀彿"> + <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="$t('login.username')"> <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item prop="password"> - <el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="瀵嗙爜" @keyup.enter="handleLogin"> + <el-input + v-model="loginForm.password" + type="password" + size="large" + auto-complete="off" + :placeholder="$t('login.password')" + @keyup.enter="handleLogin" + > <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item v-if="captchaEnabled" prop="code"> - <el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="楠岃瘉鐮�" style="width: 63%" @keyup.enter="handleLogin"> + <el-input + v-model="loginForm.code" + size="large" + auto-complete="off" + :placeholder="$t('login.code')" + style="width: 63%" + @keyup.enter="handleLogin" + > <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> </el-input> <div class="login-code"> <img :src="codeUrl" class="login-code-img" @click="getCode" /> </div> </el-form-item> - <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">璁颁綇瀵嗙爜</el-checkbox> + <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">{{ $t('login.rememberPassword') }}</el-checkbox> <el-form-item style="float: right"> - <el-button circle title="寰俊鐧诲綍" @click="doSocialLogin('wechat')"> + <el-button circle :title="$t('login.social.wechat')" @click="doSocialLogin('wechat')"> <svg-icon icon-class="wechat" /> </el-button> - <el-button circle title="MaxKey鐧诲綍" @click="doSocialLogin('maxkey')"> + <el-button circle :title="$t('login.social.maxkey')" @click="doSocialLogin('maxkey')"> <svg-icon icon-class="maxkey" /> </el-button> - <el-button circle title="TopIam鐧诲綍" @click="doSocialLogin('topiam')"> + <el-button circle :title="$t('login.social.topiam')" @click="doSocialLogin('topiam')"> <svg-icon icon-class="topiam" /> </el-button> - <el-button circle title="Gitee鐧诲綍" @click="doSocialLogin('gitee')"> + <el-button circle :title="$t('login.social.gitee')" @click="doSocialLogin('gitee')"> <svg-icon icon-class="gitee" /> </el-button> - <el-button circle title="Github鐧诲綍" @click="doSocialLogin('github')"> + <el-button circle :title="$t('login.social.github')" @click="doSocialLogin('github')"> <svg-icon icon-class="github" /> </el-button> </el-form-item> <el-form-item style="width: 100%"> <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin"> - <span v-if="!loading">鐧� 褰�</span> - <span v-else>鐧� 褰� 涓�...</span> + <span v-if="!loading">{{ $t('login.login') }}</span> + <span v-else>{{ $t('login.logging') }}</span> </el-button> <div v-if="register" style="float: right"> - <router-link class="link-type" :to="'/register'">绔嬪嵆娉ㄥ唽</router-link> + <router-link class="link-type" :to="'/register'">{{ $t('login.switchRegisterPage') }}</router-link> </div> </el-form-item> </el-form> @@ -68,9 +85,11 @@ import { LoginData, TenantVO } from '@/api/types'; import { to } from 'await-to-js'; import { HttpStatus } from '@/enums/RespEnum'; +import { useI18n } from 'vue-i18n'; const userStore = useUserStore(); const router = useRouter(); +const { t } = useI18n(); const loginForm = ref<LoginData>({ tenantId: '000000', @@ -82,10 +101,10 @@ } as LoginData); const loginRules: ElFormRules = { - tenantId: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' }], - username: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勮处鍙�' }], - password: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勫瘑鐮�' }], - code: [{ required: true, trigger: 'change', message: '璇疯緭鍏ラ獙璇佺爜' }] + tenantId: [{ required: true, trigger: 'blur', message: t('login.rule.tenantId.required') }], + username: [{ required: true, trigger: 'blur', message: t('login.rule.username.required') }], + password: [{ required: true, trigger: 'blur', message: t('login.rule.password.required') }], + code: [{ required: true, trigger: 'change', message: t('login.rule.code.required') }] }; const codeUrl = ref(''); @@ -218,10 +237,23 @@ background-size: cover; } -.title { - margin: 0px auto 30px auto; - text-align: center; - color: #707070; +.title-box { + display: flex; + + .title { + margin: 0px auto 30px auto; + text-align: center; + color: #707070; + } + + .lang-select { + line-height: 30px; + color: #7483a3; + + &.hover-effect { + cursor: pointer; + } + } } .login-form { diff --git a/src/views/register.vue b/src/views/register.vue index 83f7a27..e6b6ca8 100644 --- a/src/views/register.vue +++ b/src/views/register.vue @@ -1,20 +1,30 @@ <template> <div class="register"> <el-form ref="registerRef" :model="registerForm" :rules="registerRules" class="register-form"> - <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <div class="title-box"> + <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <lang-select class="lang-select hover-effect" /> + </div> <el-form-item v-if="tenantEnabled" prop="tenantId"> - <el-select v-model="registerForm.tenantId" filterable placeholder="璇烽�夋嫨/杈撳叆鍏徃鍚嶇О" style="width: 100%"> + <el-select v-model="registerForm.tenantId" filterable :placeholder="$t('register.selectPlaceholder')" style="width: 100%"> <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"> </el-option> <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> </el-select> </el-form-item> <el-form-item prop="username"> - <el-input v-model="registerForm.username" type="text" size="large" auto-complete="off" placeholder="璐﹀彿"> + <el-input v-model="registerForm.username" type="text" size="large" auto-complete="off" :placeholder="$t('register.username')"> <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item prop="password"> - <el-input v-model="registerForm.password" type="password" size="large" auto-complete="off" placeholder="瀵嗙爜" @keyup.enter="handleRegister"> + <el-input + v-model="registerForm.password" + type="password" + size="large" + auto-complete="off" + :placeholder="$t('register.password')" + @keyup.enter="handleRegister" + > <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> @@ -24,14 +34,21 @@ type="password" size="large" auto-complete="off" - placeholder="纭瀵嗙爜" + :placeholder="$t('register.confirmPassword')" @keyup.enter="handleRegister" > <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item v-if="captchaEnabled" prop="code"> - <el-input v-model="registerForm.code" size="large" auto-complete="off" placeholder="楠岃瘉鐮�" style="width: 63%" @keyup.enter="handleRegister"> + <el-input + v-model="registerForm.code" + size="large" + auto-complete="off" + :placeholder="$t('register.code')" + style="width: 63%" + @keyup.enter="handleRegister" + > <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> </el-input> <div class="register-code"> @@ -40,11 +57,11 @@ </el-form-item> <el-form-item style="width: 100%"> <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleRegister"> - <span v-if="!loading">娉� 鍐�</span> - <span v-else>娉� 鍐� 涓�...</span> + <span v-if="!loading">{{ $t('register.register') }}</span> + <span v-else>{{ $t('register.registering') }}</span> </el-button> <div style="float: right"> - <router-link class="link-type" :to="'/login'">浣跨敤宸叉湁璐︽埛鐧诲綍</router-link> + <router-link class="link-type" :to="'/login'">{{ $t('register.switchLoginPage') }}</router-link> </div> </el-form-item> </el-form> @@ -59,8 +76,11 @@ import { getCodeImg, register, getTenantList } from '@/api/login'; import { RegisterForm, TenantVO } from '@/api/types'; import { to } from 'await-to-js'; +import { useI18n } from 'vue-i18n'; const router = useRouter(); + +const { t } = useI18n(); const registerForm = ref<RegisterForm>({ tenantId: '', @@ -77,28 +97,28 @@ const equalToPassword = (rule: any, value: string, callback: any) => { if (registerForm.value.password !== value) { - callback(new Error('涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�')); + callback(new Error(t('register.rule.confirmPassword.equalToPassword'))); } else { callback(); } }; const registerRules: ElFormRules = { - tenantId: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' }], + tenantId: [{ required: true, trigger: 'blur', message: t('register.rule.tenantId.required') }], username: [ - { required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勮处鍙�' }, - { min: 2, max: 20, message: '鐢ㄦ埛璐﹀彿闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿', trigger: 'blur' } + { required: true, trigger: 'blur', message: t('register.rule.username.required') }, + { min: 2, max: 20, message: t('register.rule.username.length', { min: 2, max: 20 }), trigger: 'blur' } ], password: [ - { required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勫瘑鐮�' }, - { min: 5, max: 20, message: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', trigger: 'blur' }, - { pattern: /^[^<>"'|\\]+$/, message: '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\ |', trigger: 'blur' } + { required: true, trigger: 'blur', message: t('register.rule.password.required') }, + { min: 5, max: 20, message: t('register.rule.password.length', { min: 5, max: 20 }), trigger: 'blur' }, + { pattern: /^[^<>"'|\\]+$/, message: t('register.rule.password.pattern', { strings: '< > " \' \\ |' }), trigger: 'blur' } ], confirmPassword: [ - { required: true, trigger: 'blur', message: '璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�' }, + { required: true, trigger: 'blur', message: t('register.rule.confirmPassword.required') }, { required: true, validator: equalToPassword, trigger: 'blur' } ], - code: [{ required: true, trigger: 'change', message: '璇疯緭鍏ラ獙璇佺爜' }] + code: [{ required: true, trigger: 'change', message: t('register.rule.code.required') }] }; const codeUrl = ref(''); const loading = ref(false); @@ -114,7 +134,7 @@ const [err] = await to(register(registerForm.value)); if (!err) { const username = registerForm.value.username; - await ElMessageBox.alert("<font color='red'>鎭枩浣狅紝鎮ㄧ殑璐﹀彿 " + username + ' 娉ㄥ唽鎴愬姛锛�</font>', '绯荤粺鎻愮ず', { + await ElMessageBox.alert("<font color='red'>" + t('register.registerSuccess', { username }) + '</font>', '绯荤粺鎻愮ず', { dangerouslyUseHTMLString: true, type: 'success' }); @@ -166,10 +186,23 @@ background-size: cover; } -.title { - margin: 0 auto 30px auto; - text-align: center; - color: #707070; +.title-box { + display: flex; + + .title { + margin: 0px auto 30px auto; + text-align: center; + color: #707070; + } + + .lang-select { + line-height: 30px; + color: #7483a3; + + &.hover-effect { + cursor: pointer; + } + } } .register-form { -- Gitblit v1.9.3