feat: adjust signup form validation based on locale

This commit is contained in:
jingrow 2025-12-26 23:39:47 +08:00
parent 5ad1621c1f
commit 52442082a2
3 changed files with 163 additions and 82 deletions

View File

@ -42,8 +42,9 @@
"Please confirm password": "请确认密码", "Please confirm password": "请确认密码",
"Passwords do not match": "两次输入的密码不一致", "Passwords do not match": "两次输入的密码不一致",
"Email (Optional)": "邮箱(可选)", "Email (Optional)": "邮箱(可选)",
"Phone Number": "手机号", "Please enter email": "请输入邮箱",
"Phone Number (Optional)": "手机号(可选)", "Mobile": "手机号",
"Mobile (Optional)": "手机号(可选)",
"Please enter a valid email address": "请输入有效的邮箱地址", "Please enter a valid email address": "请输入有效的邮箱地址",
"Please enter phone number": "请输入手机号", "Please enter phone number": "请输入手机号",
"Please enter a valid phone number": "请输入有效的手机号码", "Please enter a valid phone number": "请输入有效的手机号码",

View File

@ -3,7 +3,7 @@ import { computed, ref, watch, onMounted, onUnmounted, nextTick, reactive } from
import { NButton, NSpace, useMessage, NModal, NForm, NFormItem, NInput, NText, NLayout, NLayoutSider, NLayoutHeader, NLayoutContent } from 'naive-ui' import { NButton, NSpace, useMessage, NModal, NForm, NFormItem, NInput, NText, NLayout, NLayoutSider, NLayoutHeader, NLayoutContent } from 'naive-ui'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import { useSEO } from '@/shared/composables/useSEO' import { useSEO } from '@/shared/composables/useSEO'
import { t } from '@/shared/i18n' import { t, getCurrentLocale } from '@/shared/i18n'
import { useAuthStore } from '@/shared/stores/auth' import { useAuthStore } from '@/shared/stores/auth'
import { signupApi } from '@/shared/api/auth' import { signupApi } from '@/shared/api/auth'
import AppHeader from '@/app/layouts/AppHeader.vue' import AppHeader from '@/app/layouts/AppHeader.vue'
@ -58,41 +58,81 @@ const validatePasswordMatch = (_rule: any, value: string) => {
return true return true
} }
const signupRules = { const isEnglish = computed(() => getCurrentLocale() === 'en-US')
username: [
{ required: true, message: t('Please enter username'), trigger: 'blur' }, const signupRules = computed(() => {
{ min: 3, message: t('Username must be at least 3 characters'), trigger: 'blur' } const rules: any = {
], username: [
password: [ { required: true, message: t('Please enter username'), trigger: 'blur' },
{ required: true, message: t('Please enter password'), trigger: 'blur' }, { min: 3, message: t('Username must be at least 3 characters'), trigger: 'blur' }
{ min: 6, message: t('Password must be at least 6 characters'), trigger: 'blur' } ],
], password: [
confirmPassword: [ { required: true, message: t('Please enter password'), trigger: 'blur' },
{ required: true, message: t('Please confirm password'), trigger: 'blur' }, { min: 6, message: t('Password must be at least 6 characters'), trigger: 'blur' }
{ validator: validatePasswordMatch, trigger: 'blur' } ],
], confirmPassword: [
email: [ { required: true, message: t('Please confirm password'), trigger: 'blur' },
{ { validator: validatePasswordMatch, trigger: 'blur' }
validator: (_rule: any, value: string) => { ]
if (!value) return true }
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(value)) { // email
return new Error(t('Please enter a valid email address')) if (isEnglish.value) {
} rules.email = [
return true { required: true, message: t('Please enter email'), trigger: 'blur' },
}, {
trigger: 'blur' validator: (_rule: any, value: string) => {
} // required
], if (!value) return true
phoneNumber: [ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
{ required: true, message: t('Please enter phone number'), trigger: 'blur' }, if (!emailRegex.test(value)) {
{ return new Error(t('Please enter a valid email address'))
pattern: /^1[3-9]\d{9}$/, }
message: t('Please enter a valid phone number'), return true
trigger: 'blur' },
} trigger: 'blur'
] }
} ]
rules.phoneNumber = [
{
validator: (_rule: any, value: string) => {
if (!value) return true
const phoneRegex = /^1[3-9]\d{9}$/
if (!phoneRegex.test(value)) {
return new Error(t('Please enter a valid phone number'))
}
return true
},
trigger: 'blur'
}
]
} else {
// email
rules.email = [
{
validator: (_rule: any, value: string) => {
if (!value) return true
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(value)) {
return new Error(t('Please enter a valid email address'))
}
return true
},
trigger: 'blur'
}
]
rules.phoneNumber = [
{ required: true, message: t('Please enter phone number'), trigger: 'blur' },
{
pattern: /^1[3-9]\d{9}$/,
message: t('Please enter a valid phone number'),
trigger: 'blur'
}
]
}
return rules
})
const handleLogin = () => { const handleLogin = () => {
showLoginModal.value = true showLoginModal.value = true
@ -134,7 +174,7 @@ const handleSignupSubmit = async () => {
username: signupFormData.username, username: signupFormData.username,
password: signupFormData.password, password: signupFormData.password,
email: signupFormData.email || undefined, email: signupFormData.email || undefined,
phone_number: signupFormData.phoneNumber phone_number: isEnglish.value ? (signupFormData.phoneNumber || undefined) : signupFormData.phoneNumber
}) })
if (result.success) { if (result.success) {
@ -1508,7 +1548,7 @@ onUnmounted(() => {
<n-form-item path="email"> <n-form-item path="email">
<n-input <n-input
v-model:value="signupFormData.email" v-model:value="signupFormData.email"
:placeholder="t('Email (Optional)')" :placeholder="isEnglish ? t('Email') : t('Email (Optional)')"
:input-props="{ autocomplete: 'email', type: 'email' }" :input-props="{ autocomplete: 'email', type: 'email' }"
> >
<template #prefix> <template #prefix>
@ -1517,10 +1557,10 @@ onUnmounted(() => {
</n-input> </n-input>
</n-form-item> </n-form-item>
<n-form-item path="phoneNumber"> <n-form-item v-if="!isEnglish" path="phoneNumber">
<n-input <n-input
v-model:value="signupFormData.phoneNumber" v-model:value="signupFormData.phoneNumber"
:placeholder="t('Phone Number')" :placeholder="t('Mobile')"
:input-props="{ autocomplete: 'tel' }" :input-props="{ autocomplete: 'tel' }"
> >
<template #prefix> <template #prefix>

View File

@ -59,7 +59,7 @@
<n-form-item path="email"> <n-form-item path="email">
<n-input <n-input
v-model:value="formData.email" v-model:value="formData.email"
:placeholder="t('Email (Optional)')" :placeholder="isEnglish ? t('Email') : t('Email (Optional)')"
:input-props="{ autocomplete: 'email', type: 'email' }" :input-props="{ autocomplete: 'email', type: 'email' }"
> >
<template #prefix> <template #prefix>
@ -68,10 +68,10 @@
</n-input> </n-input>
</n-form-item> </n-form-item>
<n-form-item path="phoneNumber"> <n-form-item v-if="!isEnglish" path="phoneNumber">
<n-input <n-input
v-model:value="formData.phoneNumber" v-model:value="formData.phoneNumber"
:placeholder="t('Phone Number')" :placeholder="t('Mobile')"
:input-props="{ autocomplete: 'tel' }" :input-props="{ autocomplete: 'tel' }"
> >
<template #prefix> <template #prefix>
@ -112,7 +112,7 @@ import { useRouter } from 'vue-router'
import { NForm, NFormItem, NInput, NButton, NText, useMessage } from 'naive-ui' import { NForm, NFormItem, NInput, NButton, NText, useMessage } from 'naive-ui'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import { useAuthStore } from '../../shared/stores/auth' import { useAuthStore } from '../../shared/stores/auth'
import { t } from '../../shared/i18n' import { t, getCurrentLocale } from '../../shared/i18n'
import { signupApi } from '../../shared/api/auth' import { signupApi } from '../../shared/api/auth'
const router = useRouter() const router = useRouter()
@ -137,41 +137,81 @@ const validatePasswordMatch = (_rule: any, value: string) => {
return true return true
} }
const rules = { const isEnglish = computed(() => getCurrentLocale() === 'en-US')
username: [
{ required: true, message: t('Please enter username'), trigger: 'blur' }, const rules = computed(() => {
{ min: 3, message: t('Username must be at least 3 characters'), trigger: 'blur' } const rules: any = {
], username: [
password: [ { required: true, message: t('Please enter username'), trigger: 'blur' },
{ required: true, message: t('Please enter password'), trigger: 'blur' }, { min: 3, message: t('Username must be at least 3 characters'), trigger: 'blur' }
{ min: 6, message: t('Password must be at least 6 characters'), trigger: 'blur' } ],
], password: [
confirmPassword: [ { required: true, message: t('Please enter password'), trigger: 'blur' },
{ required: true, message: t('Please confirm password'), trigger: 'blur' }, { min: 6, message: t('Password must be at least 6 characters'), trigger: 'blur' }
{ validator: validatePasswordMatch, trigger: 'blur' } ],
], confirmPassword: [
email: [ { required: true, message: t('Please confirm password'), trigger: 'blur' },
{ { validator: validatePasswordMatch, trigger: 'blur' }
validator: (_rule: any, value: string) => { ]
if (!value) return true }
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(value)) { // email
return new Error(t('Please enter a valid email address')) if (isEnglish.value) {
} rules.email = [
return true { required: true, message: t('Please enter email'), trigger: 'blur' },
}, {
trigger: 'blur' validator: (_rule: any, value: string) => {
} // required
], if (!value) return true
phoneNumber: [ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
{ required: true, message: t('Please enter phone number'), trigger: 'blur' }, if (!emailRegex.test(value)) {
{ return new Error(t('Please enter a valid email address'))
pattern: /^1[3-9]\d{9}$/, }
message: t('Please enter a valid phone number'), return true
trigger: 'blur' },
} trigger: 'blur'
] }
} ]
rules.phoneNumber = [
{
validator: (_rule: any, value: string) => {
if (!value) return true
const phoneRegex = /^1[3-9]\d{9}$/
if (!phoneRegex.test(value)) {
return new Error(t('Please enter a valid phone number'))
}
return true
},
trigger: 'blur'
}
]
} else {
// email
rules.email = [
{
validator: (_rule: any, value: string) => {
if (!value) return true
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(value)) {
return new Error(t('Please enter a valid email address'))
}
return true
},
trigger: 'blur'
}
]
rules.phoneNumber = [
{ required: true, message: t('Please enter phone number'), trigger: 'blur' },
{
pattern: /^1[3-9]\d{9}$/,
message: t('Please enter a valid phone number'),
trigger: 'blur'
}
]
}
return rules
})
const handleSignup = async () => { const handleSignup = async () => {
try { try {
@ -182,7 +222,7 @@ const handleSignup = async () => {
username: formData.username, username: formData.username,
password: formData.password, password: formData.password,
email: formData.email || undefined, email: formData.email || undefined,
phone_number: formData.phoneNumber phone_number: isEnglish.value ? (formData.phoneNumber || undefined) : formData.phoneNumber
}) })
if (result.success) { if (result.success) {