feat(i18n): add landing page localization for 6 languages

- Add translation keys for landing page (hero, benefits, learning paths, CTA)
- Support EN, DE, PL, ES, AR, UK languages
- Add data-i18n attributes to landing page HTML elements
This commit is contained in:
2026-01-15 17:33:58 +01:00
parent 7093a36694
commit 3010b1a902
2 changed files with 160 additions and 25 deletions

View File

@@ -114,7 +114,27 @@ const translations = {
failedToLoad: "Failed to load modules. Please refresh the page.", failedToLoad: "Failed to load modules. Please refresh the page.",
tailwindPlaceholder: "Enter Tailwind classes (e.g., bg-blue-500 text-white p-4)", tailwindPlaceholder: "Enter Tailwind classes (e.g., bg-blue-500 text-white p-4)",
lessonFallback: "Lesson {index}", lessonFallback: "Lesson {index}",
untitledLesson: "Untitled Lesson" untitledLesson: "Untitled Lesson",
// Landing page
landingHeroTitle: "Learn Web Development",
landingHeroHighlight: "By Writing Real Code",
landingHeroSubtitle: "Master HTML, CSS, and Tailwind through hands-on exercises with instant feedback. Free and open source.",
landingCtaStart: "Start Learning NOW",
landingWhyTitle: "Why Code Crispies Works",
landingBenefit1Title: "Learn by Doing",
landingBenefit1Text: "Write real code from lesson one. No videos to watch—just you, an editor, and instant feedback on every keystroke.",
landingBenefit2Title: "Practice at Your Pace",
landingBenefit2Text: "Start with basics, fill gaps in your understanding, then accelerate. Pick up where you left off anytime.",
landingBenefit3Title: "Master Real Skills",
landingBenefit3Text: "Learn CSS, HTML, and Tailwind the way professionals use them—through hands-on exercises and reference guides.",
landingPathsTitle: "Explore Learning Paths",
landingCssDesc: "Styling, layout, and animations",
landingHtmlDesc: "Semantic markup and native elements",
landingTailwindDesc: "Utility-first CSS framework",
landingCtaTitle: "Start Learning Today",
landingCtaSub: "Free and open source. No account required. Progress saved locally.",
landingCtaButton: "Begin Your Journey"
}, },
de: { de: {
@@ -229,7 +249,29 @@ const translations = {
failedToLoad: "Module konnten nicht geladen werden. Bitte Seite neu laden.", failedToLoad: "Module konnten nicht geladen werden. Bitte Seite neu laden.",
tailwindPlaceholder: "Tailwind-Klassen eingeben (z.B. bg-blue-500 text-white p-4)", tailwindPlaceholder: "Tailwind-Klassen eingeben (z.B. bg-blue-500 text-white p-4)",
lessonFallback: "Lektion {index}", lessonFallback: "Lektion {index}",
untitledLesson: "Unbenannte Lektion" untitledLesson: "Unbenannte Lektion",
// Landing page
landingHeroTitle: "Webentwicklung lernen",
landingHeroHighlight: "Durch echten Code",
landingHeroSubtitle: "Meistere HTML, CSS und Tailwind durch praktische Übungen mit sofortigem Feedback. Kostenlos und Open Source.",
landingCtaStart: "Jetzt starten",
landingWhyTitle: "Warum Code Crispies funktioniert",
landingBenefit1Title: "Lernen durch Praxis",
landingBenefit1Text:
"Schreibe echten Code ab der ersten Lektion. Keine Videos nur du, ein Editor und sofortiges Feedback bei jedem Tastendruck.",
landingBenefit2Title: "In deinem Tempo",
landingBenefit2Text:
"Beginne mit den Grundlagen, fülle Wissenslücken und beschleunige dann. Mach jederzeit dort weiter, wo du aufgehört hast.",
landingBenefit3Title: "Echte Fähigkeiten",
landingBenefit3Text: "Lerne CSS, HTML und Tailwind so, wie Profis sie nutzen durch praktische Übungen und Referenzanleitungen.",
landingPathsTitle: "Lernpfade entdecken",
landingCssDesc: "Styling, Layout und Animationen",
landingHtmlDesc: "Semantisches Markup und native Elemente",
landingTailwindDesc: "Utility-first CSS-Framework",
landingCtaTitle: "Heute noch anfangen",
landingCtaSub: "Kostenlos und Open Source. Kein Konto erforderlich. Fortschritt wird lokal gespeichert.",
landingCtaButton: "Starte deine Reise"
}, },
// Polish // Polish
@@ -344,7 +386,29 @@ const translations = {
failedToLoad: "Nie udało się załadować modułów. Odśwież stronę.", failedToLoad: "Nie udało się załadować modułów. Odśwież stronę.",
tailwindPlaceholder: "Wprowadź klasy Tailwind (np. bg-blue-500 text-white p-4)", tailwindPlaceholder: "Wprowadź klasy Tailwind (np. bg-blue-500 text-white p-4)",
lessonFallback: "Lekcja {index}", lessonFallback: "Lekcja {index}",
untitledLesson: "Lekcja bez tytułu" untitledLesson: "Lekcja bez tytułu",
// Landing page
landingHeroTitle: "Naucz się tworzenia stron",
landingHeroHighlight: "Pisząc prawdziwy kod",
landingHeroSubtitle: "Opanuj HTML, CSS i Tailwind poprzez praktyczne ćwiczenia z natychmiastową informacją zwrotną. Darmowe i open source.",
landingCtaStart: "Zacznij TERAZ",
landingWhyTitle: "Dlaczego Code Crispies działa",
landingBenefit1Title: "Ucz się przez praktykę",
landingBenefit1Text:
"Pisz prawdziwy kod od pierwszej lekcji. Żadnych filmów tylko ty, edytor i natychmiastowa informacja zwrotna przy każdym naciśnięciu klawisza.",
landingBenefit2Title: "W swoim tempie",
landingBenefit2Text: "Zacznij od podstaw, uzupełnij luki w wiedzy, a potem przyspiesz. Wróć w dowolnym momencie tam, gdzie skończyłeś.",
landingBenefit3Title: "Prawdziwe umiejętności",
landingBenefit3Text:
"Naucz się CSS, HTML i Tailwind tak, jak używają ich profesjonaliści poprzez praktyczne ćwiczenia i przewodniki referencyjne.",
landingPathsTitle: "Odkryj ścieżki nauki",
landingCssDesc: "Stylowanie, układy i animacje",
landingHtmlDesc: "Semantyczne znaczniki i natywne elementy",
landingTailwindDesc: "Framework CSS oparty na klasach utility",
landingCtaTitle: "Zacznij naukę już dziś",
landingCtaSub: "Darmowe i open source. Bez konta. Postęp zapisywany lokalnie.",
landingCtaButton: "Rozpocznij swoją podróż"
}, },
// Spanish // Spanish
@@ -460,7 +524,30 @@ const translations = {
failedToLoad: "No se pudieron cargar los módulos. Actualiza la página.", failedToLoad: "No se pudieron cargar los módulos. Actualiza la página.",
tailwindPlaceholder: "Ingresa clases de Tailwind (ej. bg-blue-500 text-white p-4)", tailwindPlaceholder: "Ingresa clases de Tailwind (ej. bg-blue-500 text-white p-4)",
lessonFallback: "Lección {index}", lessonFallback: "Lección {index}",
untitledLesson: "Lección sin título" untitledLesson: "Lección sin título",
// Landing page
landingHeroTitle: "Aprende desarrollo web",
landingHeroHighlight: "Escribiendo código real",
landingHeroSubtitle:
"Domina HTML, CSS y Tailwind a través de ejercicios prácticos con retroalimentación instantánea. Gratis y de código abierto.",
landingCtaStart: "Empieza AHORA",
landingWhyTitle: "Por qué funciona Code Crispies",
landingBenefit1Title: "Aprende haciendo",
landingBenefit1Text:
"Escribe código real desde la primera lección. Sin videos que ver—solo tú, un editor y retroalimentación instantánea en cada tecla.",
landingBenefit2Title: "A tu propio ritmo",
landingBenefit2Text:
"Comienza con lo básico, llena los vacíos en tu comprensión y luego acelera. Retoma donde lo dejaste en cualquier momento.",
landingBenefit3Title: "Habilidades reales",
landingBenefit3Text: "Aprende CSS, HTML y Tailwind como los usan los profesionales—a través de ejercicios prácticos y guías de referencia.",
landingPathsTitle: "Explora rutas de aprendizaje",
landingCssDesc: "Estilos, diseño y animaciones",
landingHtmlDesc: "Marcado semántico y elementos nativos",
landingTailwindDesc: "Framework CSS basado en utilidades",
landingCtaTitle: "Empieza a aprender hoy",
landingCtaSub: "Gratis y de código abierto. Sin cuenta requerida. Progreso guardado localmente.",
landingCtaButton: "Comienza tu viaje"
}, },
// Arabic // Arabic
@@ -574,7 +661,27 @@ const translations = {
failedToLoad: "فشل تحميل الوحدات. قم بتحديث الصفحة.", failedToLoad: "فشل تحميل الوحدات. قم بتحديث الصفحة.",
tailwindPlaceholder: "أدخل فئات Tailwind (مثل bg-blue-500 text-white p-4)", tailwindPlaceholder: "أدخل فئات Tailwind (مثل bg-blue-500 text-white p-4)",
lessonFallback: "درس {index}", lessonFallback: "درس {index}",
untitledLesson: "درس بدون عنوان" untitledLesson: "درس بدون عنوان",
// Landing page
landingHeroTitle: "تعلم تطوير الويب",
landingHeroHighlight: "بكتابة كود حقيقي",
landingHeroSubtitle: "أتقن HTML و CSS و Tailwind من خلال تمارين عملية مع ملاحظات فورية. مجاني ومفتوح المصدر.",
landingCtaStart: "ابدأ الآن",
landingWhyTitle: "لماذا Code Crispies فعال",
landingBenefit1Title: "تعلم بالممارسة",
landingBenefit1Text: "اكتب كودًا حقيقيًا من الدرس الأول. لا فيديوهات للمشاهدة—فقط أنت ومحرر وملاحظات فورية مع كل ضغطة مفتاح.",
landingBenefit2Title: "بسرعتك الخاصة",
landingBenefit2Text: "ابدأ بالأساسيات، املأ الفجوات في فهمك، ثم تسارع. استأنف من حيث توقفت في أي وقت.",
landingBenefit3Title: "مهارات حقيقية",
landingBenefit3Text: "تعلم CSS و HTML و Tailwind بالطريقة التي يستخدمها المحترفون—من خلال تمارين عملية وأدلة مرجعية.",
landingPathsTitle: "استكشف مسارات التعلم",
landingCssDesc: "التنسيق والتخطيط والرسوم المتحركة",
landingHtmlDesc: "الترميز الدلالي والعناصر الأصلية",
landingTailwindDesc: "إطار CSS قائم على الأدوات",
landingCtaTitle: "ابدأ التعلم اليوم",
landingCtaSub: "مجاني ومفتوح المصدر. لا حاجة لحساب. يُحفظ التقدم محليًا.",
landingCtaButton: "ابدأ رحلتك"
}, },
// Ukrainian // Ukrainian
@@ -689,7 +796,28 @@ const translations = {
failedToLoad: "Не вдалося завантажити модулі. Оновіть сторінку.", failedToLoad: "Не вдалося завантажити модулі. Оновіть сторінку.",
tailwindPlaceholder: "Введіть класи Tailwind (напр. bg-blue-500 text-white p-4)", tailwindPlaceholder: "Введіть класи Tailwind (напр. bg-blue-500 text-white p-4)",
lessonFallback: "Урок {index}", lessonFallback: "Урок {index}",
untitledLesson: "Урок без назви" untitledLesson: "Урок без назви",
// Landing page
landingHeroTitle: "Вивчай веб-розробку",
landingHeroHighlight: "Пишучи справжній код",
landingHeroSubtitle: "Опануй HTML, CSS та Tailwind через практичні вправи з миттєвим зворотним зв'язком. Безкоштовно та з відкритим кодом.",
landingCtaStart: "Почни ЗАРАЗ",
landingWhyTitle: "Чому Code Crispies працює",
landingBenefit1Title: "Вчись на практиці",
landingBenefit1Text:
"Пиши справжній код з першого уроку. Жодних відео—тільки ти, редактор і миттєвий зворотний зв'язок при кожному натисканні клавіші.",
landingBenefit2Title: "У своєму темпі",
landingBenefit2Text: "Почни з основ, заповни прогалини у розумінні, потім прискорюйся. Продовжуй з того місця, де зупинився, будь-коли.",
landingBenefit3Title: "Реальні навички",
landingBenefit3Text: "Вивчай CSS, HTML та Tailwind так, як їх використовують професіонали—через практичні вправи та довідники.",
landingPathsTitle: "Досліджуй шляхи навчання",
landingCssDesc: "Стилізація, макети та анімації",
landingHtmlDesc: "Семантична розмітка та нативні елементи",
landingTailwindDesc: "CSS-фреймворк на основі утиліт",
landingCtaTitle: "Почни вчитися сьогодні",
landingCtaSub: "Безкоштовно та з відкритим кодом. Без реєстрації. Прогрес зберігається локально.",
landingCtaButton: "Розпочни свою подорож"
} }
}; };

View File

@@ -86,23 +86,29 @@
<div class="landing-content"> <div class="landing-content">
<section class="hero"> <section class="hero">
<img src="./bowl.png" width="120" alt="" class="hero-logo" /> <img src="./bowl.png" width="120" alt="" class="hero-logo" />
<h1>Learn Web Development<br /><span class="hero-highlight">By Writing Real Code</span></h1> <h1>
<p class="hero-subtitle"> <span data-i18n="landingHeroTitle">Learn Web Development</span><br /><span
class="hero-highlight"
data-i18n="landingHeroHighlight"
>By Writing Real Code</span
>
</h1>
<p class="hero-subtitle" data-i18n="landingHeroSubtitle">
Master HTML, CSS, and Tailwind through hands-on exercises with instant feedback. Free and open source. Master HTML, CSS, and Tailwind through hands-on exercises with instant feedback. Free and open source.
</p> </p>
<a href="#welcome/0" class="cta-button cta-primary">Start Learning NOW</a> <a href="#welcome/0" class="cta-button cta-primary" data-i18n="landingCtaStart">Start Learning NOW</a>
</section> </section>
<section class="why-it-works"> <section class="why-it-works">
<h2>Why Code Crispies Works</h2> <h2 data-i18n="landingWhyTitle">Why Code Crispies Works</h2>
<div class="benefits-grid"> <div class="benefits-grid">
<article class="benefit-card"> <article class="benefit-card">
<svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="16 18 22 12 16 6"></polyline> <polyline points="16 18 22 12 16 6"></polyline>
<polyline points="8 6 2 12 8 18"></polyline> <polyline points="8 6 2 12 8 18"></polyline>
</svg> </svg>
<h3>Learn by Doing</h3> <h3 data-i18n="landingBenefit1Title">Learn by Doing</h3>
<p> <p data-i18n="landingBenefit1Text">
Write real code from lesson one. No videos to watch—just you, an editor, and instant feedback on every keystroke. Write real code from lesson one. No videos to watch—just you, an editor, and instant feedback on every keystroke.
</p> </p>
</article> </article>
@@ -110,8 +116,10 @@
<svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 20V10M18 20V4M6 20v-4"></path> <path d="M12 20V10M18 20V4M6 20v-4"></path>
</svg> </svg>
<h3>Practice at Your Pace</h3> <h3 data-i18n="landingBenefit2Title">Practice at Your Pace</h3>
<p>Start with basics, fill gaps in your understanding, then accelerate. Pick up where you left off anytime.</p> <p data-i18n="landingBenefit2Text">
Start with basics, fill gaps in your understanding, then accelerate. Pick up where you left off anytime.
</p>
</article> </article>
<article class="benefit-card"> <article class="benefit-card">
<svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -119,43 +127,42 @@
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
></path> ></path>
</svg> </svg>
<h3>Master Real Skills</h3> <h3 data-i18n="landingBenefit3Title">Master Real Skills</h3>
<p> <p data-i18n="landingBenefit3Text">
Learn CSS, HTML, and Tailwind the way professionals use them—through hands-on exercises and Learn CSS, HTML, and Tailwind the way professionals use them—through hands-on exercises and reference guides.
<a href="#reference/css">reference guides</a>.
</p> </p>
</article> </article>
</div> </div>
</section> </section>
<section class="learning-paths"> <section class="learning-paths">
<h2>Explore Learning Paths</h2> <h2 data-i18n="landingPathsTitle">Explore Learning Paths</h2>
<div class="section-cards" id="section-cards"> <div class="section-cards" id="section-cards">
<a href="#css" class="section-card" data-section="css"> <a href="#css" class="section-card" data-section="css">
<div class="section-card-icon" style="background: #264de4">CSS</div> <div class="section-card-icon" style="background: #264de4">CSS</div>
<h3>CSS</h3> <h3>CSS</h3>
<p>Styling, layout, and animations</p> <p data-i18n="landingCssDesc">Styling, layout, and animations</p>
<span class="section-card-progress" id="css-progress"></span> <span class="section-card-progress" id="css-progress"></span>
</a> </a>
<a href="#html" class="section-card" data-section="html"> <a href="#html" class="section-card" data-section="html">
<div class="section-card-icon" style="background: #e34c26">HTML</div> <div class="section-card-icon" style="background: #e34c26">HTML</div>
<h3>HTML</h3> <h3>HTML</h3>
<p>Semantic markup and native elements</p> <p data-i18n="landingHtmlDesc">Semantic markup and native elements</p>
<span class="section-card-progress" id="html-progress"></span> <span class="section-card-progress" id="html-progress"></span>
</a> </a>
<a href="#tailwind" class="section-card" data-section="tailwind"> <a href="#tailwind" class="section-card" data-section="tailwind">
<div class="section-card-icon" style="background: #06b6d4">TW</div> <div class="section-card-icon" style="background: #06b6d4">TW</div>
<h3>Tailwind CSS</h3> <h3>Tailwind CSS</h3>
<p>Utility-first CSS framework</p> <p data-i18n="landingTailwindDesc">Utility-first CSS framework</p>
<span class="section-card-progress" id="tailwind-progress"></span> <span class="section-card-progress" id="tailwind-progress"></span>
</a> </a>
</div> </div>
</section> </section>
<section class="landing-cta"> <section class="landing-cta">
<h2>Start Learning Today</h2> <h2 data-i18n="landingCtaTitle">Start Learning Today</h2>
<a href="#welcome/0" class="cta-button">Begin Your Journey</a> <a href="#welcome/0" class="cta-button" data-i18n="landingCtaButton">Begin Your Journey</a>
<p class="cta-sub">Free and open source. No account required. Progress saved locally.</p> <p class="cta-sub" data-i18n="landingCtaSub">Free and open source. No account required. Progress saved locally.</p>
</section> </section>
</div> </div>
</div> </div>