feat: add cloudOnboarding translations for all supported languages (#5578)

* feat: add missing translations for cloud onboarding components

Replaces hardcoded text with i18n translations across cloud onboarding flow:

- CloudWaitlistView: Add translations for title lines, questions text, and contact link
- CloudClaimInviteView: Add translations for processing title and claim button
- CloudSorryContactSupportView: Add translation for error title
- CloudVerifyEmailView: Add translation for verification title
- CloudTemplateFooter: Add translation for "Need Help?" link
- CloudLoginView: Replace hardcoded "Questions? Contact us" and "here" with translations
- CloudSignupView: Replace hardcoded "Questions? Contact us" and "here" with translations
- CloudForgotPasswordView: Replace hardcoded "here" with translation
- Remove all eslint-disable @intlify/vue-i18n/no-raw-text comments
- Add proper useI18n imports to all affected components

Ensures consistent internationalization support across the entire cloud onboarding experience.

* feat: add cloudOnboarding translations for all supported languages

Adds comprehensive translations for cloud onboarding components across all supported locales:

English (en): Base translations for waitlist, claim invite, verify email, and support
Chinese Simplified (zh): 等候名单, 邀请码处理, 邮箱验证, 联系支持
Chinese Traditional (zh-TW): 等候名單, 邀請碼處理, 郵箱驗證, 聯繫支援
Japanese (ja): ウェイトリスト, 招待コード処理, メール認証, サポート連絡
Korean (ko): 대기명단, 초대코드 처리, 이메일 인증, 지원 문의
Russian (ru): Список ожидания, обработка кода приглашения, подтверждение почты
French (fr): Liste d'attente, traitement code invitation, vérification email
Spanish (es): Lista de espera, procesamiento código invitación, verificación email
Arabic (ar): قائمة الانتظار, معالجة رمز الدعوة, التحقق من البريد

Ensures consistent internationalization across the entire cloud onboarding experience for global users.

* feat: add missing privateBeta and start section translations

Adds translations for previously missing cloud onboarding text that was already using translation keys:

- privateBeta.title: "Cloud is currently in private beta" message
- privateBeta.desc: Beta signup description text
- start.title: "Start creating in seconds" header
- start.desc: "Zero setup required" subtext
- start.explain: Multiple output generation description
- start.learnAboutButton: "Learn about Cloud" button text
- start.wantToRun: Local ComfyUI option text
- start.download: "Download ComfyUI" button text

All 9 languages updated:
- Traditional Chinese: 私人測試階段, 幾秒內開始創作, 了解 Cloud
- Simplified Chinese: 私人测试阶段, 几秒内开始创作, 了解 Cloud
- Japanese: プライベートベータ版, 数秒で創作を開始, Cloudについて学ぶ
- Korean: 비공개 베타 버전, 몇 초 만에 창작 시작, Cloud에 대해 알아보기
- Russian: закрытая бета-версия, начните создавать за секунды, Узнать о Cloud
- French: bêta privée, commencez à créer en quelques secondes, En savoir plus sur Cloud
- Spanish: beta privada, comienza a crear en segundos, Aprende sobre Cloud
- Arabic: البيتا الخاصة, ابدأ الإبداع في ثوان, تعلم عن Cloud

Fixes missing translations reported during Traditional Chinese testing.

* feat: restore French translation file and add cloudOnboarding translations

- Restored src/locales/fr/main.json from clean backup to remove duplicate sections
- Added complete French translations for cloudOnboarding section
- Includes survey, waitlist, forgotPassword, privateBeta, start, and other subsections
- Structure matches English version exactly

* [feat] Refactor cloud translations to top-level keys

- Replace nested cloudOnboarding.section.key structure with flattened cloudSection_key pattern
- Add comprehensive cloud translations for all 9 supported languages (ar, en, es, fr, ja, ko, ru, zh, zh-TW)
- Update all Vue components to use new translation key structure
- Fix "Need Help?" and other missing translations across all languages
- Simplify translation maintenance and avoid JSON structure conflicts

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Christian Byrne
2025-09-15 00:16:55 -07:00
committed by GitHub
parent 18b3b11b9a
commit 7c9b8bb7a6
19 changed files with 360 additions and 65 deletions

View File

@@ -1,21 +1,24 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<div
class="flex flex-col justify-center items-center h-screen font-mono text-black gap-4"
>
<h1 class="text-2xl">Processing Invite Code...</h1>
<h1 class="text-2xl">
{{ t('cloudClaimInvite_processingTitle') }}
</h1>
<button
class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 cursor-pointer"
@click="onClaim"
>
Claim Invite
{{ t('cloudClaimInvite_claimButton') }}
</button>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
const { t } = useI18n()
const router = useRouter()
const onClaim = () => {

View File

@@ -1,14 +1,13 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<div class="h-full flex items-center justify-center p-8">
<div class="w-96 p-2">
<!-- Header -->
<div class="flex flex-col gap-4 mb-8">
<h1 class="text-xl font-medium leading-normal my-0">
{{ t('cloudOnboarding.forgotPassword.title') }}
{{ t('cloudForgotPassword_title') }}
</h1>
<p class="text-base my-0 text-muted">
{{ t('cloudOnboarding.forgotPassword.instructions') }}
{{ t('cloudForgotPassword_instructions') }}
</p>
</div>
@@ -19,13 +18,13 @@
class="opacity-80 text-base font-medium mb-2"
for="reset-email"
>
{{ t('cloudOnboarding.forgotPassword.emailLabel') }}
{{ t('cloudForgotPassword_emailLabel') }}
</label>
<InputText
id="reset-email"
v-model="email"
type="email"
:placeholder="t('cloudOnboarding.forgotPassword.emailPlaceholder')"
:placeholder="t('cloudForgotPassword_emailPlaceholder')"
class="h-10"
:invalid="!!errorMessage && !email"
autocomplete="email"
@@ -43,7 +42,7 @@
<div class="flex flex-col gap-4">
<Button
type="submit"
:label="t('cloudOnboarding.forgotPassword.sendResetLink')"
:label="t('cloudForgotPassword_sendResetLink')"
:loading="loading"
:disabled="!email || loading"
class="h-10 font-medium text-white"
@@ -51,7 +50,7 @@
<Button
type="button"
:label="t('cloudOnboarding.forgotPassword.backToLogin')"
:label="t('cloudForgotPassword_backToLogin')"
severity="secondary"
class="h-10 bg-[#2d2e32]"
@click="navigateToLogin"
@@ -61,14 +60,14 @@
<!-- Help text -->
<p class="mt-5 text-sm text-gray-600">
{{ t('cloudOnboarding.forgotPassword.didntReceiveEmail') }}
{{ t('cloudForgotPassword_didntReceiveEmail') }}
<a
href="https://support.comfy.org"
class="text-blue-400 no-underline cursor-pointer"
target="_blank"
rel="noopener noreferrer"
>
here</a
{{ t('cloudWaitlist_contactLink') }}</a
>.
</p>
</div>
@@ -100,7 +99,7 @@ const navigateToLogin = () => {
const handleSubmit = async () => {
if (!email.value) {
errorMessage.value = t('cloudOnboarding.forgotPassword.emailRequired')
errorMessage.value = t('cloudForgotPassword_emailRequired')
return
}
@@ -112,7 +111,7 @@ const handleSubmit = async () => {
// sendPasswordReset is already wrapped and returns a promise
await authActions.sendPasswordReset(email.value)
successMessage.value = t('cloudOnboarding.forgotPassword.passwordResetSent')
successMessage.value = t('cloudForgotPassword_passwordResetSent')
// Optionally redirect to login after a delay
setTimeout(() => {
@@ -120,7 +119,7 @@ const handleSubmit = async () => {
}, 3000)
} catch (error) {
console.error('Password reset error:', error)
errorMessage.value = t('cloudOnboarding.forgotPassword.passwordResetError')
errorMessage.value = t('cloudForgotPassword_passwordResetError')
} finally {
loading.value = false
}

View File

@@ -1,13 +1,12 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<div class="h-full flex items-center justify-center p-8">
<div class="w-96 p-2">
<div class="bg-[#2d2e32] p-4 rounded-lg">
<h4 class="m-0 pb-2 text-lg">
{{ t('cloudOnboarding.privateBeta.title') }}
{{ t('cloudPrivateBeta_title') }}
</h4>
<p class="m-0 text-base leading-6">
{{ t('cloudOnboarding.privateBeta.desc') }}
{{ t('cloudPrivateBeta_desc') }}
</p>
</div>
@@ -63,14 +62,14 @@
<!-- Terms & Contact -->
<p class="mt-5 text-sm text-gray-600">
Questions? Contact us
{{ t('cloudWaitlist_questionsText') }}
<a
href="https://support.comfy.org"
class="text-blue-400 no-underline cursor-pointer"
target="_blank"
rel="noopener noreferrer"
>
here</a
{{ t('cloudWaitlist_contactLink') }}</a
>.
</p>
</div>

View File

@@ -1,4 +1,3 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<div class="h-full flex items-center justify-center p-8">
<div class="w-96 p-2">
@@ -76,14 +75,14 @@
{{ t('auth.login.privacyLink') }} </a
>.
<p class="mt-2">
Questions? Contact us
{{ t('cloudWaitlist_questionsText') }}
<a
href="https://support.comfy.org"
class="text-blue-400 no-underline cursor-pointer"
target="_blank"
rel="noopener noreferrer"
>
here</a
{{ t('cloudWaitlist_contactLink') }}</a
>.
</p>
</div>

View File

@@ -1,10 +1,15 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<div class="cloud-sorry-contact-support">
<h1>Sorry, contact support</h1>
<h1>{{ t('cloudSorryContactSupport_title') }}</h1>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>
<style scoped>
.cloud-sorry-contact-support {
display: flex;

View File

@@ -15,7 +15,7 @@
>
<div>
<label class="text-lg font-medium block mb-8">{{
t('cloudOnboarding.survey.steps.familiarity')
t('cloudSurvey_steps_familiarity')
}}</label>
<div class="flex flex-col gap-6">
<div
@@ -56,7 +56,7 @@
>
<div>
<label class="text-lg font-medium block mb-8">{{
t('cloudOnboarding.survey.steps.purpose')
t('cloudSurvey_steps_purpose')
}}</label>
<div class="flex flex-col gap-6">
<div
@@ -102,7 +102,7 @@
>
<div>
<label class="text-lg font-medium block mb-8">{{
t('cloudOnboarding.survey.steps.industry')
t('cloudSurvey_steps_industry')
}}</label>
<div class="flex flex-col gap-6">
<div
@@ -155,7 +155,7 @@
>
<div>
<label class="text-lg font-medium block mb-8">{{
t('cloudOnboarding.survey.steps.making')
t('cloudSurvey_steps_making')
}}</label>
<div class="flex flex-col gap-6">
<div

View File

@@ -1,16 +1,18 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<div>
<h1>Email Verification</h1>
<h1>{{ t('cloudVerifyEmail_title') }}</h1>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
// import { verifyEmail } from '@/api/auth'
import router from '@/router'
const { t } = useI18n()
onMounted(async () => {
// verifyEmail()
await router.push({ name: 'cloud-invite-check' })

View File

@@ -1,24 +1,23 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<div class="flex flex-col items-center justify-center p-8">
<div class="w-full max-w-md text-center">
<h1 class="text-3xl italic font-bolder mb-8">
YOU'RE ON THE<br />
WAITLIST 🎉
{{ t('cloudWaitlist_titleLine1') }}<br />
{{ t('cloudWaitlist_titleLine2') }}
</h1>
<div class="max-w-[320px] text-lg font-light">
<p class="text-white">
{{ t('cloudOnboarding.waitlist.message') }}
{{ t('cloudWaitlist_message') }}
</p>
<p class="text-white">
Questions? Contact us
{{ t('cloudWaitlist_questionsText') }}
<a
href="https://support.comfy.org"
class="text-blue-400 no-underline cursor-pointer"
target="_blank"
rel="noopener noreferrer"
>
here</a
{{ t('cloudWaitlist_contactLink') }}</a
>.
</p>
</div>

View File

@@ -27,14 +27,16 @@
<!-- Optional Overlay for better visual -->
<div class="absolute inset-0 flex justify-center items-center">
<div>
<h1 class="text-5xl italic font-bolder mb-8 uppercase text-center">
{{ t('cloudOnboarding.start.title') }}
<h1
class="text-5xl italic font-bolder mb-8 uppercase text-center text-white"
>
{{ t('cloudStart_title') }}
</h1>
<p class="m-2 text-xl text-center">
{{ t('cloudOnboarding.start.desc') }}
<p class="m-2 text-xl text-center text-white">
{{ t('cloudStart_desc') }}
</p>
<p class="m-0 text-xl text-center">
{{ t('cloudOnboarding.start.explain') }}
<p class="m-0 text-xl text-center text-white">
{{ t('cloudStart_explain') }}
</p>
</div>
</div>
@@ -46,17 +48,17 @@
severity="secondary"
@click="handleLearnAboutClick"
>
{{ t('cloudOnboarding.start.learnAboutButton') }}
{{ t('cloudStart_learnAboutButton') }}
</Button>
<div class="flex items-center gap-3">
<p>{{ t('cloudOnboarding.start.wantToRun') }}</p>
<p class="text-white">{{ t('cloudStart_wantToRun') }}</p>
<Button
type="button"
class="h-10 bg-black text-white font-bold"
severity="secondary"
@click="handleDownloadClick"
>
{{ t('cloudOnboarding.start.download') }}
{{ t('cloudStart_download') }}
</Button>
</div>
</div>

View File

@@ -1,4 +1,3 @@
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<template>
<footer class="flex gap-2.5 pl-[60px] pb-[60px]">
<a
@@ -21,7 +20,7 @@
target="_blank"
rel="noopener noreferrer"
>
Need Help?
{{ t('cloudFooter_needHelp') }}
</a>
</footer>
</template>