Skip to content

Commit 912e091

Browse files
chore(locale): config i18n & multi lang for auth page (#131)
* chore(locale): config i18n & multi lang for auth page * chore: refactor comment --------- Co-authored-by: huynam-dana <[email protected]>
1 parent 78120a0 commit 912e091

File tree

11 files changed

+485
-215
lines changed

11 files changed

+485
-215
lines changed

public/locales/US.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"auth": {
3+
"welcome_back": "Welcome Back",
4+
"new_day_description": "Today is a new day. It's your day. You shape it.",
5+
"sign_in_description": "Sign in to start managing your projects",
6+
"register_account": "Register account",
7+
"register_description": "Sign up to start managing your projects",
8+
"reset_password": "Reset Password",
9+
"reset_password_description": "Enter your new password to reset it",
10+
"forgot_password": "Forgot password",
11+
"forgot_password_description": "Enter your email to reset password",
12+
"forgot_password_sent": "A password reset link has been sent to {email}. Click the link to complete the password reset. If you still haven't received the email, please hit resend below.",
13+
"name": "Name",
14+
"name_placeholder": "Enter name...",
15+
"email": "Email",
16+
"email_placeholder": "Enter email...",
17+
"password": "Password",
18+
"password_placeholder": "Enter password...",
19+
"confirm_password": "Confirm password",
20+
"confirm_password_placeholder": "Enter confirm password...",
21+
"sign_in": "Sign in",
22+
"sign_up": "Sign Up",
23+
"submit": "Submit",
24+
"resend": "Resend",
25+
"come_back": "Come back",
26+
"or": "Or",
27+
"sign_in_with_google": "Sign in with Google",
28+
"no_account": "Don't you have an account?",
29+
"have_account": "If you have an account?",
30+
"email_required": "Email is required",
31+
"email_must_not_blank": "Email must not be blank",
32+
"name_required": "Name is required",
33+
"password_required": "Password is required",
34+
"confirm_password_required": "Confirm password is required",
35+
"password_min_length": "Password must be at least 6 characters",
36+
"password_uppercase": "Password must contain uppercase letter",
37+
"passwords_must_match": "Passwords must match",
38+
"registration_success": "Success",
39+
"registration_success_message": "Registration successful check email to confirm account",
40+
"register_failed": "Register failed",
41+
"confirm_success": "Success",
42+
"confirm_success_message": "Registration confirmed successfully, please proceed to login",
43+
"confirm_failed": "Confirm failed",
44+
"reset_success": "Success",
45+
"reset_success_message": "Reset password successful",
46+
"reset_failed": "Failed",
47+
"reset_expired": "Expired password recovery link",
48+
"reset_error": "Reset failed",
49+
"forgot_success": "Success",
50+
"forgot_success_message": "Resend email success",
51+
"forgot_failed": "Resend email failed",
52+
"forgot_failed_message": "Send forgot password error",
53+
"resend_failed": "Failed",
54+
"resend_failed_message": "Resend email failed"
55+
}
56+
}

public/locales/VN.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"auth": {
3+
"welcome_back": "Chào Mừng Trở Lại",
4+
"new_day_description": "Hôm nay là một ngày mới. Đó là ngày của bạn. Bạn tạo nên nó.",
5+
"sign_in_description": "Đăng nhập để bắt đầu quản lý dự án của bạn",
6+
"register_account": "Đăng ký tài khoản",
7+
"register_description": "Đăng ký để bắt đầu quản lý dự án của bạn",
8+
"reset_password": "Đặt Lại Mật Khẩu",
9+
"reset_password_description": "Nhập mật khẩu mới của bạn để đặt lại",
10+
"forgot_password": "Quên mật khẩu",
11+
"forgot_password_description": "Nhập email của bạn để đặt lại mật khẩu",
12+
"forgot_password_sent": "Liên kết đặt lại mật khẩu đã được gửi đến {email}. Nhấp vào liên kết để hoàn tất việc đặt lại mật khẩu. Nếu bạn vẫn chưa nhận được email, vui lòng nhấn gửi lại bên dưới.",
13+
"name": "Tên",
14+
"name_placeholder": "Nhập tên...",
15+
"email": "Email",
16+
"email_placeholder": "Nhập email...",
17+
"password": "Mật khẩu",
18+
"password_placeholder": "Nhập mật khẩu...",
19+
"confirm_password": "Xác nhận mật khẩu",
20+
"confirm_password_placeholder": "Nhập lại mật khẩu...",
21+
"sign_in": "Đăng nhập",
22+
"sign_up": "Đăng ký",
23+
"submit": "Gửi",
24+
"resend": "Gửi lại",
25+
"come_back": "Quay lại",
26+
"or": "Hoặc",
27+
"sign_in_with_google": "Đăng nhập với Google",
28+
"no_account": "Bạn chưa có tài khoản?",
29+
"have_account": "Bạn đã có tài khoản?",
30+
"email_required": "Email là bắt buộc",
31+
"email_must_not_blank": "Email không được để trống",
32+
"name_required": "Tên là bắt buộc",
33+
"password_required": "Mật khẩu là bắt buộc",
34+
"confirm_password_required": "Xác nhận mật khẩu là bắt buộc",
35+
"password_min_length": "Mật khẩu phải có ít nhất 6 ký tự",
36+
"password_uppercase": "Mật khẩu phải chứa chữ hoa",
37+
"passwords_must_match": "Mật khẩu phải khớp nhau",
38+
"registration_success": "Thành công",
39+
"registration_success_message": "Đăng ký thành công, kiểm tra email để xác nhận tài khoản",
40+
"register_failed": "Đăng ký thất bại",
41+
"confirm_success": "Thành công",
42+
"confirm_success_message": "Xác nhận đăng ký thành công, vui lòng tiến hành đăng nhập",
43+
"confirm_failed": "Xác nhận thất bại",
44+
"reset_success": "Thành công",
45+
"reset_success_message": "Đặt lại mật khẩu thành công",
46+
"reset_failed": "Thất bại",
47+
"reset_expired": "Liên kết khôi phục mật khẩu đã hết hạn",
48+
"reset_error": "Đặt lại mật khẩu thất bại",
49+
"forgot_success": "Thành công",
50+
"forgot_success_message": "Gửi email thành công",
51+
"forgot_failed": "Gửi email thất bại",
52+
"forgot_failed_message": "Lỗi gửi email quên mật khẩu",
53+
"resend_failed": "Thất bại",
54+
"resend_failed_message": "Gửi lại email thất bại"
55+
}
56+
}

public/locales/en.json

Lines changed: 0 additions & 6 deletions
This file was deleted.

public/locales/vi.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/pages/auth/login.vue

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ import { useForm } from 'vee-validate'
55
import * as yup from 'yup'
66
import { useAuthStore } from '@/stores/auth'
77
import { googleTokenLogin } from 'vue3-google-login'
8+
import { useI18n } from 'vue-i18n'
9+
10+
const { t } = useI18n()
811
912
const { handleSubmit } = useForm({
1013
validationSchema: yup.object({
11-
email: yup.string().email().required('Email is required'),
14+
email: yup.string().email().required(t('auth.email_required')),
1215
password: yup
1316
.string()
14-
.required('Password is required')
15-
.min(6, 'Password must be at least 6 characters')
16-
.matches(/[A-Z]/, 'Password must contain uppercase letter'),
17+
.required(t('auth.password_required'))
18+
.min(6, t('auth.password_min_length'))
19+
.matches(/[A-Z]/, t('auth.password_uppercase')),
1720
}),
1821
})
1922
@@ -40,28 +43,28 @@ const loginGoogle = () => {
4043
@submit="onSubmit"
4144
>
4245
<div class="flex items-center gap-0.5 mb-4">
43-
<h1 class="text-[344054] text-lg font-semibold mt-3">Welcome Back</h1>
46+
<h1 class="text-[344054] text-lg font-semibold mt-3">{{ $t('auth.welcome_back') }}</h1>
4447
</div>
4548
<div>
46-
<h2 class="mt-1 text-[#667085]">Today is a new day. It's your day. You shape it.</h2>
47-
<h2 class="mt-1 text-[#667085]">Sign in to start managing your projects</h2>
49+
<h2 class="mt-1 text-[#667085]">{{ $t('auth.new_day_description') }}</h2>
50+
<h2 class="mt-1 text-[#667085]">{{ $t('auth.sign_in_description') }}</h2>
4851
</div>
4952
<div class="mt-6">
5053
<div class="form-data">
51-
<label for="email">Email</label>
54+
<label for="email">{{ $t('auth.email') }}</label>
5255
<InputValidation
5356
id="email"
54-
placeholder="Enter email..."
57+
:placeholder="$t('auth.email_placeholder')"
5558
type="email"
5659
name="email"
5760
class="h-10 mt-1 bg-slate-50 border-slate-200 outline-none"
5861
/>
5962
</div>
6063
<div class="form-data mt-3">
61-
<label for="password">Password</label>
64+
<label for="password">{{ $t('auth.password') }}</label>
6265
<InputValidation
6366
id="password"
64-
placeholder="Enter password..."
67+
:placeholder="$t('auth.password_placeholder')"
6568
type="password"
6669
name="password"
6770
class="h-10 mt-1 bg-slate-50 border-slate-200 outline-none"
@@ -73,7 +76,7 @@ const loginGoogle = () => {
7376
class="text-[#0921D9] text-xs font-normal"
7477
to="/password/forgot"
7578
>
76-
Forgot Password?
79+
{{ $t('auth.forgot_password') }}
7780
</RouterLink>
7881
</div>
7982
<Button
@@ -84,11 +87,11 @@ const loginGoogle = () => {
8487
v-if="isLoading"
8588
class="i-svg-spinners-ring-resize"
8689
></span>
87-
Sign in
90+
{{ $t('auth.sign_in') }}
8891
</Button>
8992
<div class="flex items-center gap-2 w-full mt-8">
9093
<span class="h-px bg-slate-200 w-full"></span>
91-
<p class="text-base">Or</p>
94+
<p class="text-base">{{ $t('auth.or') }}</p>
9295
<span class="h-px bg-slate-200 w-full"></span>
9396
</div>
9497
</form>
@@ -102,16 +105,16 @@ const loginGoogle = () => {
102105
src="@/assets/img/google-logo.png"
103106
alt=""
104107
/>
105-
Sign in with Google
108+
{{ $t('auth.sign_in_with_google') }}
106109
</Button>
107110

108111
<div class="flex justify-center mt-6">
109-
<p>Don't you have an account?</p>
112+
<p>{{ $t('auth.no_account') }}</p>
110113
<RouterLink
111114
class="ml-[6px] text-[#0921D9] font-normal"
112115
to="/register"
113116
>
114-
Sign up
117+
{{ $t('auth.sign_up') }}
115118
</RouterLink>
116119
</div>
117120
</div>

src/pages/auth/password/forgot.vue

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import { Button } from '@/components/ui/button'
66
import { useForm } from 'vee-validate'
77
import * as yup from 'yup'
88
import { showToast } from '@/utils/toast'
9+
import { useI18n } from 'vue-i18n'
910
11+
const { t } = useI18n()
1012
const errorEmail = ref()
1113
const isForgot = ref(false)
1214
const isCountdown = ref(false)
@@ -17,21 +19,21 @@ const isLoading = ref(false)
1719
const handleForgot = async () => {
1820
try {
1921
if (!email.value) {
20-
errorEmail.value = 'Email must not be blank'
22+
errorEmail.value = t('auth.email_must_not_blank')
2123
return
2224
}
2325
await forgotPasswordApi(email.value)
2426
isLoading.value = true
2527
showToast({
26-
title: 'Success',
27-
description: 'Resend email success',
28+
title: t('auth.forgot_success'),
29+
description: t('auth.forgot_success_message'),
2830
variant: 'default',
2931
})
3032
isForgot.value = true
3133
} catch (error) {
3234
showToast({
33-
title: 'Resend email failed',
34-
description: `${((error as any).data?.error?.message as string) || 'Send forgot password error'}`,
35+
title: t('auth.forgot_failed'),
36+
description: `${((error as any).data?.error?.message as string) || t('auth.forgot_failed_message')}`,
3537
variant: 'destructive',
3638
})
3739
} finally {
@@ -43,8 +45,8 @@ const handleResentEmail = async (time: number) => {
4345
try {
4446
await forgotPasswordApi(email.value)
4547
showToast({
46-
title: 'Success',
47-
description: 'Resend email success',
48+
title: t('auth.forgot_success'),
49+
description: t('auth.forgot_success_message'),
4850
variant: 'default',
4951
})
5052
isForgot.value = true
@@ -53,8 +55,8 @@ const handleResentEmail = async (time: number) => {
5355
startTimer()
5456
} catch (error) {
5557
showToast({
56-
title: 'Failed',
57-
description: 'Resend email failed',
58+
title: t('auth.resend_failed'),
59+
description: t('auth.resend_failed_message'),
5860
variant: 'default',
5961
})
6062
}
@@ -83,7 +85,7 @@ const checkSecond = (sec: number) => {
8385
8486
const { errors, defineField } = useForm({
8587
validationSchema: yup.object({
86-
email: yup.string().email().required('Email is required'),
88+
email: yup.string().email().required(t('auth.email_required')),
8789
}),
8890
})
8991
@@ -102,22 +104,24 @@ const [email, emailAttrs] = defineField('email')
102104
<h2 class="text-lg font-semibold">Quizzfly</h2>
103105
</div>
104106
<div class="flex flex-col items-start gap-2 mb-2 mt-6">
105-
<h1 class="text-[344054] text-lg font-semibold">Forgot password</h1>
106-
<h1
107+
<h1 class="text-[344054] text-lg font-semibold">{{ $t('auth.forgot_password') }}</h1>
108+
<i18n-t
107109
v-if="isForgot"
110+
keypath="auth.forgot_password_sent"
111+
tag="h1"
108112
class="text-[344054] text-sm font-medium"
109113
>
110-
A password reset link has been sent to <span class="text-primary">{{ email }}</span
111-
>. Click the link to complete the password reset. If you still haven't received the
112-
email, please hit resend below.
113-
</h1>
114+
<template #email>
115+
<span class="text-primary">{{ email }}</span>
116+
</template>
117+
</i18n-t>
114118
</div>
115119
<div>
116120
<h2
117121
v-if="!isForgot"
118122
class="mt-1 text-[#667085]"
119123
>
120-
Enter your email to reset password
124+
{{ $t('auth.forgot_password_description') }}
121125
</h2>
122126
</div>
123127
<div class="mt-6">
@@ -126,12 +130,12 @@ const [email, emailAttrs] = defineField('email')
126130
class="form-data"
127131
@submit.prevent="handleForgot"
128132
>
129-
<label for="email">Email</label>
133+
<label for="email">{{ $t('auth.email') }}</label>
130134
<Input
131135
v-if="!isForgot"
132136
id="email"
133137
v-model="email"
134-
placeholder="Enter email..."
138+
:placeholder="$t('auth.email_placeholder')"
135139
v-bind="emailAttrs"
136140
:invalid="errors.email"
137141
type="email"
@@ -150,7 +154,7 @@ const [email, emailAttrs] = defineField('email')
150154
v-if="isLoading"
151155
class="i-svg-spinners-ring-resize"
152156
></span>
153-
Submit
157+
{{ $t('auth.submit') }}
154158
</Button>
155159
</form>
156160
<Button
@@ -160,7 +164,7 @@ const [email, emailAttrs] = defineField('email')
160164
:disable-cache="isCountdown"
161165
@click="handleResentEmail(5)"
162166
>
163-
Resend
167+
{{ $t('auth.resend') }}
164168
</Button>
165169
<div class="flex items-center justify-center w-full">
166170
<div
@@ -178,7 +182,7 @@ const [email, emailAttrs] = defineField('email')
178182
class="text-[#0921D9] text-xs font-semibold"
179183
to="/login"
180184
>
181-
Come back
185+
{{ $t('auth.come_back') }}
182186
</RouterLink>
183187
</div>
184188
</div>

0 commit comments

Comments
 (0)