refactor: move language picker to sidebar as dropdown
- Remove language button from header - Add language select dropdown in sidebar settings - Add translations for "Language" label in all languages - Remove unused .lang-switch CSS
This commit is contained in:
14
src/app.js
14
src/app.js
@@ -2,7 +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, getNextLanguage, applyTranslations } from "./i18n.js";
|
||||
import { initI18n, t, getLanguage, setLanguage, applyTranslations } from "./i18n.js";
|
||||
|
||||
// Simplified state - LessonEngine now manages lesson state and progress
|
||||
const state = {
|
||||
@@ -17,7 +17,7 @@ const elements = {
|
||||
// Header
|
||||
menuBtn: document.getElementById("menu-btn"),
|
||||
logoLink: document.getElementById("logo-link"),
|
||||
langBtn: document.getElementById("lang-btn"),
|
||||
langSelect: document.getElementById("lang-select"),
|
||||
helpBtn: document.getElementById("help-btn"),
|
||||
|
||||
// Left panel
|
||||
@@ -117,10 +117,7 @@ function toggleExpectedResult() {
|
||||
|
||||
// ================= LANGUAGE TOGGLE =================
|
||||
|
||||
function toggleLanguage() {
|
||||
const currentLang = getLanguage();
|
||||
const newLang = getNextLanguage(currentLang);
|
||||
|
||||
function changeLanguage(newLang) {
|
||||
// Add transition class before any updates
|
||||
elements.editorSection?.classList.add("transitioning");
|
||||
|
||||
@@ -730,8 +727,9 @@ function init() {
|
||||
loadCurrentLesson();
|
||||
});
|
||||
|
||||
// Language toggle
|
||||
elements.langBtn.addEventListener("click", toggleLanguage);
|
||||
// Language select
|
||||
elements.langSelect.value = getLanguage();
|
||||
elements.langSelect.addEventListener("change", (e) => changeLanguage(e.target.value));
|
||||
|
||||
// Expected result toggle
|
||||
elements.showExpectedBtn.addEventListener("click", toggleExpectedResult);
|
||||
|
||||
@@ -36,6 +36,7 @@ const translations = {
|
||||
// Sidebar
|
||||
menu: "Menu",
|
||||
closeMenu: "Close menu",
|
||||
language: "Language",
|
||||
progress: "Progress",
|
||||
progressText: "{percent}% Complete ({completed}/{total})",
|
||||
lessons: "Lessons",
|
||||
@@ -135,6 +136,7 @@ const translations = {
|
||||
// Sidebar
|
||||
menu: "Menü",
|
||||
closeMenu: "Menü schließen",
|
||||
language: "Sprache",
|
||||
progress: "Fortschritt",
|
||||
progressText: "{percent}% abgeschlossen ({completed}/{total})",
|
||||
lessons: "Lektionen",
|
||||
@@ -235,6 +237,7 @@ const translations = {
|
||||
// Sidebar
|
||||
menu: "Menu",
|
||||
closeMenu: "Zamknij menu",
|
||||
language: "Język",
|
||||
progress: "Postęp",
|
||||
progressText: "{percent}% ukończone ({completed}/{total})",
|
||||
lessons: "Lekcje",
|
||||
@@ -335,6 +338,7 @@ const translations = {
|
||||
// Sidebar
|
||||
menu: "Menú",
|
||||
closeMenu: "Cerrar menú",
|
||||
language: "Idioma",
|
||||
progress: "Progreso",
|
||||
progressText: "{percent}% completado ({completed}/{total})",
|
||||
lessons: "Lecciones",
|
||||
@@ -435,6 +439,7 @@ const translations = {
|
||||
// Sidebar
|
||||
menu: "القائمة",
|
||||
closeMenu: "إغلاق القائمة",
|
||||
language: "اللغة",
|
||||
progress: "التقدم",
|
||||
progressText: "{percent}% مكتمل ({completed}/{total})",
|
||||
lessons: "الدروس",
|
||||
@@ -535,6 +540,7 @@ const translations = {
|
||||
// Sidebar
|
||||
menu: "Меню",
|
||||
closeMenu: "Закрити меню",
|
||||
language: "Мова",
|
||||
progress: "Прогрес",
|
||||
progressText: "{percent}% завершено ({completed}/{total})",
|
||||
lessons: "Уроки",
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<h1><span class="code-text">CODE</span><span>CRISPIES</span></h1>
|
||||
</a>
|
||||
<div class="header-actions">
|
||||
<button id="lang-btn" class="lang-switch" data-i18n-aria-label="langSwitchLabel" data-i18n="langSwitch" aria-label="Sprache wechseln: Deutsch">DE</button>
|
||||
<button id="help-btn" class="help-toggle" data-i18n-aria-label="help" aria-label="Help">?</button>
|
||||
</div>
|
||||
</header>
|
||||
@@ -109,6 +108,17 @@
|
||||
|
||||
<div class="sidebar-section">
|
||||
<h4 data-i18n="settings">Settings</h4>
|
||||
<label class="setting-row">
|
||||
<span class="setting-label" data-i18n="language">Language</span>
|
||||
<select id="lang-select" class="lang-select">
|
||||
<option value="en">English</option>
|
||||
<option value="de">Deutsch</option>
|
||||
<option value="pl">Polski</option>
|
||||
<option value="es">Español</option>
|
||||
<option value="ar">العربية</option>
|
||||
<option value="uk">Українська</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="disable-feedback-toggle" checked />
|
||||
<span class="toggle-slider"></span>
|
||||
|
||||
57
src/main.css
57
src/main.css
@@ -220,28 +220,6 @@ code, kbd {
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.lang-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--border-color);
|
||||
background: none;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
color: var(--light-text);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.lang-switch:hover {
|
||||
border-color: var(--primary-color);
|
||||
color: var(--primary-color);
|
||||
background: var(--primary-bg-light);
|
||||
}
|
||||
|
||||
/* ================= GAME LAYOUT ================= */
|
||||
.game-layout {
|
||||
display: flex;
|
||||
@@ -991,6 +969,41 @@ button.lesson-list-item {
|
||||
}
|
||||
|
||||
/* ================= TOGGLE SWITCH ================= */
|
||||
/* Setting row (for label + control) */
|
||||
.setting-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
/* Language select */
|
||||
.lang-select {
|
||||
padding: 6px 10px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--panel-bg);
|
||||
color: var(--text-color);
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.lang-select:hover {
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.lang-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user