fix(i18n): show current language and add RTL support for Arabic
- Language switcher now shows current language code (EN, DE, PL, etc.) - Add RTL layout support for Arabic (dir="rtl" on html element) - Sidebar slides from right in RTL mode - Flip horizontal layouts, navigation, and text alignment for RTL
This commit is contained in:
30
src/i18n.js
30
src/i18n.js
@@ -10,8 +10,8 @@ const translations = {
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
menuOpen: "Open menu",
|
menuOpen: "Open menu",
|
||||||
langSwitch: "DE",
|
langSwitch: "EN",
|
||||||
langSwitchLabel: "Switch language: Deutsch",
|
langSwitchLabel: "Switch language",
|
||||||
help: "Help",
|
help: "Help",
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
@@ -109,8 +109,8 @@ const translations = {
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
menuOpen: "Menü öffnen",
|
menuOpen: "Menü öffnen",
|
||||||
langSwitch: "PL",
|
langSwitch: "DE",
|
||||||
langSwitchLabel: "Zmień język: Polski",
|
langSwitchLabel: "Sprache wechseln",
|
||||||
help: "Hilfe",
|
help: "Hilfe",
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
@@ -209,8 +209,8 @@ const translations = {
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
menuOpen: "Otwórz menu",
|
menuOpen: "Otwórz menu",
|
||||||
langSwitch: "ES",
|
langSwitch: "PL",
|
||||||
langSwitchLabel: "Cambiar idioma: Español",
|
langSwitchLabel: "Zmień język",
|
||||||
help: "Pomoc",
|
help: "Pomoc",
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
@@ -309,8 +309,8 @@ const translations = {
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
menuOpen: "Abrir menú",
|
menuOpen: "Abrir menú",
|
||||||
langSwitch: "AR",
|
langSwitch: "ES",
|
||||||
langSwitchLabel: "تغيير اللغة: العربية",
|
langSwitchLabel: "Cambiar idioma",
|
||||||
help: "Ayuda",
|
help: "Ayuda",
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
@@ -409,8 +409,8 @@ const translations = {
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
menuOpen: "افتح القائمة",
|
menuOpen: "افتح القائمة",
|
||||||
langSwitch: "UK",
|
langSwitch: "AR",
|
||||||
langSwitchLabel: "Змінити мову: Українська",
|
langSwitchLabel: "تغيير اللغة",
|
||||||
help: "مساعدة",
|
help: "مساعدة",
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
@@ -509,8 +509,8 @@ const translations = {
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
menuOpen: "Відкрити меню",
|
menuOpen: "Відкрити меню",
|
||||||
langSwitch: "EN",
|
langSwitch: "UK",
|
||||||
langSwitchLabel: "Switch language: English",
|
langSwitchLabel: "Змінити мову",
|
||||||
help: "Допомога",
|
help: "Допомога",
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
@@ -654,6 +654,9 @@ export function getLanguage() {
|
|||||||
/**
|
/**
|
||||||
* Set language and persist to localStorage
|
* Set language and persist to localStorage
|
||||||
*/
|
*/
|
||||||
|
// RTL languages
|
||||||
|
const rtlLanguages = ["ar"];
|
||||||
|
|
||||||
export function setLanguage(lang) {
|
export function setLanguage(lang) {
|
||||||
if (!translations[lang]) {
|
if (!translations[lang]) {
|
||||||
console.warn(`Language "${lang}" not supported, falling back to English`);
|
console.warn(`Language "${lang}" not supported, falling back to English`);
|
||||||
@@ -662,6 +665,9 @@ export function setLanguage(lang) {
|
|||||||
currentLang = lang;
|
currentLang = lang;
|
||||||
localStorage.setItem("codeCrispies.language", lang);
|
localStorage.setItem("codeCrispies.language", lang);
|
||||||
document.documentElement.lang = lang;
|
document.documentElement.lang = lang;
|
||||||
|
|
||||||
|
// Set text direction for RTL languages
|
||||||
|
document.documentElement.dir = rtlLanguages.includes(lang) ? "rtl" : "ltr";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
68
src/main.css
68
src/main.css
@@ -1307,3 +1307,71 @@ input:checked + .toggle-slider::before {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ================== RTL SUPPORT ================== */
|
||||||
|
|
||||||
|
/* RTL: Sidebar slides from right */
|
||||||
|
[dir="rtl"] .sidebar-drawer {
|
||||||
|
left: auto;
|
||||||
|
right: calc(-1 * var(--sidebar-width));
|
||||||
|
transition: right 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .sidebar-drawer.open {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Content shifts to left when sidebar opens */
|
||||||
|
[dir="rtl"] .app-container:has(.sidebar-drawer.open) .game-layout {
|
||||||
|
transform: translateX(calc(-1 * var(--sidebar-width) * 0.8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Flip horizontal layouts */
|
||||||
|
[dir="rtl"] .header-left,
|
||||||
|
[dir="rtl"] .header-right {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Editor tools */
|
||||||
|
[dir="rtl"] .editor-tools {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Navigation buttons */
|
||||||
|
[dir="rtl"] .nav-controls {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Hint layout */
|
||||||
|
[dir="rtl"] .hint {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Module list items */
|
||||||
|
[dir="rtl"] .module-header {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .lesson-list button {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Lesson progress indicator */
|
||||||
|
[dir="rtl"] .lesson-list button::before {
|
||||||
|
margin-left: var(--spacing-sm);
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Text alignment */
|
||||||
|
[dir="rtl"] .lesson-description,
|
||||||
|
[dir="rtl"] .task-instruction,
|
||||||
|
[dir="rtl"] #lesson-title {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL: Dialog close button */
|
||||||
|
[dir="rtl"] .dialog-close {
|
||||||
|
left: var(--spacing-sm);
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user