- New UnitBuilder component with language pair selector (DE⇄EN, ES, FR, etc.)
- Manual word entry form with auto-suggest from Kaikki dictionary (6M words)
- "No results" prompt to add multi-word terms (e.g. "schottisches Hochland")
- New backend endpoint GET /vocabulary/lookup-translation (any→any via EN hub)
- Updated POST /vocabulary/units: accepts custom_words + source_lang/target_lang
- Split unit endpoints into vocabulary/unit_api.py (500 LOC budget)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two buttons on topic cards:
- "Anzeigen": Shows words in search results (for review)
- "Alle zur Unit": Adds all topic words to the unit builder directly
Both buttons load from Kaikki and respect selected language.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Topics API now accepts lang= parameter. When lang=de, the word
labels are translated from English via Kaikki translations:
"eye, pupil, iris" → "Auge, Pupille, Iris"
Frontend sends searchLang to /topics endpoint and displays
display_words (translated) instead of words (English).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sidebar: Only "Lernmodule" link (no separate Woerterbuch).
/learn page: "Neue Lernunit erstellen" button links to /vocabulary
for the word selection flow. Teacher stays in one flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When user selects DE and types "Auge", the topic "Eye/Auge" is found
correctly. But "Alle laden" must search words with lang=en because
the topic word list is English (eye, pupil, iris...).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
31 curated topics with 683 words (Fruit, Animals, Body, Eye, Sports,
School, Family, Weather, etc.). When user types a word that belongs
to a topic, the topic appears as a suggestion with "Alle laden" button.
Clicking "Alle laden" fetches all words from that topic via Kaikki
and displays them for easy selection into a learning unit.
New endpoint: GET /api/vocabulary/topics?q=banana
New table: vocabulary_topics (topic, words[], word_count)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Search now sends lang= to API (was always defaulting to EN).
Users can select any of the 24 languages in the search bar dropdown.
Placeholder text changes based on selected language.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Search endpoint now defaults to source=kaikki, searching the
vocabulary_kaikki table with 6.27M Wiktionary entries.
/filters returns kaikki_total and kaikki_languages count.
/vocabulary header shows "6,271,749 Woerter in 24 Sprachen".
Manual vocabulary_words (27 entries) still accessible via source=manual.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Removed stale 'explanations' export that broke build
2. Explanation banner now spans full width ABOVE the 2/3+1/3 layout
so exercise cards and native words start at the same height
3. Both columns use items-start for visual alignment
4. Impressum link added at bottom of learn layout
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When user clicks an EN word, the corresponding image (Wikipedia
photo or emoji) appears below the match grid. Emoji shown as
large text (6xl), Wikipedia photos as max-h 160px image.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- exerciseType prop for correct explanation lookup (was using title)
- Vertical divider line between work area and native helper
- Cyan-tinted explanation card with lightbulb icon
- Padding between sections (pr-6 / pl-6 around divider)
- Explanation card has distinct background for visibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ExerciseLayout.tsx: Reusable layout component for all exercises.
- Left 2/3: Standard exercise area (EN + DE)
- Right 1/3: Native language helper (explanation + word list)
- Only shows right panel for non-DE/EN speakers
- Explanation card describes what the child should do
- Column headers are trilingual (TR · English · Deutsch)
Match page rebuilt using ExerciseLayout:
- EN+DE cards in 2/3 left area with equal height + audio
- Native words in 1/3 right panel with audio buttons
- Highlights native word when EN word is selected
- Progress bar with count, score counter
ExerciseLayout can be reused for flashcards, quiz, type, etc.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All cards (EN/DE/native) now have min-h-[48px] for consistent height.
Progress bar shows "4/12" count next to the fill bar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Progress bar under header (fills as pairs are matched)
- Counter with symbols: ✓ first-try, ↻ retry, ✗ errors
- EN column now also has audio buttons (small speaker icon)
- All 3 columns have consistent height (flex layout)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major improvements:
1. Third column shows native language translation (TR/AR/UK/RU)
2. Clicking EN word flashes native translation briefly (2s overlay)
3. German column has audio button on each word (speaker icon)
4. Native column has audio button for each translation
5. Scoring: tracks first-try correct vs retry vs errors separately
6. Full points only for error-free completion
7. "Nochmal" button always available to repeat the unit
8. Header shows live score: green/yellow/red counters
9. All buttons use translation system (t('back'), t('match'), etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaced localStorage-only hook with React Context Provider.
Layout and page components now share the same state — switching
language in the dropdown instantly updates all text on screen
without requiring a page reload.
NativeLanguageProvider added to root layout.tsx.
useNativeLanguage() re-exported from Context for backward compat.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
useNativeLanguage: Now has setNativeLang() that persists to localStorage.
Language selection carries across all pages automatically.
LanguageSwitcher: Compact dropdown component added to learn/layout.tsx
and parent/layout.tsx — visible on every sub-page (top-right).
Parent portal: Language dropdown syncs both UI language and native
language. Parents can switch language mid-session (e.g. when both
parents speak different languages).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Non-DE/EN users (parents) see a guide panel explaining:
- What this page is (vocabulary exercises from teacher)
- How each exercise type works (cards, quiz, listen, speak)
- All text in parent's native language (TR/AR/UK/RU/PL)
German/English users see the original layout without the guide.
This is the single entry point — no need to duplicate explanations
in every exercise sub-page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major improvements for non-DE/EN speaking parents:
1. Right panel: Explains in parent's native language what this
exercise is about and how it works (TR/AR/UK/RU/PL translations)
2. Trilingual buttons: "Dogru" (primary) with "Richtig / Correct"
subtitle so parents understand even if language detection is wrong
3. Native word shown prominently: "= elma" next to "apple"
4. Audio buttons labeled EN/DE/TR with language codes
5. Answer card shows all 3 languages: English, Deutsch, native
6. Progress tracker in the explanation panel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Vocab units created via /vocabulary/units only have QA items, no
pre-generated MC questions. Quiz now falls back to generating MC
questions client-side from QA items (EN word → 4 DE options).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All exercise pages now use useNativeLanguage() hook:
- Buttons show text in user's native language (Richtig→Dogru, etc.)
- Instructions translated (Geschafft→Bitti, Nochmal→Tekrar, etc.)
- wordInNative() available for vocab translations (needs data)
Pages updated: flashcards, quiz, type, listen, match, pronounce, story.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uses useNativeLanguage() hook for all UI text. Shows native language
translation of vocab word + audio button for native pronunciation.
Removed inline pt translations dict (now in exerciseTranslations.ts).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Binary data (MP3 audio) was corrupted by resp.text(). Now detects
content-type and uses arrayBuffer() for audio/* and image/* responses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Next.js route-level layouts provide Sidebar + gradient background
automatically for all sub-pages. Individual pages no longer need
their own wrapper divs or Sidebar imports.
- learn/layout.tsx: Sidebar + purple gradient for all learning pages
- parent/layout.tsx: Same for all parent portal pages
- LearnLayout.tsx: Reusable component for other pages
- Fixed broken <LearnLayout>}> artifacts from previous refactoring
- Removed duplicate Sidebar/wrapper code from 9 sub-pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
Turbopack doesn't support tsconfig path aliases pointing outside
the project root. Reverted to copying shared types directly into
each service. The canonical source remains shared/types/*.ts,
synced via scripts/sync-shared-types.sh.
Changes:
- Reverted docker-compose.yml contexts to ./service
- Reverted Dockerfiles to simple COPY . .
- Removed @shared/* from tsconfigs
- Removed symlinks + .gitignore hacks
- Added scripts/sync-shared-types.sh for keeping copies in sync
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shared types extracted to shared/types/:
- companion.ts (33+ types, was 100% duplicated admin-lehrer ↔ studio-v2)
- klausur.ts (18+ types, was 95% duplicated across 4 locations)
- ocr-labeling.ts (11 types, was 100% duplicated admin-lehrer ↔ website)
Original type files replaced with re-exports for backward compat.
tsconfig.json paths updated with @shared/* alias in all 3 services.
Docker: Changed build context from ./service to . (root) so shared/
is accessible. Dockerfiles updated to COPY service/ + shared/.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sed replacement left orphaned hostname references in story page
and empty lines in getApiBase functions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>