diff --git a/steam-gift-manager/Dockerfile b/steam-gift-manager/Dockerfile new file mode 100644 index 0000000..5f82566 --- /dev/null +++ b/steam-gift-manager/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.10-slim + +# Shell explizit setzen +SHELL ["/bin/bash", "-c"] + +# Datenbankordner erstellen und Berechtigungen setzen +RUN mkdir -p /app/data && chmod -R a+rwX /app/data + +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +ARG UID=1000 +ARG GID=1000 + +RUN groupadd -g $GID appuser && useradd -u $UID -g $GID -m appuser && chown -R appuser:appuser /app + +USER appuser + +EXPOSE 5000 +CMD ["python", "app.py"] diff --git a/steam-gift-manager/app.py b/steam-gift-manager/app.py new file mode 100644 index 0000000..af6bdc8 --- /dev/null +++ b/steam-gift-manager/app.py @@ -0,0 +1,212 @@ +from flask import Flask, render_template, request, redirect, url_for, flash, make_response, session, abort +from flask_sqlalchemy import SQLAlchemy +from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user +from flask_babel import Babel, _ +from werkzeug.security import generate_password_hash, check_password_hash +from datetime import datetime +import os + +app = Flask(__name__) +app.config['SECRET_KEY'] = os.urandom(24) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////app/data/games.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['BABEL_DEFAULT_LOCALE'] = 'de' +app.config['BABEL_SUPPORTED_LOCALES'] = ['de', 'en'] +app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'translations' + + +db = SQLAlchemy(app) +login_manager = LoginManager(app) +login_manager.login_view = 'login' +babel = Babel(app) + +@babel.localeselector +def get_locale(): + if 'lang' in session and session['lang'] in app.config['BABEL_SUPPORTED_LOCALES']: + return session['lang'] + return request.accept_languages.best_match(app.config['BABEL_SUPPORTED_LOCALES']) + +@app.context_processor +def inject_template_vars(): + return dict( + get_locale=get_locale, + theme='dark' if request.cookies.get('dark_mode') == 'true' else 'light' + ) + +class User(UserMixin, db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(100), unique=True) + password = db.Column(db.String(100)) + games = db.relationship('Game', backref='owner', lazy=True) + +class Game(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(100), nullable=False) + steam_key = db.Column(db.String(100), nullable=False) + status = db.Column(db.String(50), nullable=False) + recipient = db.Column(db.String(100)) + notes = db.Column(db.Text) + url = db.Column(db.String(200)) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + redeem_date = db.Column(db.DateTime) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + steam_appid = db.Column(db.String(20)) + +@login_manager.user_loader +def load_user(user_id): + return db.session.get(User, int(user_id)) + +@app.route('/') +@login_required +def index(): + search_query = request.args.get('q', '') + query = db.session.query(Game).filter_by(user_id=current_user.id) + if search_query: + query = query.filter(Game.name.ilike(f'%{search_query}%')) + games = query.order_by(Game.created_at.desc()).all() + return render_template('index.html', + games=games, + format_date=lambda dt: dt.strftime('%d.%m.%Y') if dt else '', + search_query=search_query) + +@app.route('/set-lang/') +def set_lang(lang): + if lang in app.config['BABEL_SUPPORTED_LOCALES']: + session['lang'] = lang + return redirect(request.referrer or url_for('index')) + +@app.route('/set-theme/') +def set_theme(theme): + resp = make_response('', 204) + resp.set_cookie('dark_mode', 'true' if theme == 'dark' else 'false', max_age=60*60*24*365) + return resp + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + username = request.form['username'] + password = request.form['password'] + user = User.query.filter_by(username=username).first() + if user and check_password_hash(user.password, password): + login_user(user) + return redirect(url_for('index')) + flash(_('Invalid credentials'), 'danger') + return render_template('login.html') + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if request.method == 'POST': + username = request.form['username'] + password = generate_password_hash(request.form['password']) + if User.query.filter_by(username=username).first(): + flash(_('Username already exists'), 'danger') + return redirect(url_for('register')) + new_user = User(username=username, password=password) + db.session.add(new_user) + db.session.commit() + login_user(new_user) + return redirect(url_for('index')) + return render_template('register.html') + +@app.route('/logout') +@login_required +def logout(): + logout_user() + return redirect(url_for('login')) + +import re + +def extract_steam_appid(url): + match = re.search(r'store\.steampowered\.com/app/(\d+)', url or '') + if match: + return match.group(1) + return '' + +@app.route('/add', methods=['GET', 'POST']) +@login_required +def add_game(): + if request.method == 'POST': + try: + url = request.form.get('url', '') + steam_appid = request.form.get('steam_appid', '').strip() + if not steam_appid: + steam_appid = extract_steam_appid(url) + new_game = Game( + name=request.form['name'], + steam_key=request.form['steam_key'], + status=request.form['status'], + recipient=request.form.get('recipient', ''), + notes=request.form.get('notes', ''), + url=url, + steam_appid=steam_appid, # <- jetzt wird sie gesetzt! + redeem_date=datetime.strptime(request.form['redeem_date'], '%Y-%m-%d') if request.form['redeem_date'] else None, + user_id=current_user.id + ) + db.session.add(new_game) + db.session.commit() + flash(_('Game added successfully!'), 'success') + return redirect(url_for('index')) + except Exception as e: + db.session.rollback() + flash(_('Error: ') + str(e), 'danger') + return render_template('add_game.html') + + +@app.route('/edit/', methods=['GET', 'POST']) +@login_required +def edit_game(game_id): + game = db.session.get(Game, game_id) # SQLAlchemy 2.x-kompatibel + if not game or game.owner != current_user: + return _("Not allowed!"), 403 + + if request.method == 'POST': + try: + # Steam AppID aus Formular oder URL extrahieren + url = request.form.get('url', '') + steam_appid = request.form.get('steam_appid', '').strip() + if not steam_appid: + steam_appid = extract_steam_appid(url) + + # Aktualisiere alle Felder + game.name = request.form['name'] + game.steam_key = request.form['steam_key'] + game.status = request.form['status'] + game.recipient = request.form.get('recipient', '') + game.notes = request.form.get('notes', '') + game.url = url + game.steam_appid = steam_appid # <- FEHLTE HIER + game.redeem_date = datetime.strptime(request.form['redeem_date'], '%Y-%m-%d') if request.form['redeem_date'] else None + + db.session.commit() + flash(_('Changes saved!'), 'success') + return redirect(url_for('index')) + + except Exception as e: + db.session.rollback() + flash(_('Error: ') + str(e), 'danger') + + return render_template('edit_game.html', + game=game, + redeem_date=game.redeem_date.strftime('%Y-%m-%d') if game.redeem_date else '') + + +@app.route('/delete/', methods=['POST']) +@login_required +def delete_game(game_id): + game = Game.query.get_or_404(game_id) + if game.owner != current_user: + return _("Not allowed!"), 403 + try: + db.session.delete(game) + db.session.commit() + flash(_('Game deleted!'), 'success') + except Exception as e: + db.session.rollback() + flash(_('Error deleting: ') + str(e), 'danger') + return redirect(url_for('index')) + + +if __name__ == '__main__': + with app.app_context(): + db.create_all() + app.run(host='0.0.0.0', port=5000) diff --git a/steam-gift-manager/babel.cfg b/steam-gift-manager/babel.cfg new file mode 100644 index 0000000..b27cadf --- /dev/null +++ b/steam-gift-manager/babel.cfg @@ -0,0 +1,2 @@ +[python: **.py] +[jinja2: templates/**.html] diff --git a/steam-gift-manager/docker-compose.yml b/steam-gift-manager/docker-compose.yml new file mode 100644 index 0000000..c82d8c5 --- /dev/null +++ b/steam-gift-manager/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.8' + +services: + steam-manager: + build: . + ports: + - "5000:5000" + volumes: + - /root/test/data:/app/data + - /root/test/steam-translations:/app/translations + environment: + - FLASK_DEBUG=0 + restart: unless-stopped diff --git a/steam-gift-manager/requirements.txt b/steam-gift-manager/requirements.txt new file mode 100644 index 0000000..0a93304 --- /dev/null +++ b/steam-gift-manager/requirements.txt @@ -0,0 +1,7 @@ +flask +flask-login +werkzeug +python-dotenv +flask-sqlalchemy +flask-babel +jinja2<3.1.0 diff --git a/steam-gift-manager/static/style.css b/steam-gift-manager/static/style.css new file mode 100644 index 0000000..37b47ea --- /dev/null +++ b/steam-gift-manager/static/style.css @@ -0,0 +1,33 @@ +:root { + --bs-body-bg: #ffffff; + --bs-body-color: #212529; +} +[data-bs-theme="dark"] { + --bs-body-bg: #1a1a1a; + --bs-body-color: #f8f9fa; + --bs-border-color: #495057; +} +[data-bs-theme="dark"] .table { + --bs-table-bg: #212529; + --bs-table-color: #fff; + --bs-table-border-color: #495057; +} +[data-bs-theme="dark"] .card { + background-color: #2b3035; + border-color: var(--bs-border-color); +} +[data-bs-theme="dark"] .navbar { + background-color: #212529 !important; +} +body { + background-color: var(--bs-body-bg); + color: var(--bs-body-color); + transition: all 0.3s ease; +} +.font-monospace { + font-family: Monaco, Consolas, "Courier New", monospace; +} +.badge { + font-size: 0.9em; + font-weight: 500; +} diff --git a/steam-gift-manager/templates/add_game.html b/steam-gift-manager/templates/add_game.html new file mode 100644 index 0000000..2cce4d1 --- /dev/null +++ b/steam-gift-manager/templates/add_game.html @@ -0,0 +1,46 @@ +{% extends "base.html" %} +{% block content %} +
+

{{ _('Add New Game') }}

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + {{ _('Cancel') }} +
+
+
+
+{% endblock %} diff --git a/steam-gift-manager/templates/base.html b/steam-gift-manager/templates/base.html new file mode 100644 index 0000000..b5751b3 --- /dev/null +++ b/steam-gift-manager/templates/base.html @@ -0,0 +1,81 @@ + + + + + + {{ _('Steam Manager') }} + + + + + +
+ {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ {{ message }} + +
+ {% endfor %} + {% endif %} + {% endwith %} + {% block content %}{% endblock %} +
+ + + + diff --git a/steam-gift-manager/templates/edit_game.html b/steam-gift-manager/templates/edit_game.html new file mode 100644 index 0000000..bfc43b8 --- /dev/null +++ b/steam-gift-manager/templates/edit_game.html @@ -0,0 +1,50 @@ +{% extends "base.html" %} +{% block content %} +
+

{{ _('Edit Game') }}

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + {{ _('Cancel') }} +
+
+
+
+{% endblock %} diff --git a/steam-gift-manager/templates/index.html b/steam-gift-manager/templates/index.html new file mode 100644 index 0000000..b45a1a7 --- /dev/null +++ b/steam-gift-manager/templates/index.html @@ -0,0 +1,70 @@ +{% extends "base.html" %} +{% block content %} +
+

{{ _('My Games') }}

+ + + {{ _('Add New Game') }} + +
+ +{% if games %} +
+ + + + + + + + + + + + + + + {% for game in games %} + + + + + + + + + + + {% endfor %} + +
{{ _('Cover') }}{{ _('Name') }}{{ _('Key') }}{{ _('Status') }}{{ _('Created') }}{{ _('Redeem by') }}{{ _('Shop') }}{{ _('Actions') }}
+ {% if game.steam_appid %} + Steam Header + {% endif %} + {{ game.name }}{{ game.steam_key }} + {% if game.status == 'nicht eingelöst' %} + {{ _('Not redeemed') }} + {% elif game.status == 'verschenkt' %} + {{ _('Gifted') }} + {% elif game.status == 'eingelöst' %} + {{ _('Redeemed') }} + {% endif %} + {{ format_date(game.created_at) }} + {% if game.redeem_date %} + {{ format_date(game.redeem_date) }} + {% endif %} + + {% if game.url %} + 🔗 {{ _('Shop') }} + {% endif %} + + ✏️ +
+ +
+
+
+{% else %} +
{{ _('No games yet') }}
+{% endif %} +{% endblock %} diff --git a/steam-gift-manager/templates/login.html b/steam-gift-manager/templates/login.html new file mode 100644 index 0000000..2bd37d1 --- /dev/null +++ b/steam-gift-manager/templates/login.html @@ -0,0 +1,26 @@ +{% extends "base.html" %} +{% block content %} +
+
+
+
+

{{ _('Login') }}

+
+
+ + +
+
+ + +
+ +
+ +
+
+
+
+{% endblock %} diff --git a/steam-gift-manager/templates/register.html b/steam-gift-manager/templates/register.html new file mode 100644 index 0000000..8511407 --- /dev/null +++ b/steam-gift-manager/templates/register.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} +{% block content %} +
+
+
+
+

{{ _('Register') }}

+
+
+ + +
+
+ + +
+ +
+
+
+
+
+{% endblock %} diff --git a/steam-translations/de/LC_MESSAGES/messages.mo b/steam-translations/de/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..8381234 Binary files /dev/null and b/steam-translations/de/LC_MESSAGES/messages.mo differ diff --git a/steam-translations/de/LC_MESSAGES/messages.po b/steam-translations/de/LC_MESSAGES/messages.po new file mode 100644 index 0000000..d02d6e5 --- /dev/null +++ b/steam-translations/de/LC_MESSAGES/messages.po @@ -0,0 +1,185 @@ +# German translations for PROJECT. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2025-04-21 11:24+0000\n" +"PO-Revision-Date: 2025-04-21 11:24+0000\n" +"Last-Translator: FULL NAME \n" +"Language: de\n" +"Language-Team: de \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: app.py:93 +msgid "Invalid credentials" +msgstr "" + +#: app.py:102 +msgid "Username already exists" +msgstr "" + +#: app.py:147 +msgid "Game added successfully!" +msgstr "" + +#: app.py:151 app.py:186 +msgid "Error: " +msgstr "" + +#: app.py:160 app.py:198 +msgid "Not allowed!" +msgstr "" + +#: app.py:181 +msgid "Changes saved!" +msgstr "" + +#: app.py:202 +msgid "Game deleted!" +msgstr "" + +#: app.py:205 +msgid "Error deleting: " +msgstr "" + +#: templates/add_game.html:4 templates/index.html:6 +msgid "Add New Game" +msgstr "" + +#: templates/add_game.html:8 templates/edit_game.html:8 templates/index.html:16 +msgid "Name" +msgstr "" + +#: templates/add_game.html:12 templates/edit_game.html:12 +msgid "Steam Key" +msgstr "" + +#: templates/add_game.html:16 templates/edit_game.html:20 +#: templates/index.html:18 +msgid "Status" +msgstr "" + +#: templates/add_game.html:18 templates/edit_game.html:22 +#: templates/index.html:38 +msgid "Not redeemed" +msgstr "" + +#: templates/add_game.html:19 templates/edit_game.html:23 +#: templates/index.html:40 +msgid "Gifted" +msgstr "" + +#: templates/add_game.html:20 templates/edit_game.html:24 +#: templates/index.html:42 +msgid "Redeemed" +msgstr "" + +#: templates/add_game.html:24 templates/edit_game.html:28 +#: templates/index.html:20 +msgid "Redeem by" +msgstr "" + +#: templates/add_game.html:28 templates/edit_game.html:32 +msgid "Recipient" +msgstr "" + +#: templates/add_game.html:32 templates/edit_game.html:36 +msgid "Shop URL" +msgstr "" + +#: templates/add_game.html:36 templates/edit_game.html:40 +msgid "Notes" +msgstr "" + +#: templates/add_game.html:40 templates/edit_game.html:44 +msgid "Save" +msgstr "" + +#: templates/add_game.html:41 templates/edit_game.html:45 +msgid "Cancel" +msgstr "" + +#: templates/base.html:6 templates/base.html:13 +msgid "Steam Manager" +msgstr "" + +#: templates/base.html:19 +msgid "Search" +msgstr "" + +#: templates/base.html:27 +msgid "Dark Mode" +msgstr "" + +#: templates/base.html:48 +msgid "Logout" +msgstr "" + +#: templates/edit_game.html:4 +msgid "Edit Game" +msgstr "" + +#: templates/edit_game.html:16 +msgid "Steam AppID (optional)" +msgstr "" + +#: templates/index.html:4 +msgid "My Games" +msgstr "" + +#: templates/index.html:15 +msgid "Cover" +msgstr "" + +#: templates/index.html:17 +msgid "Key" +msgstr "" + +#: templates/index.html:19 +msgid "Created" +msgstr "" + +#: templates/index.html:21 templates/index.html:53 +msgid "Shop" +msgstr "" + +#: templates/index.html:22 +msgid "Actions" +msgstr "" + +#: templates/index.html:59 +msgid "Really delete?" +msgstr "" + +#: templates/index.html:68 +msgid "No games yet" +msgstr "" + +#: templates/login.html:7 templates/login.html:17 +msgid "Login" +msgstr "" + +#: templates/login.html:10 templates/register.html:10 +msgid "Username" +msgstr "" + +#: templates/login.html:14 templates/register.html:14 +msgid "Password" +msgstr "" + +#: templates/login.html:20 +msgid "No account yet? Register" +msgstr "" + +#: templates/register.html:7 templates/register.html:17 +msgid "Register" +msgstr "" + diff --git a/steam-translations/en/LC_MESSAGES/messages.mo b/steam-translations/en/LC_MESSAGES/messages.mo new file mode 100644 index 0000000..ab9f395 Binary files /dev/null and b/steam-translations/en/LC_MESSAGES/messages.mo differ diff --git a/steam-translations/en/LC_MESSAGES/messages.po b/steam-translations/en/LC_MESSAGES/messages.po new file mode 100644 index 0000000..7eacdbd --- /dev/null +++ b/steam-translations/en/LC_MESSAGES/messages.po @@ -0,0 +1,185 @@ +# English translations for PROJECT. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2025-04-21 11:24+0000\n" +"PO-Revision-Date: 2025-04-21 11:24+0000\n" +"Last-Translator: FULL NAME \n" +"Language: en\n" +"Language-Team: en \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: app.py:93 +msgid "Invalid credentials" +msgstr "" + +#: app.py:102 +msgid "Username already exists" +msgstr "" + +#: app.py:147 +msgid "Game added successfully!" +msgstr "" + +#: app.py:151 app.py:186 +msgid "Error: " +msgstr "" + +#: app.py:160 app.py:198 +msgid "Not allowed!" +msgstr "" + +#: app.py:181 +msgid "Changes saved!" +msgstr "" + +#: app.py:202 +msgid "Game deleted!" +msgstr "" + +#: app.py:205 +msgid "Error deleting: " +msgstr "" + +#: templates/add_game.html:4 templates/index.html:6 +msgid "Add New Game" +msgstr "" + +#: templates/add_game.html:8 templates/edit_game.html:8 templates/index.html:16 +msgid "Name" +msgstr "" + +#: templates/add_game.html:12 templates/edit_game.html:12 +msgid "Steam Key" +msgstr "" + +#: templates/add_game.html:16 templates/edit_game.html:20 +#: templates/index.html:18 +msgid "Status" +msgstr "" + +#: templates/add_game.html:18 templates/edit_game.html:22 +#: templates/index.html:38 +msgid "Not redeemed" +msgstr "" + +#: templates/add_game.html:19 templates/edit_game.html:23 +#: templates/index.html:40 +msgid "Gifted" +msgstr "" + +#: templates/add_game.html:20 templates/edit_game.html:24 +#: templates/index.html:42 +msgid "Redeemed" +msgstr "" + +#: templates/add_game.html:24 templates/edit_game.html:28 +#: templates/index.html:20 +msgid "Redeem by" +msgstr "" + +#: templates/add_game.html:28 templates/edit_game.html:32 +msgid "Recipient" +msgstr "" + +#: templates/add_game.html:32 templates/edit_game.html:36 +msgid "Shop URL" +msgstr "" + +#: templates/add_game.html:36 templates/edit_game.html:40 +msgid "Notes" +msgstr "" + +#: templates/add_game.html:40 templates/edit_game.html:44 +msgid "Save" +msgstr "" + +#: templates/add_game.html:41 templates/edit_game.html:45 +msgid "Cancel" +msgstr "" + +#: templates/base.html:6 templates/base.html:13 +msgid "Steam Manager" +msgstr "" + +#: templates/base.html:19 +msgid "Search" +msgstr "" + +#: templates/base.html:27 +msgid "Dark Mode" +msgstr "" + +#: templates/base.html:48 +msgid "Logout" +msgstr "" + +#: templates/edit_game.html:4 +msgid "Edit Game" +msgstr "" + +#: templates/edit_game.html:16 +msgid "Steam AppID (optional)" +msgstr "" + +#: templates/index.html:4 +msgid "My Games" +msgstr "" + +#: templates/index.html:15 +msgid "Cover" +msgstr "" + +#: templates/index.html:17 +msgid "Key" +msgstr "" + +#: templates/index.html:19 +msgid "Created" +msgstr "" + +#: templates/index.html:21 templates/index.html:53 +msgid "Shop" +msgstr "" + +#: templates/index.html:22 +msgid "Actions" +msgstr "" + +#: templates/index.html:59 +msgid "Really delete?" +msgstr "" + +#: templates/index.html:68 +msgid "No games yet" +msgstr "" + +#: templates/login.html:7 templates/login.html:17 +msgid "Login" +msgstr "" + +#: templates/login.html:10 templates/register.html:10 +msgid "Username" +msgstr "" + +#: templates/login.html:14 templates/register.html:14 +msgid "Password" +msgstr "" + +#: templates/login.html:20 +msgid "No account yet? Register" +msgstr "" + +#: templates/register.html:7 templates/register.html:17 +msgid "Register" +msgstr "" + diff --git a/steam-translations/messages.pot b/steam-translations/messages.pot new file mode 100644 index 0000000..8f32f79 --- /dev/null +++ b/steam-translations/messages.pot @@ -0,0 +1,184 @@ +# Translations template for PROJECT. +# Copyright (C) 2025 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2025. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2025-04-21 11:24+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +#: app.py:93 +msgid "Invalid credentials" +msgstr "" + +#: app.py:102 +msgid "Username already exists" +msgstr "" + +#: app.py:147 +msgid "Game added successfully!" +msgstr "" + +#: app.py:151 app.py:186 +msgid "Error: " +msgstr "" + +#: app.py:160 app.py:198 +msgid "Not allowed!" +msgstr "" + +#: app.py:181 +msgid "Changes saved!" +msgstr "" + +#: app.py:202 +msgid "Game deleted!" +msgstr "" + +#: app.py:205 +msgid "Error deleting: " +msgstr "" + +#: templates/add_game.html:4 templates/index.html:6 +msgid "Add New Game" +msgstr "" + +#: templates/add_game.html:8 templates/edit_game.html:8 templates/index.html:16 +msgid "Name" +msgstr "" + +#: templates/add_game.html:12 templates/edit_game.html:12 +msgid "Steam Key" +msgstr "" + +#: templates/add_game.html:16 templates/edit_game.html:20 +#: templates/index.html:18 +msgid "Status" +msgstr "" + +#: templates/add_game.html:18 templates/edit_game.html:22 +#: templates/index.html:38 +msgid "Not redeemed" +msgstr "" + +#: templates/add_game.html:19 templates/edit_game.html:23 +#: templates/index.html:40 +msgid "Gifted" +msgstr "" + +#: templates/add_game.html:20 templates/edit_game.html:24 +#: templates/index.html:42 +msgid "Redeemed" +msgstr "" + +#: templates/add_game.html:24 templates/edit_game.html:28 +#: templates/index.html:20 +msgid "Redeem by" +msgstr "" + +#: templates/add_game.html:28 templates/edit_game.html:32 +msgid "Recipient" +msgstr "" + +#: templates/add_game.html:32 templates/edit_game.html:36 +msgid "Shop URL" +msgstr "" + +#: templates/add_game.html:36 templates/edit_game.html:40 +msgid "Notes" +msgstr "" + +#: templates/add_game.html:40 templates/edit_game.html:44 +msgid "Save" +msgstr "" + +#: templates/add_game.html:41 templates/edit_game.html:45 +msgid "Cancel" +msgstr "" + +#: templates/base.html:6 templates/base.html:13 +msgid "Steam Manager" +msgstr "" + +#: templates/base.html:19 +msgid "Search" +msgstr "" + +#: templates/base.html:27 +msgid "Dark Mode" +msgstr "" + +#: templates/base.html:48 +msgid "Logout" +msgstr "" + +#: templates/edit_game.html:4 +msgid "Edit Game" +msgstr "" + +#: templates/edit_game.html:16 +msgid "Steam AppID (optional)" +msgstr "" + +#: templates/index.html:4 +msgid "My Games" +msgstr "" + +#: templates/index.html:15 +msgid "Cover" +msgstr "" + +#: templates/index.html:17 +msgid "Key" +msgstr "" + +#: templates/index.html:19 +msgid "Created" +msgstr "" + +#: templates/index.html:21 templates/index.html:53 +msgid "Shop" +msgstr "" + +#: templates/index.html:22 +msgid "Actions" +msgstr "" + +#: templates/index.html:59 +msgid "Really delete?" +msgstr "" + +#: templates/index.html:68 +msgid "No games yet" +msgstr "" + +#: templates/login.html:7 templates/login.html:17 +msgid "Login" +msgstr "" + +#: templates/login.html:10 templates/register.html:10 +msgid "Username" +msgstr "" + +#: templates/login.html:14 templates/register.html:14 +msgid "Password" +msgstr "" + +#: templates/login.html:20 +msgid "No account yet? Register" +msgstr "" + +#: templates/register.html:7 templates/register.html:17 +msgid "Register" +msgstr "" + diff --git a/translate.sh b/translate.sh new file mode 100755 index 0000000..b54d8f6 --- /dev/null +++ b/translate.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +cd "$(dirname "$0")/steam-gift-manager" + +# 1. Extrahiere alle Texte +docker-compose exec steam-manager pybabel extract -F babel.cfg -o translations/messages.pot . + +# 2. Initialisiere Sprachen (nur einmal nötig, danach auskommentieren) +for lang in de en; do + if [ ! -f "../steam-translations/$lang/LC_MESSAGES/messages.po" ]; then + docker-compose exec steam-manager pybabel init -i translations/messages.pot -d translations -l $lang + fi +done + +# 3. Aktualisiere Übersetzungen +docker-compose exec steam-manager pybabel update -i translations/messages.pot -d translations + +# 4. Kompiliere Übersetzungen +docker-compose exec steam-manager pybabel compile -d translations + +echo "✅ Übersetzungen extrahiert, aktualisiert und kompiliert!"