diff --git a/src/app.js b/src/app.js
index 776d58c..6165b9b 100644
--- a/src/app.js
+++ b/src/app.js
@@ -2,6 +2,7 @@ import { LessonEngine } from "./impl/LessonEngine.js";
import { CodeEditor } from "./impl/CodeEditor.js";
import { renderLesson, renderModuleList, renderLevelIndicator, updateActiveLessonInSidebar } from "./helpers/renderer.js";
import { loadModules } from "./config/lessons.js";
+import { initI18n, t, getLanguage, setLanguage, applyTranslations } from "./i18n.js";
// Simplified state - LessonEngine now manages lesson state and progress
const state = {
@@ -15,6 +16,7 @@ const state = {
const elements = {
// Header
menuBtn: document.getElementById("menu-btn"),
+ langBtn: document.getElementById("lang-btn"),
helpBtn: document.getElementById("help-btn"),
// Left panel
@@ -100,15 +102,30 @@ function toggleExpectedResult() {
if (state.showExpected) {
elements.expectedOverlay.classList.add("visible");
- elements.showExpectedBtn.textContent = "Hide Expected";
+ elements.showExpectedBtn.textContent = t("hideExpected");
elements.showExpectedBtn.classList.add("btn-primary");
} else {
elements.expectedOverlay.classList.remove("visible");
- elements.showExpectedBtn.textContent = "Show Expected";
+ elements.showExpectedBtn.textContent = t("showExpected");
elements.showExpectedBtn.classList.remove("btn-primary");
}
}
+// ================= LANGUAGE TOGGLE =================
+
+function toggleLanguage() {
+ const currentLang = getLanguage();
+ const newLang = currentLang === "en" ? "de" : "en";
+ setLanguage(newLang);
+ applyTranslations();
+ updateProgressDisplay();
+ // Reload current lesson to update any dynamic text
+ const engineState = lessonEngine.getCurrentState();
+ if (engineState.lesson) {
+ loadCurrentLesson();
+ }
+}
+
// ================= HINT SYSTEM =================
function showHint(message, step, total, isSuccess = false) {
@@ -139,7 +156,11 @@ function showSuccessHint(message) {
function updateProgressDisplay() {
const stats = lessonEngine.getProgressStats();
elements.progressFill.style.width = `${stats.percentComplete}%`;
- elements.progressText.textContent = `${stats.percentComplete}% Complete (${stats.totalCompleted}/${stats.totalLessons})`;
+ elements.progressText.textContent = t("progressText", {
+ percent: stats.percentComplete,
+ completed: stats.totalCompleted,
+ total: stats.totalLessons
+ });
}
// ================= USER SETTINGS =================
@@ -184,7 +205,7 @@ async function initializeModules() {
updateProgressDisplay();
} catch (error) {
console.error("Failed to load modules:", error);
- elements.lessonDescription.textContent = "Failed to load modules. Please refresh the page.";
+ elements.lessonDescription.textContent = t("failedToLoad");
}
}
@@ -248,7 +269,7 @@ function updateEditorForMode(mode) {
cmMode: "html"
},
tailwind: {
- placeholder: "Enter Tailwind classes (e.g., bg-blue-500 text-white p-4)",
+ placeholder: t("tailwindPlaceholder"),
label: "Tailwind Classes",
cmMode: "css"
},
@@ -318,17 +339,17 @@ function loadCurrentLesson() {
// Update Run button text based on completion status
if (engineState.isCompleted) {
- elements.runBtn.innerHTML = '
Re-run';
+ elements.runBtn.querySelector("span").textContent = t("rerun");
// Add completion badge if not present
if (!document.querySelector(".completion-badge")) {
const badge = document.createElement("span");
badge.className = "completion-badge";
- badge.textContent = "Completed";
+ badge.textContent = t("completed");
elements.lessonTitle.appendChild(badge);
}
} else {
- elements.runBtn.innerHTML = '
Run';
+ elements.runBtn.querySelector("span").textContent = t("run");
// Remove completion badge if exists
const badge = document.querySelector(".completion-badge");
@@ -448,17 +469,17 @@ function runCode() {
if (validationResult.isValid) {
// Show success hint
- showSuccessHint(validationResult.message || "CRISPY! ٩(◕‿◕)۶ Your code works correctly.");
+ showSuccessHint(validationResult.message || t("successMessage"));
// Update Run button
- elements.runBtn.innerHTML = '
Re-run';
+ elements.runBtn.querySelector("span").textContent = t("rerun");
elements.runBtn.classList.add("success");
// Add completion badge
if (!document.querySelector(".completion-badge")) {
const badge = document.createElement("span");
badge.className = "completion-badge";
- badge.textContent = "Completed";
+ badge.textContent = t("completed");
elements.lessonTitle.appendChild(badge);
}
@@ -486,7 +507,7 @@ function runCode() {
// Only show hints if enabled
if (!state.userSettings.disableFeedbackErrors) {
- showHint(validationResult.message || "Keep trying!", step, total);
+ showHint(validationResult.message || t("keepTrying"), step, total);
}
}
}
@@ -546,6 +567,9 @@ function initCodeEditor() {
}
function init() {
+ // Initialize i18n before anything else
+ initI18n();
+
loadUserSettings();
// Initialize CodeMirror editor
@@ -559,6 +583,9 @@ function init() {
elements.closeSidebar.addEventListener("click", closeSidebar);
elements.sidebarBackdrop.addEventListener("click", closeSidebar);
+ // Language toggle
+ elements.langBtn.addEventListener("click", toggleLanguage);
+
// Expected result toggle
elements.showExpectedBtn.addEventListener("click", toggleExpectedResult);