bugfix: i18n问题

This commit is contained in:
2026-02-04 16:10:10 +08:00
parent 228e3d56b5
commit 3da4a97400
9 changed files with 242 additions and 120 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 B

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

View File

@@ -1858,14 +1858,16 @@ export default {
uploadSuccess: '上传成功',
uploadFailed: '上传失败',
pdfFileTip: 'PDF文件不超过20MB',
videoFileTip: '视频文件(MP4, MOV)1080p不超过100MB'
videoFileTip: '视频文件(MP4, MOV)1080p不超过100MB',
wechatTitle: '微信公众号',
wechatDesc: '请使用微信扫描二维码'
},
AwardApply: {
// 页面主标题区域
applicationForm: '参赛表格',
emailVerification: '邮箱验证',
aidaUsersOnly: '仅限 AiDA 用户',
slogan: '绽放你的创意 • AiDA 全球设计奖 2026',
slogan: '绽放你的创意 • AiDA 全球设计奖 2026',
// 邮箱验证部分
emailAddress: '邮箱',
sendCode: '发送验证码',
@@ -1952,6 +1954,7 @@ export default {
uploadPdfOnly: '请仅上传 PDF 文件。',
uploadVideoOnly: '请仅上传 MP4 或 MOV 文件。',
fileSizeExceeds: '文件大小超过 {sizeLimit} 限制。请上传较小的文件。',
videoDurationExceeds: '视频时长不可超过60秒',
uploadFailed: '上传失败'
}
}

View File

@@ -1926,18 +1926,21 @@ export default {
uploadSuccess: 'Uploaded Successfully',
uploadFailed: 'Upload failed',
pdfFileTip: 'PDF file, max 20MB',
videoFileTip: 'Video file (MP4, MOV), 1080p, max 100MB'
videoFileTip: 'Video file (MP4, MOV), 1080p, max 100MB',
wechatTitle: 'WeChat Official Account',
wechatDesc: 'Scan the QR code in WeChat'
},
AwardApply: {
// 页面主标题区域
applicationForm: 'Application Form',
emailVerification: 'Email Verification',
aidaUsersOnly: 'AiDA Users Only',
slogan: 'BLOOM YOUR CREATIVITY • AiDA GLOBAL FASHION AWARD 2026',
slogan: 'BLOOM YOUR CREATIVITY • AIDA GLOBAL DESIGN AWARDS 2026',
// 邮箱验证部分
emailAddress: 'Email Address',
sendCode: 'Send Code',
pleaseUseRegisteredEmail: 'Please use the email address you registered with AiDA.',
pleaseUseRegisteredEmail:
'Please use the email address you registered with AiDA.',
// 个人信息部分
personalInformation: 'Personal Information',
tellUsAboutYourself: 'Tell us about yourself',
@@ -1958,7 +1961,8 @@ export default {
shareYourCreativeVision: 'Share your creative vision',
designTitle: 'Design Title',
designDescription: 'Design description',
designDescriptionPlaceholder: 'Briefly describe your design concept, inspiration, and creative direction...',
designDescriptionPlaceholder:
'Briefly describe your design concept, inspiration, and creative direction...',
// 提交文件部分
submissionFiles: 'Submission Files',
uploadYourDesignMaterials: 'Upload your design materials',
@@ -1978,13 +1982,18 @@ export default {
videoFileLimit: 'Video file (MP4, MOV), 1080p, max 100MB',
// 条款与条件
termsAndConditions: 'Terms & Conditions',
conditionFirst: 'I confirm that all submitted work is original and created by me.',
conditionSecond: 'I understand that Code-Create has marketing and promotional rights to all submitted designs and videos.',
conditionThird: 'I agree to participate in finalist activities if selected, including AiDA training and award ceremony.',
conditionFourth: 'I would like to receive updates about AiDA products and future competitions. (Optional)',
conditionFirst:
'I confirm that all submitted work is original and created by me.',
conditionSecond:
'I understand that Code-Create has marketing and promotional rights to all submitted designs and videos.',
conditionThird:
'I agree to participate in finalist activities if selected, including AiDA training and award ceremony.',
conditionFourth:
'I would like to receive updates about AiDA products and future competitions. (Optional)',
// 提交按钮
submitYourDesign: 'Submit your Design',
unfinishedFormTip: 'The link in the AiDA in-platform message will save your unfinished form.',
unfinishedFormTip:
'The link in the AiDA in-platform message will save your unfinished form.',
// 验证码弹窗
checkYourEmail: 'Check your email',
enterSixDigitCode: 'Enter the 6-digit code sent to',
@@ -2018,7 +2027,10 @@ export default {
pleaseUploadVideo: 'Please upload your video',
uploadPdfOnly: 'Please upload a PDF file only.',
uploadVideoOnly: 'Please upload a MP4 or MOV file only.',
fileSizeExceeds: 'File size exceeds {sizeLimit} limit. Please upload a smaller file.',
fileSizeExceeds:
'File size exceeds {sizeLimit} limit. Please upload a smaller file.',
videoDurationExceeds:
'Video duration exceeds 60 seconds limit. Please upload a shorter video.',
uploadFailed: 'Upload failed'
}
}

View File

@@ -9,7 +9,9 @@
class="form-header"
v-if="!isCompleted && !isExpired"
>
<div class="form-title poppins-bold">{{ t('AwardApply.emailVerification') }}</div>
<div class="form-title poppins-bold">
{{ t('AwardApply.emailVerification') }}
</div>
<div class="desc">{{ t('AwardApply.aidaUsersOnly') }}</div>
</div>
</div>
@@ -63,7 +65,9 @@
</a-form-item>
</div>
<div class="form-row full-row">
<div class="form-title poppins-bold">{{ t('AwardApply.personalInformation') }}</div>
<div class="form-title poppins-bold">
{{ t('AwardApply.personalInformation') }}
</div>
<div class="desc">{{ t('AwardApply.tellUsAboutYourself') }}</div>
</div>
<div class="user-info flex">
@@ -109,8 +113,12 @@
</template>
</div>
<div class="form-row full-row">
<div class="form-title poppins-bold">{{ t('AwardApply.designInformation') }}</div>
<div class="desc">{{ t('AwardApply.shareYourCreativeVision') }}</div>
<div class="form-title poppins-bold">
{{ t('AwardApply.designInformation') }}
</div>
<div class="desc">
{{ t('AwardApply.shareYourCreativeVision') }}
</div>
</div>
<a-form-item
class="full-row design-title"
@@ -137,28 +145,30 @@
/>
</a-form-item>
<div class="form-row full-row">
<div class="form-title poppins-bold">{{ t('AwardApply.submissionFiles') }}</div>
<div class="desc">{{ t('AwardApply.uploadYourDesignMaterials') }}</div>
<div class="form-title poppins-bold">
{{ t('AwardApply.submissionFiles') }}
</div>
<div class="desc">
{{ t('AwardApply.uploadYourDesignMaterials') }}
</div>
</div>
<div class="information full-row">
<div class="information-title flex align-center">
<div class="point"></div>
<div class="text poppins-bold">{{ t('AwardApply.submissionRequirements') }}</div>
<div class="text poppins-bold">
{{ t('AwardApply.submissionRequirements') }}
</div>
</div>
<ul class="information-list flex space-between">
<li class="information-item">
{{
t('AwardApply.pdfRequirement')
}}
{{ t('AwardApply.pdfRequirement') }}
</li>
<div class="right">
<li class="information-item">
{{ t('AwardApply.rightContent.format') }}
</li>
<li class="information-item">
{{
t('AwardApply.rightContent.video')
}}
{{ t('AwardApply.rightContent.video') }}
</li>
</div>
</ul>
@@ -187,8 +197,12 @@
alt=""
class="upload-icon"
/>
<p class="desc">{{ t('AwardApply.clickToUploadPdf') }}</p>
<p class="limit">{{ t('AwardApply.pdfFileLimit') }}</p>
<p class="desc">
{{ t('AwardApply.clickToUploadPdf') }}
</p>
<p class="limit">
{{ t('AwardApply.pdfFileLimit') }}
</p>
<template #itemRender="{ file, actions }">
<div
class="custom-upload-list flex align-center space-between"
@@ -258,7 +272,9 @@
alt=""
class="upload-icon"
/>
<p class="desc">{{ t('AwardApply.clickToUploadVideo') }}</p>
<p class="desc">
{{ t('AwardApply.clickToUploadVideo') }}
</p>
<p class="limit">
{{ t('AwardApply.videoFileLimit') }}
</p>
@@ -308,38 +324,40 @@
</a-form-item>
</div>
</a-form>
<div class="conditions">
<div class="confitions-title poppins-bold">{{ t('AwardApply.termsAndConditions') }}</div>
<div class="condition-list flex flex-col">
<div
class="condition-item flex align-center"
v-for="item in conditionsList"
:key="item.id"
>
<a-checkbox v-model:checked="item.check" />
<span>
{{ t('AwardApply.' + item.translationKey) }}
<span
class="required"
v-if="item.required"
>
*
<div class="conditions">
<div class="confitions-title poppins-bold">
{{ t('AwardApply.termsAndConditions') }}
</div>
<div class="condition-list flex flex-col">
<div
class="condition-item flex align-center"
v-for="item in conditionsList"
:key="item.id"
>
<a-checkbox v-model:checked="item.check" />
<span>
{{ t('AwardApply.' + item.translationKey) }}
<span
class="required"
v-if="item.required"
>
*
</span>
</span>
</span>
</div>
</div>
</div>
</div>
<div class="submit-container">
<div
class="submit-btn poppins-bold"
@click="handleSubmitForm"
>
{{ t('AwardApply.submitYourDesign') }}
<div class="submit-container">
<div
class="submit-btn poppins-bold"
@click="handleSubmitForm"
>
{{ t('AwardApply.submitYourDesign') }}
</div>
<div class="desc">
{{ t('AwardApply.unfinishedFormTip') }}
</div>
</div>
<div class="desc">
{{ t('AwardApply.unfinishedFormTip') }}
</div>
</div>
</div>
</div>
<a-modal
@@ -359,7 +377,11 @@
@click="handleCloseModal"
/>
<div class="title poppins-bold">{{ t('AwardApply.checkYourEmail') }}</div>
<div class="desc">{{ t('AwardApply.enterSixDigitCode') }} {{ form.email }}</div>
<div class="desc">
{{ t('AwardApply.enterSixDigitCode') }}
<br />
<span class="email-verify">{{ form.email }}</span>
</div>
<div class="code-box">
<VerifycationCodeInput
:ct="emailCode"
@@ -379,7 +401,9 @@
>
{{
isCountingDown
? `${t('AwardApply.resendCodeIn')} ${formatCountdown(countdown)}`
? `${t('AwardApply.resendCodeIn')} ${formatCountdown(
countdown
)}`
: t('AwardApply.resendCode')
}}
</div>
@@ -436,6 +460,7 @@
designDescription: '',
pdfPath: '',
videoPath: '',
videoDuration: 0,
secureToken: ''
})
const hasValidEmail = computed(() => {
@@ -493,18 +518,36 @@
const rulesRef = {
email: [{ required: true, validator: validEmail }],
firstName: [
{ required: true, message: t('AwardApply.pleaseInputFirstName'), trigger: 'blur' }
{
required: true,
message: t('AwardApply.pleaseInputFirstName'),
trigger: 'blur'
}
],
lastName: [
{ required: true, message: t('AwardApply.pleaseInputLastName'), trigger: 'blur' }
{
required: true,
message: t('AwardApply.pleaseInputLastName'),
trigger: 'blur'
}
],
gender: [
{ required: true, message: t('AwardApply.pleaseSelectGender'), trigger: 'blur' }
{
required: true,
message: t('AwardApply.pleaseSelectGender'),
trigger: 'blur'
}
],
occupation: [
{ required: true, message: t('AwardApply.pleaseInputOccupation'), trigger: 'blur' }
{
required: true,
message: t('AwardApply.pleaseInputOccupation'),
trigger: 'blur'
}
],
age: [
{ required: true, message: t('AwardApply.pleaseInputAge'), trigger: 'blur' }
],
age: [{ required: true, message: t('AwardApply.pleaseInputAge'), trigger: 'blur' }],
countryRegionCity: [
{
required: true,
@@ -515,7 +558,11 @@
phoneNumber: [{ required: true, validator: validatePhone, trigger: 'blur' }],
designTitle: [
{ required: true, message: t('AwardApply.pleaseInputDesignTitle'), trigger: 'blur' }
{
required: true,
message: t('AwardApply.pleaseInputDesignTitle'),
trigger: 'blur'
}
],
designDescription: [
{
@@ -524,9 +571,15 @@
trigger: 'blur'
}
],
pdfPath: [{ required: true, message: t('AwardApply.pleaseUploadPdf'), trigger: 'null' }],
pdfPath: [
{ required: true, message: t('AwardApply.pleaseUploadPdf'), trigger: 'null' }
],
videoPath: [
{ required: true, message: t('AwardApply.pleaseUploadVideo'), trigger: 'null' }
{
required: true,
message: t('AwardApply.pleaseUploadVideo'),
trigger: 'null'
}
]
}
@@ -760,7 +813,24 @@
}
// 统一的文件上传前验证
const beforeUploadFile = (type: FileType, file: File) => {
// 获取视频时长
const getVideoDuration = (file: File): Promise<number> => {
return new Promise((resolve, reject) => {
const video = document.createElement('video')
video.preload = 'metadata'
video.onloadedmetadata = () => {
window.URL.revokeObjectURL(video.src)
resolve(video.duration)
}
video.onerror = () => {
window.URL.revokeObjectURL(video.src)
reject(new Error('Failed to load video'))
}
video.src = window.URL.createObjectURL(file)
})
}
const beforeUploadFile = async (type: FileType, file: File) => {
if (!hasValidEmail.value) {
message.error(t('AwardApply.pleaseVerifyEmailFirst'))
return Upload.LIST_IGNORE
@@ -792,42 +862,33 @@
if (!isValidType) {
message.error(errorMessage)
// 从文件列表中移除
// if (type === 'pdf') {
// const index = pdfList.value.findIndex(item => item.uid === file.uid)
// if (index > -1) {
// pdfList.value.splice(index, 1)
// }
// } else {
// const index = videoList.value.findIndex(item => item.uid === file.uid)
// if (index > -1) {
// videoList.value.splice(index, 1)
// }
// }
return Upload.LIST_IGNORE
}
// 验证文件大小
if (file.size > maxSize) {
const sizeLimit = type === 'pdf' ? '20MB' : '100MB'
message.error(
t('AwardApply.fileSizeExceeds', { sizeLimit })
)
// 从文件列表中移除
// if (type === 'pdf') {
// const index = pdfList.value.findIndex(item => item.uid === file.uid)
// if (index > -1) {
// pdfList.value.splice(index, 1)
// }
// } else {
// const index = videoList.value.findIndex(item => item.uid === file.uid)
// if (index > -1) {
// videoList.value.splice(index, 1)
// }
// }
message.error(t('AwardApply.fileSizeExceeds', { sizeLimit }))
return Upload.LIST_IGNORE
}
// 验证视频时长
let duration = 0
if (type === 'video') {
duration = await getVideoDuration(file)
try {
if (duration > 60) {
message.error(t('AwardApply.videoDurationExceeds'))
return Upload.LIST_IGNORE
}
} catch (error) {
console.error('Failed to get video duration:', error)
}
}
form.value.videoDuration = Math.ceil(duration)
return true
}
@@ -933,7 +994,9 @@
const status = info.file.status
if (status === 'done') {
message.success(t('AwardApply.fileUploadedSuccess', { fileName: info.file.name }))
message.success(
t('AwardApply.fileUploadedSuccess', { fileName: info.file.name })
)
if (type === 'pdf') {
isUploadingPdf.value = false
uploadProgressPdf.value = 0
@@ -957,9 +1020,9 @@
}
}
// 统一的上传处理函数
const handleUploadFile = async (option: any, type: FileType) => {
const file = option.file as File
//
if (!form.value.email) {
message.error(t('AwardApply.pleaseInputEmail'))
@@ -1247,7 +1310,7 @@
}
}
// :deep(.ant-select-arrow) {
// justify-content: center;
// display: flex;
// align-items: center;
@@ -1552,6 +1615,13 @@
font-size: 1.6rem;
line-height: 3.4rem;
margin-top: 1.4rem;
text-align: center;
.email-verify {
color: #232323;
font-family: 'ArialBold';
font-weight: 700;
font-size: 1.6rem;
}
}
.email {

View File

@@ -202,6 +202,9 @@ onBeforeUnmount(() => {
column-gap: 23.22rem;
row-gap: 8rem;
padding: 0 25rem 0 26.6rem;
div{
text-align: center;
}
.judgement-item {
overflow: hidden;
.picture {

View File

@@ -52,6 +52,13 @@
const { t } = useI18n()
const props = defineProps({
isZh: {
type: Boolean,
default: false
}
})
const prizes = [
{
money: 'AwardsPage.grandMoney',
@@ -83,11 +90,8 @@
{
money: 'AwardsPage.awardCertification',
name: 'AwardsPage.finalists',
desc: [
'AwardsPage.TravelAllowance',
'AwardsPage.globalMediaExposure'
],
smaller: true
desc: ['AwardsPage.TravelAllowance', 'AwardsPage.globalMediaExposure'],
smaller: !props.isZh
}
]

View File

@@ -83,12 +83,12 @@
class="close-icon"
@click="handleCloseQRcode"
/>
<div class="code-title">WeChat Official Account</div>
<div class="code-title">{{ $t('AwardsPage.wechatTitle') }}</div>
<img
src="@/assets/images/award/qrcode.jpg"
class="qrcode"
/>
<div class="tips">Scan the QR code in WeChat</div>
<div class="tips">{{ $t('AwardsPage.wechatDesc') }}</div>
</div>
</div>
</div>

View File

@@ -1,8 +1,11 @@
<template>
<div class="award-page">
<div
class="award-page"
:class="{ 'is-zh': isZh }"
>
<div class="banner">
<video
src="@/assets/images/award/banner.mp4"
:src="bannerUrl"
autoplay
muted
loop
@@ -11,32 +14,33 @@
webkit-playsinline
x5-playsinline
></video>
<div
class="submit-btn flex flex-center"
@click="handleSubmitApplication"
>
<div>{{ $t('AwardsPage.submitApplication') }}</div>
<img
src="@/assets/images/award/arrow_right.png"
alt=""
class="arrow"
/>
<div class="ddl">{{ $t('AwardsPage.applicationDeadline') }}</div>
</div>
<div
class="submit-btn flex flex-center"
@click="handleSubmitApplication"
>
<div>{{ $t('AwardsPage.submitApplication') }}</div>
<img
src="@/assets/images/award/arrow_right.png"
alt=""
class="arrow"
/>
<div class="ddl">{{ $t('AwardsPage.applicationDeadline') }}</div>
</div>
</div>
<Slogan />
<Bloom />
<TimeLine />
<JudgesSection />
<PrizesSection />
<PrizesSection :is-zh="isZh" />
<ApplySection />
<SelectionSection />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ref, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import JudgesSection from './components/JudgesSection.vue'
import SelectionSection from './components/SelectionSection.vue'
@@ -46,7 +50,19 @@
import Bloom from './components/Bloom.vue'
import Slogan from './components/Slogan.vue'
import banner from '@/assets/images/award/banner.mp4'
import bannerZh from '@/assets/images/award/banner_chinese.mp4'
const router = useRouter()
const { locale } = useI18n()
const isZh = computed(() => {
return locale.value === 'CHINESE_SIMPLIFIED'
})
const bannerUrl = computed(() => {
return isZh.value ? bannerZh : banner
})
const handleSubmitApplication = () => {
router.push('/award/contestants')
@@ -110,4 +126,18 @@
}
}
}
.is-zh {
.submit-btn {
padding: 0 7.5rem;
height: 7.8rem;
border-radius: 7.74rem;
column-gap: 3.8rem;
// justify-content: space-between;
&,
.ddl {
width: 35.4rem;
}
}
}
</style>