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:
Benjamin Admin
2026-04-25 20:17:25 +02:00
parent b49ee3467e
commit d4959172a9
8 changed files with 805 additions and 0 deletions

View File

@@ -324,3 +324,29 @@ async def api_bulk_import(payload: BulkImportPayload):
count = await insert_words_bulk(words)
logger.info(f"Bulk imported {count} vocabulary words")
return {"imported": count}
# ---------------------------------------------------------------------------
# Translation Generation
# ---------------------------------------------------------------------------
class TranslateRequest(BaseModel):
word_ids: List[str]
target_language: str
@router.post("/translate")
async def api_translate_words(payload: TranslateRequest):
"""Generate translations for vocabulary words into a target language.
Uses local LLM (Ollama) for translation. Results are cached in the
vocabulary_words.translations JSONB field.
"""
from translation_service import translate_and_store
if payload.target_language not in {"tr", "ar", "uk", "ru", "pl", "fr", "es"}:
raise HTTPException(status_code=400, detail=f"Sprache '{payload.target_language}' nicht unterstuetzt")
count = await translate_and_store(payload.word_ids, payload.target_language)
return {"translated": count, "target_language": payload.target_language}