modified: .env.example
modified: Dockerfile modified: app.py new file: locales/de-DE.json modified: templates/login.html modified: templates/playlists.html modified: templates/quiz.html
This commit is contained in:
@@ -7,4 +7,6 @@ SPOTIPY_REDIRECT_URI=http://localhost:5000/callback
|
||||
SECRET_KEY=dein_geheimer_flask_key
|
||||
|
||||
# Flask Umgebung (optional)
|
||||
FLASK_ENV=development
|
||||
FLASK_ENV=development
|
||||
|
||||
LANG=de-DE
|
||||
@@ -17,6 +17,7 @@ ENV SPOTIPY_CLIENT_ID=$SPOTIPY_CLIENT_ID
|
||||
ENV SPOTIPY_CLIENT_SECRET=$SPOTIPY_CLIENT_SECRET
|
||||
ENV SPOTIPY_REDIRECT_URI=$SPOTIPY_REDIRECT_URI
|
||||
ENV FLASK_ENV=development
|
||||
ENV LANG=$LANG
|
||||
|
||||
# Starten mit Gunicorn für Production
|
||||
CMD ["python", "app.py"]
|
||||
|
||||
18
app.py
18
app.py
@@ -9,6 +9,7 @@ from spotipy.oauth2 import SpotifyOAuth
|
||||
import random
|
||||
from difflib import SequenceMatcher
|
||||
import re
|
||||
import json
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = os.getenv("SECRET_KEY")
|
||||
@@ -16,6 +17,20 @@ app.secret_key = os.getenv("SECRET_KEY")
|
||||
# Erweiterte Berechtigungen für Web Playback SDK
|
||||
SCOPE = "user-library-read playlist-read-private streaming user-read-email user-read-private"
|
||||
|
||||
def get_locale():
|
||||
return os.getenv("LANG", "de-DE")
|
||||
|
||||
def get_translations():
|
||||
lang = get_locale()
|
||||
path = os.path.join(os.path.dirname(__file__), "locales", f"{lang}.json")
|
||||
try:
|
||||
with open(path, encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except Exception:
|
||||
# Fallback auf Deutsch
|
||||
with open(os.path.join(os.path.dirname(__file__), "locales", "de-DE.json"), encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
def get_spotify_client():
|
||||
token_info = session.get("token_info", None)
|
||||
if not token_info:
|
||||
@@ -150,7 +165,8 @@ def quiz(playlist_id):
|
||||
question_number=len(played_tracks),
|
||||
total_questions=len(tracks),
|
||||
score=score,
|
||||
answered=answered
|
||||
answered=answered,
|
||||
translations=get_translations()
|
||||
)
|
||||
|
||||
@app.route("/search_track", methods=["POST"])
|
||||
|
||||
24
locales/de-DE.json
Normal file
24
locales/de-DE.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"login_title": "Login mit Spotify",
|
||||
"login_button": "Mit Spotify einloggen",
|
||||
"quiz_title": "Musik Quiz",
|
||||
"choose_playlist": "Wähle eine Playlist:",
|
||||
"guess_artist": "Künstler erraten",
|
||||
"guess_title": "Titel erraten",
|
||||
"guess_year": "Jahr erraten",
|
||||
"question_artist": "Wer ist der Künstler dieses Songs?",
|
||||
"question_title": "Wie heißt dieser Song?",
|
||||
"question_year": "In welchem Jahr wurde dieser Song veröffentlicht?",
|
||||
"input_artist": "Künstlername eingeben...",
|
||||
"input_title": "Songtitel eingeben...",
|
||||
"input_year": "Jahr eingeben...",
|
||||
"answer_button": "Antworten",
|
||||
"next_question": "Nächste Frage",
|
||||
"quiz_end": "Quiz beenden",
|
||||
"tip_artist": "Tipp: Gib den Namen des Künstlers ein, der diesen Song performt.",
|
||||
"tip_title": "Tipp: Gib den Titel des Songs ein, den du gerade hörst.",
|
||||
"tip_year": "Tipp: Gib das Erscheinungsjahr des Songs ein.",
|
||||
"correct": "Richtig! 🎉",
|
||||
"wrong": "Falsch 😢",
|
||||
"right_answer": "Die richtige Antwort ist:"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Login mit Spotify</title>
|
||||
<title>{{ translations['login_title'] }}</title>
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #1DB954 0%, #191414 100%);
|
||||
@@ -46,7 +46,7 @@
|
||||
<body>
|
||||
<div class="login-container">
|
||||
<h1>Quizify Musik Quiz</h1>
|
||||
<a href="/login" class="button">Mit Spotify einloggen</a>
|
||||
<a href="/login" class="button">{{ translations['login_button'] }}</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Deine Playlists</title>
|
||||
<title>{{ translations['quiz_title'] }}</title>
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #191414 0%, #1DB954 100%);
|
||||
@@ -55,7 +55,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="playlist-container">
|
||||
<h2>Wähle eine Playlist:</h2>
|
||||
<h2>{{ translations['choose_playlist'] }}</h2>
|
||||
<ul>
|
||||
{% for pl in playlists %}
|
||||
<li><a class="playlist-link" href="/quiz/{{ pl.id }}">{{ pl.name }}</a></li>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Musik Quiz</title>
|
||||
<title>{{ translations['quiz_title'] }}</title>
|
||||
<!-- Spotify Web Playback SDK -->
|
||||
<script src="https://sdk.scdn.co/spotify-player.js"></script>
|
||||
<style>
|
||||
@@ -104,6 +104,9 @@
|
||||
let currentGameMode = "{{ game_mode }}";
|
||||
let correctAnswer = "";
|
||||
|
||||
// translations für JS verfügbar machen
|
||||
const i18n = {{ translations|tojson }};
|
||||
|
||||
// Wird aufgerufen, wenn Spotify Web Playback SDK geladen ist
|
||||
window.onSpotifyWebPlaybackSDKReady = () => {
|
||||
const token = '{{ access_token }}';
|
||||
@@ -184,16 +187,16 @@
|
||||
function setCorrectAnswer() {
|
||||
if (currentGameMode === 'artist') {
|
||||
correctAnswer = "{{ track.artists[0].name }}";
|
||||
document.getElementById('question-text').innerText = "Wer ist der Künstler dieses Songs?";
|
||||
document.getElementById('answerInput').placeholder = "Künstlername eingeben...";
|
||||
document.getElementById('question-text').innerText = i18n.question_artist;
|
||||
document.getElementById('answerInput').placeholder = i18n.input_artist;
|
||||
} else if (currentGameMode === 'title') {
|
||||
correctAnswer = "{{ track.name }}";
|
||||
document.getElementById('question-text').innerText = "Wie heißt dieser Song?";
|
||||
document.getElementById('answerInput').placeholder = "Songtitel eingeben...";
|
||||
document.getElementById('question-text').innerText = i18n.question_title;
|
||||
document.getElementById('answerInput').placeholder = i18n.input_title;
|
||||
} else if (currentGameMode === 'year') {
|
||||
correctAnswer = "{{ track.album.release_date[:4] }}";
|
||||
document.getElementById('question-text').innerText = "In welchem Jahr wurde dieser Song veröffentlicht?";
|
||||
document.getElementById('answerInput').placeholder = "Jahr eingeben...";
|
||||
document.getElementById('question-text').innerText = i18n.question_year;
|
||||
document.getElementById('answerInput').placeholder = i18n.input_year;
|
||||
document.getElementById('answerInput').type = "number";
|
||||
}
|
||||
}
|
||||
@@ -332,16 +335,16 @@ window.onload = function() {
|
||||
<div style="text-align:center; margin-bottom: 20px;">
|
||||
<a href="/reset_quiz/{{ playlist_id }}" class="btn btn-danger" style="margin-top:10px;">Quiz beenden</a>
|
||||
</div>
|
||||
<h2 id="question-text">Wer ist der Künstler dieses Songs?</h2>
|
||||
<h2 id="question-text">{{ translations['question_artist'] }}</h2>
|
||||
|
||||
<!-- Verstecktes Feld für device_id -->
|
||||
<input type="hidden" id="device_id" value="">
|
||||
|
||||
<!-- Spielmodi -->
|
||||
<div class="game-modes">
|
||||
<button class="btn {{ 'btn-success' if game_mode == 'artist' else 'btn-secondary' }}" onclick="switchGameMode('artist')">Künstler erraten</button>
|
||||
<button class="btn {{ 'btn-success' if game_mode == 'title' else 'btn-secondary' }}" onclick="switchGameMode('title')">Titel erraten</button>
|
||||
<button class="btn {{ 'btn-success' if game_mode == 'year' else 'btn-secondary' }}" onclick="switchGameMode('year')">Jahr erraten</button>
|
||||
<button class="btn {{ 'btn-success' if game_mode == 'artist' else 'btn-secondary' }}" onclick="switchGameMode('artist')">{{ translations['guess_artist'] }}</button>
|
||||
<button class="btn {{ 'btn-success' if game_mode == 'title' else 'btn-secondary' }}" onclick="switchGameMode('title')">{{ translations['guess_title'] }}</button>
|
||||
<button class="btn {{ 'btn-success' if game_mode == 'year' else 'btn-secondary' }}" onclick="switchGameMode('year')">{{ translations['guess_year'] }}</button>
|
||||
</div>
|
||||
|
||||
<!-- Optionen für das Spiel -->
|
||||
@@ -369,8 +372,8 @@ window.onload = function() {
|
||||
|
||||
<!-- Antwort-Eingabe -->
|
||||
<div style="text-align: center; margin-top: 30px;">
|
||||
<input type="text" id="answerInput" placeholder="Gib deine Antwort ein..." oninput="searchTracks()">
|
||||
<button class="btn" onclick="checkAnswer()">Antworten</button>
|
||||
<input type="text" id="answerInput" placeholder="{{ translations['input_artist'] }}" oninput="searchTracks()">
|
||||
<button class="btn" onclick="checkAnswer()">{{ translations['answer_button'] }}</button>
|
||||
|
||||
<!-- Suchergebnisse -->
|
||||
<div id="searchResults" class="search-results"></div>
|
||||
@@ -379,17 +382,17 @@ window.onload = function() {
|
||||
<div id="resultContainer" class="result-container"></div>
|
||||
|
||||
<!-- Nächste Frage Button, wird nach Antwort angezeigt -->
|
||||
<a id="nextQuestionBtn" href="/quiz/{{ playlist_id }}?mode={{ game_mode }}" class="btn" style="display: none;">Nächste Frage</a>
|
||||
<a id="nextQuestionBtn" href="/quiz/{{ playlist_id }}?mode={{ game_mode }}" class="btn" style="display: none;">{{ translations['next_question'] }}</a>
|
||||
</div>
|
||||
|
||||
<!-- Hilfe-Text je nach Modus -->
|
||||
<div class="hint-container">
|
||||
{% if game_mode == 'artist' %}
|
||||
<p>Tipp: Gib den Namen des Künstlers ein, der diesen Song performt.</p>
|
||||
<p>{{ translations['tip_artist'] }}</p>
|
||||
{% elif game_mode == 'title' %}
|
||||
<p>Tipp: Gib den Titel des Songs ein, den du gerade hörst.</p>
|
||||
<p>{{ translations['tip_title'] }}</p>
|
||||
{% elif game_mode == 'year' %}
|
||||
<p>Tipp: Gib das Erscheinungsjahr des Songs ein.</p>
|
||||
<p>{{ translations['tip_year'] }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user