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