Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
German Learning Gradio App
|
| 2 |
+
|
| 3 |
+
File: app.py
|
| 4 |
+
|
| 5 |
+
Run locally: python app.py
|
| 6 |
+
|
| 7 |
+
Deploy: on Hugging Face Spaces (Gradio SDK)
|
| 8 |
+
|
| 9 |
+
import gradio as gr import pandas as pd import random from gtts import gTTS import io
|
| 10 |
+
|
| 11 |
+
--- Data ---
|
| 12 |
+
|
| 13 |
+
LESSONS = { "A1 - Greetings & Basics": { "vocab": [ ("Hallo", "Hello"), ("Guten Morgen", "Good morning"), ("Gute Nacht", "Good night"), ("Danke", "Thank you"), ("Bitte", "Please / You're welcome"), ("Ja", "Yes"), ("Nein", "No"), ], "grammar": [ "Nouns have genders: der (m), die (f), das (n).", "Basic verb sein (to be): ich bin, du bist, er/sie ist.", ], }, "A1 - Introductions": { "vocab": [ ("Ich heiße...", "My name is..."), ("Wie heißt du?", "What's your name?"), ("Ich komme aus...", "I come from..."), ("Wohnst du hier?", "Do you live here?"), ], "grammar": [ "Personal pronouns: ich, du, er, sie, es, wir, ihr, sie, Sie.", ], }, }
|
| 14 |
+
|
| 15 |
+
QUIZZES = { "A1 - Basics Quiz": [ { "q": "What is 'Danke' in English?", "options": ["Please", "Thank you", "Hello", "No"], "answer": "Thank you", }, { "q": "Which article is masculine?", "options": ["die", "das", "der", "dem"], "answer": "der", }, { "q": "Translate: 'Guten Morgen'", "options": ["Good night", "Good morning", "Hello", "Goodbye"], "answer": "Good morning", }, ] }
|
| 16 |
+
|
| 17 |
+
--- Helpers ---
|
| 18 |
+
|
| 19 |
+
def tts_audio_bytes(text, lang="de"): try: tts = gTTS(text=text, lang=lang) fp = io.BytesIO() tts.write_to_fp(fp) fp.seek(0) return fp.read() except Exception: return None
|
| 20 |
+
|
| 21 |
+
def get_vocab_table(lesson_name): vocab = LESSONS[lesson_name]["vocab"] df = pd.DataFrame(vocab, columns=["German", "English"]) return df
|
| 22 |
+
|
| 23 |
+
def play_pronunciation(word): audio = tts_audio_bytes(word) return (word, audio)
|
| 24 |
+
|
| 25 |
+
def random_flashcard(lesson_name): word, meaning = random.choice(LESSONS[lesson_name]["vocab"]) audio = tts_audio_bytes(word) return (f"{word} — {meaning}", audio)
|
| 26 |
+
|
| 27 |
+
def get_grammar_notes(lesson_name): notes = LESSONS[lesson_name]["grammar"] return "\n".join([f"• {n}" for n in notes])
|
| 28 |
+
|
| 29 |
+
--- Quiz Logic ---
|
| 30 |
+
|
| 31 |
+
def start_quiz(): q = QUIZZES["A1 - Basics Quiz"] return q[0]["q"], q[0]["options"], 0, 0, []
|
| 32 |
+
|
| 33 |
+
def next_question(qidx, score, answers, choice): quiz = QUIZZES["A1 - Basics Quiz"] if choice == quiz[qidx]["answer"]: score += 1 answers.append({ "question": quiz[qidx]["q"], "selected": choice, "correct": quiz[qidx]["answer"], }) qidx += 1 if qidx >= len(quiz): result_text = f"Quiz Complete! Score: {score}/{len(quiz)}" df = pd.DataFrame(answers) return result_text, None, None, qidx, score, answers else: q = quiz[qidx] return q["q"], q["options"], None, qidx, score, answers
|
| 34 |
+
|
| 35 |
+
--- Gradio Interface ---
|
| 36 |
+
|
| 37 |
+
with gr.Blocks(title="German Learning Hub") as demo: gr.Markdown("# 🇩🇪 German Learning Hub — Beginner Level (A1)")
|
| 38 |
+
|
| 39 |
+
with gr.Tab("Vocabulary & Grammar"):
|
| 40 |
+
lesson = gr.Dropdown(list(LESSONS.keys()), label="Choose Lesson", value="A1 - Greetings & Basics")
|
| 41 |
+
vocab_table = gr.DataFrame(headers=["German", "English"], label="Vocabulary")
|
| 42 |
+
grammar_notes = gr.Textbox(label="Grammar Notes", lines=5)
|
| 43 |
+
word_input = gr.Dropdown(label="Play Pronunciation", choices=[w for w, _ in LESSONS["A1 - Greetings & Basics"]["vocab"]])
|
| 44 |
+
pronounce_btn = gr.Button("Play")
|
| 45 |
+
word_output = gr.Textbox(label="Selected Word")
|
| 46 |
+
audio_output = gr.Audio(label="Audio", type="filepath")
|
| 47 |
+
|
| 48 |
+
flash_btn = gr.Button("🎴 Show Random Flashcard")
|
| 49 |
+
flash_text = gr.Textbox(label="Flashcard")
|
| 50 |
+
flash_audio = gr.Audio(label="Flashcard Audio", type="filepath")
|
| 51 |
+
|
| 52 |
+
lesson.change(get_vocab_table, inputs=lesson, outputs=vocab_table)
|
| 53 |
+
lesson.change(get_grammar_notes, inputs=lesson, outputs=grammar_notes)
|
| 54 |
+
pronounce_btn.click(play_pronunciation, inputs=word_input, outputs=[word_output, audio_output])
|
| 55 |
+
flash_btn.click(random_flashcard, inputs=lesson, outputs=[flash_text, flash_audio])
|
| 56 |
+
|
| 57 |
+
with gr.Tab("Quiz"):
|
| 58 |
+
start_btn = gr.Button("Start Quiz")
|
| 59 |
+
question = gr.Textbox(label="Question")
|
| 60 |
+
options = gr.Radio(label="Options")
|
| 61 |
+
submit_btn = gr.Button("Submit Answer")
|
| 62 |
+
result_box = gr.Textbox(label="Result")
|
| 63 |
+
|
| 64 |
+
qidx = gr.State(0)
|
| 65 |
+
score = gr.State(0)
|
| 66 |
+
answers = gr.State([])
|
| 67 |
+
|
| 68 |
+
start_btn.click(start_quiz, outputs=[question, options, qidx, score, answers])
|
| 69 |
+
submit_btn.click(next_question, inputs=[qidx, score, answers, options], outputs=[question, options, result_box, qidx, score, answers])
|
| 70 |
+
|
| 71 |
+
with gr.Tab("Listening Practice"):
|
| 72 |
+
sentence = gr.Dropdown(["Ich heiße Hidayat.", "Ich komme aus Pakistan.", "Wie geht es dir?"], label="Select a sentence")
|
| 73 |
+
listen_btn = gr.Button("Play")
|
| 74 |
+
audio_sent = gr.Audio(label="Audio", type="filepath")
|
| 75 |
+
|
| 76 |
+
def play_sentence(sent):
|
| 77 |
+
audio = tts_audio_bytes(sent)
|
| 78 |
+
return audio
|
| 79 |
+
|
| 80 |
+
listen_btn.click(play_sentence, inputs=sentence, outputs=audio_sent)
|
| 81 |
+
|
| 82 |
+
gr.Markdown("---")
|
| 83 |
+
gr.Markdown("Made by Dr. Hidayatullah Mahar — German Learning Hub on Hugging Face 💡")
|
| 84 |
+
|
| 85 |
+
if name == "main": demo.launch()
|
| 86 |
+
|