Compare commits
	
		
			2 commits
		
	
	
		
			9fde7cd75e
			...
			545020609a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 545020609a | |||
| a02bed57ff | 
					 1 changed files with 45 additions and 67 deletions
				
			
		
							
								
								
									
										110
									
								
								setup.sh
									
										
									
									
									
								
							
							
						
						
									
										110
									
								
								setup.sh
									
										
									
									
									
								
							| 
						 | 
					@ -157,7 +157,6 @@ warnings.simplefilter("ignore", category=LegacyAPIWarning)
 | 
				
			||||||
from flask import Flask, render_template, request, redirect, url_for, flash, make_response, session, abort, send_file, jsonify
 | 
					from flask import Flask, render_template, request, redirect, url_for, flash, make_response, session, abort, send_file, jsonify
 | 
				
			||||||
from flask_sqlalchemy import SQLAlchemy
 | 
					from flask_sqlalchemy import SQLAlchemy
 | 
				
			||||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
 | 
					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 werkzeug.security import generate_password_hash, check_password_hash
 | 
				
			||||||
from datetime import datetime, timedelta
 | 
					from datetime import datetime, timedelta
 | 
				
			||||||
from flask_wtf import CSRFProtect
 | 
					from flask_wtf import CSRFProtect
 | 
				
			||||||
| 
						 | 
					@ -195,19 +194,24 @@ from io import BytesIO
 | 
				
			||||||
import reportlab.lib
 | 
					import reportlab.lib
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
logging.basicConfig()
 | 
					logging.basicConfig()
 | 
				
			||||||
logging.getLogger('babel').setLevel(logging.DEBUG)
 | 
					 | 
				
			||||||
app = Flask(__name__)
 | 
					app = Flask(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Load Languages
 | 
					# Load Languages
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TRANSLATIONS = {}
 | 
					TRANSLATIONS = {}
 | 
				
			||||||
for lang in app.config['SUPPORTED_LANGUAGES'].split(','):
 | 
					SUPPORTED_LANGUAGES = os.getenv('SUPPORTED_LANGUAGES', 'en').split(',')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for lang in SUPPORTED_LANGUAGES:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        with open(f'translations/{lang}.json') as f:
 | 
					        with open(f'translations/{lang}.json', encoding='utf-8') as f:
 | 
				
			||||||
            TRANSLATIONS[lang] = json.load(f)
 | 
					            TRANSLATIONS[lang] = json.load(f)
 | 
				
			||||||
    except:
 | 
					    except Exception:
 | 
				
			||||||
        TRANSLATIONS[lang] = {}
 | 
					        TRANSLATIONS[lang] = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def translate(key, lang=app.config['DEFAULT_LANGUAGE'], **kwargs):
 | 
					def translate(key, lang=None, **kwargs):
 | 
				
			||||||
 | 
					    if not lang:
 | 
				
			||||||
 | 
					        lang = session.get('lang', os.getenv('DEFAULT_LANGUAGE', 'en'))
 | 
				
			||||||
    return TRANSLATIONS.get(lang, {}).get(key, key).format(**kwargs)
 | 
					    return TRANSLATIONS.get(lang, {}).get(key, key).format(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
csrf = CSRFProtect(app)
 | 
					csrf = CSRFProtect(app)
 | 
				
			||||||
| 
						 | 
					@ -231,9 +235,6 @@ app.config.update(
 | 
				
			||||||
    SECRET_KEY=os.getenv('SECRET_KEY'),
 | 
					    SECRET_KEY=os.getenv('SECRET_KEY'),
 | 
				
			||||||
    SQLALCHEMY_DATABASE_URI='sqlite:////app/data/games.db',
 | 
					    SQLALCHEMY_DATABASE_URI='sqlite:////app/data/games.db',
 | 
				
			||||||
    SQLALCHEMY_TRACK_MODIFICATIONS=False,
 | 
					    SQLALCHEMY_TRACK_MODIFICATIONS=False,
 | 
				
			||||||
    BABEL_DEFAULT_LOCALE=os.getenv('BABEL_DEFAULT_LOCALE', 'en'),
 | 
					 | 
				
			||||||
    BABEL_SUPPORTED_LOCALES=os.getenv('BABEL_SUPPORTED_LOCALES', 'de,en').split(','),
 | 
					 | 
				
			||||||
    BABEL_TRANSLATION_DIRECTORIES=os.path.join(app.root_path, 'translations'),
 | 
					 | 
				
			||||||
    SESSION_COOKIE_SECURE=os.getenv('SESSION_COOKIE_SECURE', 'False') == 'True',
 | 
					    SESSION_COOKIE_SECURE=os.getenv('SESSION_COOKIE_SECURE', 'False') == 'True',
 | 
				
			||||||
    SESSION_COOKIE_SAMESITE='Lax',
 | 
					    SESSION_COOKIE_SAMESITE='Lax',
 | 
				
			||||||
    PERMANENT_SESSION_LIFETIME=timedelta(days=30),
 | 
					    PERMANENT_SESSION_LIFETIME=timedelta(days=30),
 | 
				
			||||||
| 
						 | 
					@ -251,17 +252,11 @@ db = SQLAlchemy(app, metadata=metadata)
 | 
				
			||||||
migrate = Migrate(app, db)
 | 
					migrate = Migrate(app, db)
 | 
				
			||||||
login_manager = LoginManager(app)
 | 
					login_manager = LoginManager(app)
 | 
				
			||||||
login_manager.login_view = 'login'
 | 
					login_manager.login_view = 'login'
 | 
				
			||||||
babel = Babel(app)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Logging
 | 
					# Logging
 | 
				
			||||||
app.logger.addHandler(logging.StreamHandler())
 | 
					app.logger.addHandler(logging.StreamHandler())
 | 
				
			||||||
app.logger.setLevel(logging.INFO)
 | 
					app.logger.setLevel(logging.INFO)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@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.before_request
 | 
					@app.before_request
 | 
				
			||||||
def enforce_https():
 | 
					def enforce_https():
 | 
				
			||||||
| 
						 | 
					@ -271,20 +266,14 @@ def enforce_https():
 | 
				
			||||||
            url = request.url.replace('http://', 'https://', 1)
 | 
					            url = request.url.replace('http://', 'https://', 1)
 | 
				
			||||||
            return redirect(url, code=301)
 | 
					            return redirect(url, code=301)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def reload_translations():
 | 
					 | 
				
			||||||
    if app.config['DEBUG']:
 | 
					 | 
				
			||||||
        babel.reload()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@app.context_processor
 | 
					@app.context_processor
 | 
				
			||||||
def inject_translations():
 | 
					 | 
				
			||||||
    def _(key, **kwargs):
 | 
					 | 
				
			||||||
        lang = session.get('lang', app.config['DEFAULT_LANGUAGE'])
 | 
					 | 
				
			||||||
        return translate(key, lang, **kwargs)
 | 
					 | 
				
			||||||
    return {'_': _}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def inject_template_vars():
 | 
					def inject_template_vars():
 | 
				
			||||||
 | 
					    def _(key, **kwargs):
 | 
				
			||||||
 | 
					        lang = session.get('lang', os.getenv('DEFAULT_LANGUAGE', 'en'))
 | 
				
			||||||
 | 
					        return translate(key, lang, **kwargs)
 | 
				
			||||||
    return dict(
 | 
					    return dict(
 | 
				
			||||||
        get_locale=get_locale,
 | 
					        _=_,
 | 
				
			||||||
 | 
					        get_locale=lambda: session.get('lang', os.getenv('DEFAULT_LANGUAGE', 'en')),
 | 
				
			||||||
        theme='dark' if request.cookies.get('dark_mode') == 'true' else 'light'
 | 
					        theme='dark' if request.cookies.get('dark_mode') == 'true' else 'light'
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -353,9 +342,9 @@ def index():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.route('/set-lang/<lang>')
 | 
					@app.route('/set-lang/<lang>')
 | 
				
			||||||
def set_lang(lang):
 | 
					def set_lang(lang):
 | 
				
			||||||
    if lang in app.config['SUPPORTED_LANGUAGES'].split(','):
 | 
					    if lang in SUPPORTED_LANGUAGES:
 | 
				
			||||||
        session['lang'] = lang
 | 
					        session['lang'] = lang
 | 
				
			||||||
    return redirect(request.referrer)
 | 
					    return redirect(request.referrer or url_for('index'))
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@app.route('/set-theme/<theme>')
 | 
					@app.route('/set-theme/<theme>')
 | 
				
			||||||
def set_theme(theme):
 | 
					def set_theme(theme):
 | 
				
			||||||
| 
						 | 
					@ -754,13 +743,6 @@ def redeem_page(token):
 | 
				
			||||||
                         redeem_token=redeem_token,
 | 
					                         redeem_token=redeem_token,
 | 
				
			||||||
                         platform_link='https://store.steampowered.com/account/registerkey?key=' if game.steam_appid else 'https://www.gog.com/redeem')
 | 
					                         platform_link='https://store.steampowered.com/account/registerkey?key=' if game.steam_appid else 'https://www.gog.com/redeem')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.route('/debug-session')
 | 
					 | 
				
			||||||
def debug_session():
 | 
					 | 
				
			||||||
    return jsonify({
 | 
					 | 
				
			||||||
        'session_lang': session.get('lang'),
 | 
					 | 
				
			||||||
        'config_locales': app.config['BABEL_SUPPORTED_LOCALES']
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Apprise Notifications
 | 
					# Apprise Notifications
 | 
				
			||||||
import apprise
 | 
					import apprise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -830,13 +812,6 @@ if __name__ == '__main__':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PYTHON_END
 | 
					PYTHON_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Create Babel configuration
 | 
					 | 
				
			||||||
cat <<EOL > babel.cfg
 | 
					 | 
				
			||||||
[python: **.py]
 | 
					 | 
				
			||||||
[jinja2: **/templates/**.html]
 | 
					 | 
				
			||||||
extensions=jinja2.ext.autoescape,jinja2.ext.with_
 | 
					 | 
				
			||||||
EOL
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# 5. Dockerfile
 | 
					# 5. Dockerfile
 | 
				
			||||||
cat <<DOCKER_END > Dockerfile
 | 
					cat <<DOCKER_END > Dockerfile
 | 
				
			||||||
FROM python:3.10-slim
 | 
					FROM python:3.10-slim
 | 
				
			||||||
| 
						 | 
					@ -927,35 +902,38 @@ cat <<'SCRIPT_END' > ../translate.sh
 | 
				
			||||||
#!/bin/bash
 | 
					#!/bin/bash
 | 
				
			||||||
set -e
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd "$(dirname "$0")/steam-gift-manager"
 | 
					# Directories and languages
 | 
				
			||||||
 | 
					TRANSLATION_DIR="./translations"
 | 
				
			||||||
 | 
					LANGS=("de" "en")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
declare -a locales=("de" "en")
 | 
					# 1. Create JSON files if they do not yet exist
 | 
				
			||||||
 | 
					for lang in "${LANGS[@]}"; do
 | 
				
			||||||
docker-compose run --rm steam-manager pybabel extract -F babel.cfg -o translations/messages.pot .
 | 
					  file="$TRANSLATION_DIR/$lang.json"
 | 
				
			||||||
 | 
					  if [ ! -f "$file" ]; then
 | 
				
			||||||
for lang in "${locales[@]}"; do
 | 
					    echo "{}" > "$file"
 | 
				
			||||||
  po_path="translations/${lang}/LC_MESSAGES/messages.po"
 | 
					    echo "Created $file"
 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  if [ -f "$po_path" ]; then
 | 
					 | 
				
			||||||
    encoding=$(file -i "$po_path" | grep -Po 'charset=\K.+')
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if [[ "$encoding" != "utf-8" ]]; then
 | 
					 | 
				
			||||||
      echo "Konvertiere $po_path von $encoding nach UTF-8"
 | 
					 | 
				
			||||||
      iconv -f "$encoding" -t UTF-8 "$po_path" > "$po_path.utf8"
 | 
					 | 
				
			||||||
      mv "$po_path.utf8" "$po_path"
 | 
					 | 
				
			||||||
  fi
 | 
					  fi
 | 
				
			||||||
  fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  docker-compose run --rm steam-manager pybabel update \
 | 
					 | 
				
			||||||
    -i translations/messages.pot \
 | 
					 | 
				
			||||||
    -d translations \
 | 
					 | 
				
			||||||
    -l "$lang" \
 | 
					 | 
				
			||||||
    --previous
 | 
					 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
docker-compose run --rm steam-manager pybabel compile -d translations
 | 
					# 2. Extract all strings to be translated from the templates and Python files
 | 
				
			||||||
 | 
					STRINGS=$(grep -hoR "_('\([^']*\)')" ./templates ./app.py | sed "s/.*_('\([^']*\)').*/\1/" | sort | uniq)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "✅ Setup and/or update translations done! YOLO"
 | 
					# 3. Insert new keys into the JSON files without overwriting existing translations
 | 
				
			||||||
 | 
					for lang in "${LANGS[@]}"; do
 | 
				
			||||||
 | 
					  file="$TRANSLATION_DIR/$lang.json"
 | 
				
			||||||
 | 
					  tmp="$file.tmp"
 | 
				
			||||||
 | 
					  cp "$file" "$tmp"
 | 
				
			||||||
 | 
					  for key in $STRINGS; do
 | 
				
			||||||
 | 
					    # Prüfe, ob der Key schon existiert
 | 
				
			||||||
 | 
					    if ! jq -e --arg k "$key" 'has($k)' "$tmp" >/dev/null; then
 | 
				
			||||||
 | 
					      jq --arg k "$key" '. + {($k): ""}' "$tmp" > "$tmp.new" && mv "$tmp.new" "$tmp"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					  done
 | 
				
			||||||
 | 
					  mv "$tmp" "$file"
 | 
				
			||||||
 | 
					  echo "Updated $file"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "✅ JSON translation files updated. Please enter your translations!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SCRIPT_END
 | 
					SCRIPT_END
 | 
				
			||||||
chmod +x ../translate.sh
 | 
					chmod +x ../translate.sh
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue