From 9c053b50217ec07a00c72ea78485d625e9b03a0e Mon Sep 17 00:00:00 2001 From: sqozz Date: Fri, 29 Dec 2017 08:03:17 +0100 Subject: [PATCH] Add translation capability --- .gitignore | 2 + HACKING.md | 10 + babel.cfg | 6 + indexer.py | 57 +++--- requirements.txt | 2 + static/js/create.js | 3 +- static/js/main.js | 17 -- strings.json | 46 ----- templates/categories.html | 2 +- templates/create.html | 38 ++-- templates/details.html | 2 +- templates/index.html | 7 +- templates/result.html | 18 +- templates/search.html | 6 +- translations/de/LC_MESSAGES/messages.po | 258 ++++++++++++++++++++++++ 15 files changed, 342 insertions(+), 132 deletions(-) create mode 100644 HACKING.md create mode 100644 babel.cfg delete mode 100644 strings.json create mode 100644 translations/de/LC_MESSAGES/messages.po diff --git a/.gitignore b/.gitignore index 1fd8db3..b2907b5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ *.swp *.swo +*.mo +*.pot backup uploadTest torrentFiles/* diff --git a/HACKING.md b/HACKING.md new file mode 100644 index 0000000..22a31ce --- /dev/null +++ b/HACKING.md @@ -0,0 +1,10 @@ +Localization +===== + 1) Mark all translatable strings by wrapping them in gettext() (or \_()) + 2) Extract all those strings: + pybabel extract -F babel.cfg -o messages.pot . + 3) Update the language-specific translation files: + pybabel update -i messages.pot -d translations/ -l [LANGCODE] + 4) Translate the strings in the generated .po files using your favourite editor + 5) Compile the .po files to .mo files: + pybabel compile -d translations diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000..39539aa --- /dev/null +++ b/babel.cfg @@ -0,0 +1,6 @@ +[ignore: venv/**] + +[python: **.py] +[jinja2: **/templates/**.html] +[json: **.json] +extensions=jinja2.ext.autoescape,jinja2.ext.with_ diff --git a/indexer.py b/indexer.py index 6c5cf2e..3d10846 100644 --- a/indexer.py +++ b/indexer.py @@ -5,35 +5,43 @@ from hashlib import sha1 import bencoder import requests from flask import Flask, render_template, url_for, request, send_file, redirect +from flask_babel import Babel, gettext as _, lazy_gettext from werkzeug import secure_filename from hurry.filesize import size app = Flask(__name__) -strings = None +babel = Babel(app) + +LANGUAGES = ['en', 'de'] + settings = None def get_categories(): - return settings["categories"] + cats = settings["categories"] + for c in cats: + c["label"] = str(lazy_gettext(c["label"])) + for s in c["subcategories"]: + s["label"] = str(lazy_gettext(s["label"])) + return cats @app.route("/") def index(): - return render_template("search.html", language="english", categories=get_categories(), strings=strings) + return render_template("search.html", categories=get_categories()) @app.route("/categories") def categorys(): - global strings - return render_template("categories.html", categories=get_categories(), strings=strings) + return render_template("categories.html", categories=get_categories()) @app.route("/create", methods=['GET','POST']) def create(): if request.method == "GET": - return render_template("create.html", language="english", categories=get_categories(), strings=strings, errors=None) + return render_template("create.html", categories=get_categories(), errors=None) elif request.method == "POST": newTorrent = createNewTorrent(request) if len(newTorrent.errors) == 0: - message = "Successfully created torrent {}".format(newTorrent.fileid, newTorrent.fileid[:-20]) - return render_template("create.html", language="english", categories=get_categories(), strings=strings, messages=[message]) + message = _("Successfully created torrent {}").format(newTorrent.fileid, newTorrent.fileid[:-20]) + return render_template("create.html", categories=get_categories(), messages=[message]) else: - return render_template("create.html", language="english", categories=get_categories(), strings=strings, errors=newTorrent.errors) + return render_template("create.html", categories=get_categories(), errors=newTorrent.errors) @app.route("/download/") def download(filename): @@ -45,8 +53,6 @@ def download(filename): @app.route("/search", methods=['GET']) def search(): - global strings - print(strings) connection = sqlite3.connect("torrentdb.sqlite") c = connection.cursor() @@ -80,13 +86,13 @@ def search(): r = row[0:2] + (size(float(row[2])) , ) + row[3:] results.append(r) - return render_template("result.html", results=results, strings=strings, language="english", categories=get_categories()) + return render_template("result.html", results=results, categories=get_categories()) @app.route("/details", methods=['GET']) def details(): info_hash = request.args["h"] print(info_hash) - return render_template("details.html", strings=strings, language="english", categories=get_categories()) + return render_template("details.html", categories=get_categories()) def scrapeAll(): TRACKER_URL = "http://tracker.lootbox.cf:6969/" @@ -95,11 +101,7 @@ def scrapeAll(): return def init(): - global strings global settings - with open("strings.json") as stringsJson: - strings = json.load(stringsJson) - with open("settings.json") as settingsJson: settings = json.load(settingsJson) initDb() @@ -113,16 +115,6 @@ def initDb(): connection.commit() connection.close() -def getLocalString(language, descriptor): - global strings - if language in strings.keys(): - if descriptor in strings[language].keys(): - return strings[language][descriptor] - else: - return descriptor - else: - return descriptor - def createNewTorrent(reuqest): uploadfile = request.files["torrentFile"] filename = secure_filename(uploadfile.filename) @@ -133,7 +125,7 @@ def createNewTorrent(reuqest): with open("torrentFiles/" + info_hash, "wb") as torrent_file: torrent_file.write(content) - + bcoded = bencoder.decode(content) size = ((len(bcoded[b'info'][b'pieces']) / 20) * bcoded[b'info'][b'piece length']) / 1024 / 1024 @@ -160,9 +152,9 @@ def createNewTorrent(reuqest): connection.close() except sqlite3.IntegrityError as e: print(e) - newTFile.errors = ["Torrent {} already exists".format(info_hash, info_hash[:-20])] + newTFile.errors = [_("Torrent {} already exists").format(info_hash, info_hash[:-20])] except Exception as e: - newTFile.errors = ["Unknown error in creation"] + newTFile.errors = [_("Unknown error in creation")] return newTFile @@ -214,9 +206,12 @@ class TorrentFile(): b64videoquality_description = base64.b64encode(self.videoquality_description.encode()) c.execute("INSERT INTO torrents(fileid, name, category, subcategory, description, audioquality_description, videoquality_description) VALUES(:fileid, :name, :category, :subcategory, :description, :audioquality_description, :videoquality_description)", { 'fileid' : self.fileid, 'name' : self.name, 'category' : self.category, 'subcategory' : self.subcategory, 'description' : b64description , 'audioquality_description' : b64audioquality_description, 'videoquality_description' : b64videoquality_description}) +@babel.localeselector +def get_locale(): + return request.accept_languages.best_match(LANGUAGES) + if __name__ == "__main__": init() - app.jinja_env.globals.update(getLocalString=getLocalString) app.jinja_env.globals.update(json=json) app.jinja_env.globals.update(sorted=sorted) app.run(debug=True, host="127.0.0.1") diff --git a/requirements.txt b/requirements.txt index 065179c..fc7ccff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ bencoder==0.2.0 requests==2.18.2 hurry.filesize==0.9 +Flask-Babel==0.11.2 +PyBabel-json==0.2.0 diff --git a/static/js/create.js b/static/js/create.js index 6029207..a6870db 100644 --- a/static/js/create.js +++ b/static/js/create.js @@ -75,8 +75,9 @@ function fillDetectedFilelist(file) { function fillSubcategory(value) { var subSelect = $('#subcategory') + var selText = $(':first-child', subSelect).text() subSelect.empty(); - subSelect.append($('