Add migration learning platform: Onboarding, Translation, Parent Portal
Phase 1.1 — user_language_api.py: Stores native language preference per user (TR/AR/UK/RU/PL/DE/EN). Onboarding page with flag-based language selection for students and parents. Phase 1.2 — translation_service.py: Batch-translates vocabulary words into target languages via Ollama LLM. Stores in translations JSONB. New endpoint POST /vocabulary/translate triggers translation. Phase 2.1 — Parent Portal (/parent): Simplified UI in parent's native language showing child's learning progress. Daily tips translated. Phase 2.2 — Parent Quiz (/parent/quiz/[unitId]): Parents can quiz their child on vocabulary WITHOUT speaking DE or EN. Shows word in child's learning language + parent's native language as hint. Answer hidden by default, revealed on tap. All UI text translated into 7 languages (DE/EN/TR/AR/UK/RU/PL). Arabic gets RTL layout support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
86
backend-lehrer/user_language_api.py
Normal file
86
backend-lehrer/user_language_api.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""
|
||||
User Language Preferences API — Stores native language + learning level.
|
||||
|
||||
Each user (student, parent, teacher) can set their native language.
|
||||
This drives: UI language, third-language display in flashcards,
|
||||
parent portal language, and translation generation.
|
||||
|
||||
Supported languages: de, en, tr, ar, uk, ru, pl
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/user", tags=["user-language"])
|
||||
|
||||
# Supported native languages with metadata
|
||||
SUPPORTED_LANGUAGES = {
|
||||
"de": {"name": "Deutsch", "name_native": "Deutsch", "flag": "de", "rtl": False},
|
||||
"en": {"name": "English", "name_native": "English", "flag": "gb", "rtl": False},
|
||||
"tr": {"name": "Tuerkisch", "name_native": "Turkce", "flag": "tr", "rtl": False},
|
||||
"ar": {"name": "Arabisch", "name_native": "\u0627\u0644\u0639\u0631\u0628\u064a\u0629", "flag": "sy", "rtl": True},
|
||||
"uk": {"name": "Ukrainisch", "name_native": "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430", "flag": "ua", "rtl": False},
|
||||
"ru": {"name": "Russisch", "name_native": "\u0420\u0443\u0441\u0441\u043a\u0438\u0439", "flag": "ru", "rtl": False},
|
||||
"pl": {"name": "Polnisch", "name_native": "Polski", "flag": "pl", "rtl": False},
|
||||
}
|
||||
|
||||
# In-memory store (will be replaced with DB later)
|
||||
_preferences: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
|
||||
class LanguagePreference(BaseModel):
|
||||
native_language: str # ISO 639-1 code
|
||||
role: str = "student" # student, parent, teacher
|
||||
learning_level: str = "A1" # A1, A2, B1, B2, C1
|
||||
|
||||
|
||||
@router.get("/languages")
|
||||
def get_supported_languages():
|
||||
"""List all supported native languages with metadata."""
|
||||
return {
|
||||
"languages": [
|
||||
{"code": code, **meta}
|
||||
for code, meta in SUPPORTED_LANGUAGES.items()
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@router.get("/language-preference")
|
||||
def get_language_preference(user_id: str = Query("default")):
|
||||
"""Get user's language preference."""
|
||||
pref = _preferences.get(user_id)
|
||||
if not pref:
|
||||
return {"user_id": user_id, "native_language": "de", "role": "student", "learning_level": "A1", "is_default": True}
|
||||
return {**pref, "is_default": False}
|
||||
|
||||
|
||||
@router.put("/language-preference")
|
||||
def set_language_preference(
|
||||
pref: LanguagePreference,
|
||||
user_id: str = Query("default"),
|
||||
):
|
||||
"""Set user's native language and learning level."""
|
||||
if pref.native_language not in SUPPORTED_LANGUAGES:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Sprache '{pref.native_language}' nicht unterstuetzt. "
|
||||
f"Verfuegbar: {', '.join(SUPPORTED_LANGUAGES.keys())}",
|
||||
)
|
||||
|
||||
_preferences[user_id] = {
|
||||
"user_id": user_id,
|
||||
"native_language": pref.native_language,
|
||||
"role": pref.role,
|
||||
"learning_level": pref.learning_level,
|
||||
}
|
||||
|
||||
lang_meta = SUPPORTED_LANGUAGES[pref.native_language]
|
||||
logger.info(f"Language preference set: user={user_id} lang={pref.native_language} ({lang_meta['name']})")
|
||||
|
||||
return {**_preferences[user_id], "language_meta": lang_meta}
|
||||
Reference in New Issue
Block a user