Add translation capability
This commit is contained in:
parent
2c220afced
commit
9c053b5021
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,7 @@
|
|||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
backup
|
backup
|
||||||
uploadTest
|
uploadTest
|
||||||
torrentFiles/*
|
torrentFiles/*
|
||||||
|
10
HACKING.md
Normal file
10
HACKING.md
Normal file
@ -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
|
6
babel.cfg
Normal file
6
babel.cfg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[ignore: venv/**]
|
||||||
|
|
||||||
|
[python: **.py]
|
||||||
|
[jinja2: **/templates/**.html]
|
||||||
|
[json: **.json]
|
||||||
|
extensions=jinja2.ext.autoescape,jinja2.ext.with_
|
55
indexer.py
55
indexer.py
@ -5,35 +5,43 @@ from hashlib import sha1
|
|||||||
import bencoder
|
import bencoder
|
||||||
import requests
|
import requests
|
||||||
from flask import Flask, render_template, url_for, request, send_file, redirect
|
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 werkzeug import secure_filename
|
||||||
from hurry.filesize import size
|
from hurry.filesize import size
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
strings = None
|
babel = Babel(app)
|
||||||
|
|
||||||
|
LANGUAGES = ['en', 'de']
|
||||||
|
|
||||||
settings = None
|
settings = None
|
||||||
|
|
||||||
def get_categories():
|
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("/")
|
@app.route("/")
|
||||||
def index():
|
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")
|
@app.route("/categories")
|
||||||
def categorys():
|
def categorys():
|
||||||
global strings
|
return render_template("categories.html", categories=get_categories())
|
||||||
return render_template("categories.html", categories=get_categories(), strings=strings)
|
|
||||||
|
|
||||||
@app.route("/create", methods=['GET','POST'])
|
@app.route("/create", methods=['GET','POST'])
|
||||||
def create():
|
def create():
|
||||||
if request.method == "GET":
|
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":
|
elif request.method == "POST":
|
||||||
newTorrent = createNewTorrent(request)
|
newTorrent = createNewTorrent(request)
|
||||||
if len(newTorrent.errors) == 0:
|
if len(newTorrent.errors) == 0:
|
||||||
message = "Successfully created torrent <a href=\"/search?h={}\">{}</a>".format(newTorrent.fileid, newTorrent.fileid[:-20])
|
message = _("Successfully created torrent <a href=\"/search?h={}\">{}</a>").format(newTorrent.fileid, newTorrent.fileid[:-20])
|
||||||
return render_template("create.html", language="english", categories=get_categories(), strings=strings, messages=[message])
|
return render_template("create.html", categories=get_categories(), messages=[message])
|
||||||
else:
|
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/<filename>")
|
@app.route("/download/<filename>")
|
||||||
def download(filename):
|
def download(filename):
|
||||||
@ -45,8 +53,6 @@ def download(filename):
|
|||||||
|
|
||||||
@app.route("/search", methods=['GET'])
|
@app.route("/search", methods=['GET'])
|
||||||
def search():
|
def search():
|
||||||
global strings
|
|
||||||
print(strings)
|
|
||||||
connection = sqlite3.connect("torrentdb.sqlite")
|
connection = sqlite3.connect("torrentdb.sqlite")
|
||||||
c = connection.cursor()
|
c = connection.cursor()
|
||||||
|
|
||||||
@ -80,13 +86,13 @@ def search():
|
|||||||
r = row[0:2] + (size(float(row[2])) , ) + row[3:]
|
r = row[0:2] + (size(float(row[2])) , ) + row[3:]
|
||||||
results.append(r)
|
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'])
|
@app.route("/details", methods=['GET'])
|
||||||
def details():
|
def details():
|
||||||
info_hash = request.args["h"]
|
info_hash = request.args["h"]
|
||||||
print(info_hash)
|
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():
|
def scrapeAll():
|
||||||
TRACKER_URL = "http://tracker.lootbox.cf:6969/"
|
TRACKER_URL = "http://tracker.lootbox.cf:6969/"
|
||||||
@ -95,11 +101,7 @@ def scrapeAll():
|
|||||||
return
|
return
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
global strings
|
|
||||||
global settings
|
global settings
|
||||||
with open("strings.json") as stringsJson:
|
|
||||||
strings = json.load(stringsJson)
|
|
||||||
|
|
||||||
with open("settings.json") as settingsJson:
|
with open("settings.json") as settingsJson:
|
||||||
settings = json.load(settingsJson)
|
settings = json.load(settingsJson)
|
||||||
initDb()
|
initDb()
|
||||||
@ -113,16 +115,6 @@ def initDb():
|
|||||||
connection.commit()
|
connection.commit()
|
||||||
connection.close()
|
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):
|
def createNewTorrent(reuqest):
|
||||||
uploadfile = request.files["torrentFile"]
|
uploadfile = request.files["torrentFile"]
|
||||||
filename = secure_filename(uploadfile.filename)
|
filename = secure_filename(uploadfile.filename)
|
||||||
@ -160,9 +152,9 @@ def createNewTorrent(reuqest):
|
|||||||
connection.close()
|
connection.close()
|
||||||
except sqlite3.IntegrityError as e:
|
except sqlite3.IntegrityError as e:
|
||||||
print(e)
|
print(e)
|
||||||
newTFile.errors = ["Torrent <a href=\"/search?h={}\">{}</a> already exists".format(info_hash, info_hash[:-20])]
|
newTFile.errors = [_("Torrent <a href=\"/search?h={}\">{}</a> already exists").format(info_hash, info_hash[:-20])]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
newTFile.errors = ["Unknown error in creation"]
|
newTFile.errors = [_("Unknown error in creation")]
|
||||||
|
|
||||||
return newTFile
|
return newTFile
|
||||||
|
|
||||||
@ -214,9 +206,12 @@ class TorrentFile():
|
|||||||
b64videoquality_description = base64.b64encode(self.videoquality_description.encode())
|
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})
|
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__":
|
if __name__ == "__main__":
|
||||||
init()
|
init()
|
||||||
app.jinja_env.globals.update(getLocalString=getLocalString)
|
|
||||||
app.jinja_env.globals.update(json=json)
|
app.jinja_env.globals.update(json=json)
|
||||||
app.jinja_env.globals.update(sorted=sorted)
|
app.jinja_env.globals.update(sorted=sorted)
|
||||||
app.run(debug=True, host="127.0.0.1")
|
app.run(debug=True, host="127.0.0.1")
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
bencoder==0.2.0
|
bencoder==0.2.0
|
||||||
requests==2.18.2
|
requests==2.18.2
|
||||||
hurry.filesize==0.9
|
hurry.filesize==0.9
|
||||||
|
Flask-Babel==0.11.2
|
||||||
|
PyBabel-json==0.2.0
|
||||||
|
|
||||||
|
@ -75,8 +75,9 @@ function fillDetectedFilelist(file) {
|
|||||||
|
|
||||||
function fillSubcategory(value) {
|
function fillSubcategory(value) {
|
||||||
var subSelect = $('#subcategory')
|
var subSelect = $('#subcategory')
|
||||||
|
var selText = $(':first-child', subSelect).text()
|
||||||
subSelect.empty();
|
subSelect.empty();
|
||||||
subSelect.append($('<option value="-1" selected>--- Select Subcategory ---</selected>'))
|
subSelect.append($('<option value="-1" selected>'+selText+'</selected>'))
|
||||||
if (value >= 0) {
|
if (value >= 0) {
|
||||||
var subcategories = null
|
var subcategories = null
|
||||||
for(var i = 0; i < global_categories.length; i++) {
|
for(var i = 0; i < global_categories.length; i++) {
|
||||||
|
@ -1,20 +1,3 @@
|
|||||||
function getLocalString(language, descriptor){
|
|
||||||
if(global_strings[language]){
|
|
||||||
return global_strings[language][descriptor] || global_strings["english"][descriptor] || descriptor
|
|
||||||
} else {
|
|
||||||
return descriptor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDescriptorByLocalString(language, localString){
|
|
||||||
for(string in global_strings[language]){
|
|
||||||
if(global_strings[language][string] == localString){
|
|
||||||
return string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return localString
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNextUnit(bSize) {
|
function getNextUnit(bSize) {
|
||||||
units = ["B", "kB", "MB", "GB", "TB", "PB", "To damn high"]
|
units = ["B", "kB", "MB", "GB", "TB", "PB", "To damn high"]
|
||||||
iters = 0
|
iters = 0
|
||||||
|
46
strings.json
46
strings.json
@ -1,46 +0,0 @@
|
|||||||
{
|
|
||||||
"english" : {
|
|
||||||
"audio" : "Audio",
|
|
||||||
"lossless" : "Lossless",
|
|
||||||
"lossy" : "Lossy",
|
|
||||||
"audiobooks" : "Audiobooks",
|
|
||||||
"other" : "Other",
|
|
||||||
"video" : "Video",
|
|
||||||
"movies_3d" : "Movies 3D",
|
|
||||||
"movies_4k" : "Movies 4K",
|
|
||||||
"movies_hd" : "Movies HD",
|
|
||||||
"movies_sd" : "Movies SD",
|
|
||||||
"series_hd" : "Series HD",
|
|
||||||
"series_sd" : "Series SD",
|
|
||||||
"clips" : "Clips",
|
|
||||||
"other" : "Other",
|
|
||||||
"porn" : "Porn",
|
|
||||||
"pictures" : "Pictures",
|
|
||||||
"games" : "Games",
|
|
||||||
"pc" : "PC",
|
|
||||||
"mac" : "Mac",
|
|
||||||
"ios" : "iOS",
|
|
||||||
"android" : "Android",
|
|
||||||
"consoles" : "Consoles",
|
|
||||||
"applications" : "Applications",
|
|
||||||
"windows" : "Windows",
|
|
||||||
"unix" : "*nix",
|
|
||||||
"ebooks" : "E-Books",
|
|
||||||
"comics" : "Comics",
|
|
||||||
"please_choose" : "Please choose...",
|
|
||||||
"search" : "Search",
|
|
||||||
"categories" : "Categories",
|
|
||||||
"category" : "Category",
|
|
||||||
"subcategory" : "Subcategory",
|
|
||||||
"create" : "Create",
|
|
||||||
"torrent_file" : "Torrent file",
|
|
||||||
"name" : "Name",
|
|
||||||
"create_new_torrent" : "Create a new torrent",
|
|
||||||
"description" : "Description",
|
|
||||||
"audio_quality" : "Audio quality",
|
|
||||||
"video_quality" : "Video quality",
|
|
||||||
"size" : "Size",
|
|
||||||
"tracker" : "Tracker",
|
|
||||||
"detected_files" : "Detected files"
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,7 @@ vim: ts=2 noexpandtab
|
|||||||
{% set active_page = "categories" %}
|
{% set active_page = "categories" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link href="{{ url_for("static", filename="css/categories.css") }}" rel="stylesheet">
|
<link href="{{ url_for("static", filename="css/categories.css") }}" rel="stylesheet">
|
||||||
<h2 class="headline">Categories</h2>
|
<h2 class="headline">{{ _("Categories") }}</h2>
|
||||||
<div id="categories">
|
<div id="categories">
|
||||||
{% for category in categories %}
|
{% for category in categories %}
|
||||||
<div>
|
<div>
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
vim: ts=2 noexpandtab
|
vim: ts=2 noexpandtab
|
||||||
-->
|
-->
|
||||||
{% extends "index.html" %}
|
{% extends "index.html" %}
|
||||||
{% block title %}{{ super() }} - {{ getLocalString(language, "create") }}{% endblock%}
|
{% block title %}{{ super() }} - {{ _("Create") }}{% endblock%}
|
||||||
{% set active_page = "create" %}
|
{% set active_page = "create" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link href="{{ url_for("static", filename="css/create.css") }}" rel="stylesheet">
|
<link href="{{ url_for("static", filename="css/create.css") }}" rel="stylesheet">
|
||||||
<script src="{{ url_for("static", filename="js/create.js") }}"></script>
|
<script src="{{ url_for("static", filename="js/create.js") }}"></script>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="headline">{{ getLocalString(language, "create_new_torrent") }}</h2>
|
<h2 class="headline">{{ _("Create new torrent") }}</h2>
|
||||||
{% if errors %}
|
{% if errors %}
|
||||||
{% for error in errors %}
|
{% for error in errors %}
|
||||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||||
@ -27,24 +27,24 @@ vim: ts=2 noexpandtab
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<form class="form-horizontal" action="/create" method="post" enctype="multipart/form-data" onsubmit="return validateForm()">
|
<form class="form-horizontal" action="/create" method="post" enctype="multipart/form-data" onsubmit="return validateForm()">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputTorrentFile" class="col-sm-3 control-label">{{ getLocalString(language, "torrent_file") }}</label>
|
<label for="inputTorrentFile" class="col-sm-3 control-label">{{ _("Torrent file") }}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input name="torrentFile" class="file" type="file" size="50" maxlength="100000" accept="application/x-bittorrent" onchange="setButtonToFilename(event)">
|
<input name="torrentFile" class="file" type="file" size="50" maxlength="100000" accept="application/x-bittorrent" onchange="setButtonToFilename(event)">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group detectedInfosGroup">
|
<div class="form-group detectedInfosGroup">
|
||||||
<label for="inputTorrentFile" class="col-sm-3 control-label">File info</label>
|
<label for="inputTorrentFile" class="col-sm-3 control-label">{{ _("File info") }}</label>
|
||||||
<div class="col-sm-9 detectedInfos">
|
<div class="col-sm-9 detectedInfos">
|
||||||
<div class="detectedGroup sizeGroup">
|
<div class="detectedGroup sizeGroup">
|
||||||
<h5>{{ getLocalString(language, "size") }}:</h5>
|
<h5>{{ _("Size") }}:</h5>
|
||||||
<p class="detectedSize"></p>
|
<p class="detectedSize"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="detectedGroup trackerGroup">
|
<div class="detectedGroup trackerGroup">
|
||||||
<h5>{{ getLocalString(language, "tracker") }}:</h5>
|
<h5>{{ _("Tracker") }}:</h5>
|
||||||
<p class="detectedTracker"></p>
|
<p class="detectedTracker"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="detectedGroup filesGroup">
|
<div class="detectedGroup filesGroup">
|
||||||
<h5>{{ getLocalString(language, "detected_files") }}:</h5>
|
<h5>{{ _("Detected files") }}:</h5>
|
||||||
<div class="detectedFiles">
|
<div class="detectedFiles">
|
||||||
<ul>
|
<ul>
|
||||||
</ul>
|
</ul>
|
||||||
@ -53,12 +53,12 @@ vim: ts=2 noexpandtab
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputCategory" class="col-sm-3 control-label">{{ getLocalString(language, "category") }}</label>
|
<label for="category" class="col-sm-3 control-label">{{ _("Category") }}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="row row-container">
|
<div class="row row-container">
|
||||||
<div class="col-md-6 category-column">
|
<div class="col-md-6 category-column">
|
||||||
<select class="form-control dropdown" id="category" name="category">
|
<select class="form-control dropdown" id="category" name="category">
|
||||||
<option value="-1" selected>--- Select Category ---</option>
|
<option value="-1" selected>--- {{ _("Select Category") }} ---</option>
|
||||||
{% for category in categories %}
|
{% for category in categories %}
|
||||||
<option value="{{ category.id }}">{{ category.label }}</option>
|
<option value="{{ category.id }}">{{ category.label }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -66,28 +66,28 @@ vim: ts=2 noexpandtab
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 subcategory-column">
|
<div class="col-md-6 subcategory-column">
|
||||||
<select class="form-control dropdown" id="subcategory" name="subcategory">
|
<select class="form-control dropdown" id="subcategory" name="subcategory">
|
||||||
<option value="-1" selected>--- Select Subcategory ---</option>
|
<option value="-1" selected>--- {{ _("Select Subcategory") }} ---</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputName" class="col-sm-3 control-label">{{ getLocalString(language, "name") }}</label>
|
<label for="inputName" class="col-sm-3 control-label">{{ _("Name") }}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input type="text" name="name" class="form-control name" placeholder="e.g. Attack of the Killer Tomatoes" aria-describedby="basic-addon1">
|
<input type="text" name="name" class="form-control name" placeholder="{{ _("e.g. Attack of the Killer Tomatoes") }}" aria-describedby="basic-addon1">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputName" class="col-sm-3 control-label">{{ getLocalString(language, "audio_quality") }}</label>
|
<label for="inputName" class="col-sm-3 control-label">{{ _("Audio quality") }}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input type="text" name="audioquality_description" class="form-control name" placeholder="e.g. English, AC-3 at 384kbps" aria-describedby="basic-addon1">
|
<input type="text" name="audioquality_description" class="form-control name" placeholder="{{ _("e.g. English, AC-3 @ 384kbps") }}" aria-describedby="basic-addon1">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputName" class="col-sm-3 control-label">{{ getLocalString(language, "video_quality") }}</label>
|
<label for="inputName" class="col-sm-3 control-label">{{ _("Video quality") }}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input type="text" name="videoquality_description" class="form-control name" placeholder="e.g. XviD, 720×400 at 1809 kbps" aria-describedby="basic-addon1">
|
<input type="text" name="videoquality_description" class="form-control name" placeholder="{{ _("e.g. XviD, 720×400 @ 1809 kbps") }}" aria-describedby="basic-addon1">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--
|
<!--
|
||||||
@ -115,14 +115,14 @@ vim: ts=2 noexpandtab
|
|||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputName" class="col-sm-3 control-label">{{ getLocalString(language, "description") }}</label>
|
<label for="inputName" class="col-sm-3 control-label">{{ _("Description") }}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea name="description" class="form-control description" rows="10" placeholder="Hint: Markdown is supported in this field"></textarea>
|
<textarea name="description" class="form-control description" rows="10" placeholder="{{ _("Hint: Markdown is supported in this field") }}"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-3 col-sm-9">
|
<div class="col-sm-offset-3 col-sm-9">
|
||||||
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> {{ getLocalString(language, "create") }}!</button>
|
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> {{ _("Create") }}!</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
vim: ts=2 noexpandtab
|
vim: ts=2 noexpandtab
|
||||||
-->
|
-->
|
||||||
{% extends "index.html" %}
|
{% extends "index.html" %}
|
||||||
{% block title %}{{ super() }} - Results{% endblock%}
|
{% block title %}{{ super() }} - {{ _("Results") }}{% endblock%}
|
||||||
{% set active_page = "search" %}
|
{% set active_page = "search" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link href="{{ url_for("static", filename="css/details.css") }}" rel="stylesheet">
|
<link href="{{ url_for("static", filename="css/details.css") }}" rel="stylesheet">
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
vim: ts=2 noexpandtab
|
vim: ts=2 noexpandtab
|
||||||
-->
|
-->
|
||||||
{% set navigation_bar = [
|
{% set navigation_bar = [
|
||||||
("/", "search", "Search", "glyphicon-search"),
|
("/", "search", _("Search"), "glyphicon-search"),
|
||||||
("/categories", "categories", "Categories", "glyphicon-th"),
|
("/categories", "categories", _("Categories"), "glyphicon-th"),
|
||||||
("/create", "create", "Create", "glyphicon-plus")
|
("/create", "create", _("Create"), "glyphicon-plus")
|
||||||
] -%}
|
] -%}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -23,7 +23,6 @@ vim: ts=2 noexpandtab
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var global_strings = {{json.dumps(strings)|safe}};
|
|
||||||
var global_categories = {{json.dumps(categories)|safe}};
|
var global_categories = {{json.dumps(categories)|safe}};
|
||||||
</script>
|
</script>
|
||||||
<div class="site-wrapper">
|
<div class="site-wrapper">
|
||||||
|
@ -2,26 +2,26 @@
|
|||||||
vim: ts=2 noexpandtab
|
vim: ts=2 noexpandtab
|
||||||
-->
|
-->
|
||||||
{% extends "index.html" %}
|
{% extends "index.html" %}
|
||||||
{% block title %}{{ super() }} - Results{% endblock%}
|
{% block title %}{{ super() }} - {{ _("Results") }}{% endblock%}
|
||||||
{% set active_page = "search" %}
|
{% set active_page = "search" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link href="{{ url_for("static", filename="css/result.css") }}" rel="stylesheet">
|
<link href="{{ url_for("static", filename="css/result.css") }}" rel="stylesheet">
|
||||||
<script src="{{ url_for("static", filename="js/main.js") }}"></script>
|
<script src="{{ url_for("static", filename="js/main.js") }}"></script>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>{{ _("Name") }}</th>
|
||||||
<th>Size</th>
|
<th>{{ _("Size") }}</th>
|
||||||
<th>Snatches</th>
|
<th>{{ _("Snatches") }}</th>
|
||||||
<th>UL</th>
|
<th>{{ _("UL") }}</th>
|
||||||
<th>DL</th>
|
<th>{{ _("DL") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for result in results %}
|
{% for result in results %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/download/{{ result[0] }}">{{ result[1] }}</a></td>
|
<td><a href="/download/{{ result[0] }}">{{ result[1] }}</a></td>
|
||||||
<td>{{ result[2] }}</td>
|
<td>{{ result[2] }}</td>
|
||||||
<td>N/A</td>
|
<td>{{ _("N/A") }}</td>
|
||||||
<td>N/A</td>
|
<td>{{ _("N/A") }}</td>
|
||||||
<td>N/A</td>
|
<td>{{ _("N/A") }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
vim: ts=2 noexpandtab
|
vim: ts=2 noexpandtab
|
||||||
-->
|
-->
|
||||||
{% extends "index.html" %}
|
{% extends "index.html" %}
|
||||||
{% block title %}{{ super() }} - Search{% endblock%}
|
{% block title %}{{ super() }} - {{ _("Search") }}{% endblock%}
|
||||||
{% set active_page = "search" %}
|
{% set active_page = "search" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<link href="{{ url_for("static", filename="css/search.css") }}" rel="stylesheet">
|
<link href="{{ url_for("static", filename="css/search.css") }}" rel="stylesheet">
|
||||||
@ -12,11 +12,11 @@ vim: ts=2 noexpandtab
|
|||||||
<form action="search" >
|
<form action="search" >
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="input-group search-box">
|
<div class="input-group search-box">
|
||||||
<input type="text" name="q" class="form-control" placeholder="Seach for…" aria-describedby="basic-addon2">
|
<input type="text" name="q" class="form-control" placeholder="{{ _("Seach for…") }}" aria-describedby="basic-addon2">
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button class="btn btn-default" type="submit">
|
<button class="btn btn-default" type="submit">
|
||||||
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||||
{{ getLocalString(language, "search") }}!
|
{{ _("Search!") }}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
258
translations/de/LC_MESSAGES/messages.po
Normal file
258
translations/de/LC_MESSAGES/messages.po
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
# German translations for PROJECT.
|
||||||
|
# Copyright (C) 2017 ORGANIZATION
|
||||||
|
# This file is distributed under the same license as the PROJECT project.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
|
"POT-Creation-Date: 2017-12-29 06:12+0100\n"
|
||||||
|
"PO-Revision-Date: 2017-12-28 04:10+0100\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language: de\n"
|
||||||
|
"Language-Team: de <LL@li.org>\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.5.1\n"
|
||||||
|
|
||||||
|
#: indexer.py:41
|
||||||
|
msgid "Successfully created torrent <a href=\"/search?h={}\">{}</a>"
|
||||||
|
msgstr "Torrent <a href=\"/search?h={}\">{}</a> erfolgreich erstellt"
|
||||||
|
|
||||||
|
#: indexer.py:155
|
||||||
|
msgid "Torrent <a href=\"/search?h={}\">{}</a> already exists"
|
||||||
|
msgstr "Torrent <a href=\"/search?h={}\">{}</a> ist bereits vorhanden"
|
||||||
|
|
||||||
|
#: indexer.py:157
|
||||||
|
msgid "Unknown error in creation"
|
||||||
|
msgstr "Unbekannter Fehler bei der Erstellung"
|
||||||
|
|
||||||
|
#: settings.json:4 settings.json:8 settings.json:12 settings.json:16
|
||||||
|
#: settings.json:20 settings.json:26 settings.json:30 settings.json:34
|
||||||
|
#: settings.json:38 settings.json:42 settings.json:46 settings.json:50
|
||||||
|
#: settings.json:54 settings.json:58 settings.json:64 settings.json:68
|
||||||
|
#: settings.json:72 settings.json:76 settings.json:80 settings.json:84
|
||||||
|
#: settings.json:88 settings.json:92 settings.json:96 settings.json:100
|
||||||
|
#: settings.json:106 settings.json:110 settings.json:114 settings.json:118
|
||||||
|
#: settings.json:122 settings.json:126 settings.json:130 settings.json:136
|
||||||
|
#: settings.json:140 settings.json:144 settings.json:148 settings.json:152
|
||||||
|
#: settings.json:156 settings.json:160 settings.json:166 settings.json:170
|
||||||
|
#: settings.json:174 settings.json:178 settings.json:182
|
||||||
|
msgid "id"
|
||||||
|
msgstr "id"
|
||||||
|
|
||||||
|
#: settings.json:5
|
||||||
|
msgid "Audio"
|
||||||
|
msgstr "Audio"
|
||||||
|
|
||||||
|
#: settings.json:9
|
||||||
|
msgid "Lossless"
|
||||||
|
msgstr "Verlustfrei"
|
||||||
|
|
||||||
|
#: settings.json:13
|
||||||
|
msgid "Lossy"
|
||||||
|
msgstr "Verlustbehaftet"
|
||||||
|
|
||||||
|
#: settings.json:17
|
||||||
|
msgid "Audio book"
|
||||||
|
msgstr "Hörbuch"
|
||||||
|
|
||||||
|
#: settings.json:21 settings.json:59 settings.json:101 settings.json:131
|
||||||
|
#: settings.json:161 settings.json:167 settings.json:183
|
||||||
|
msgid "Other"
|
||||||
|
msgstr "Sonstige"
|
||||||
|
|
||||||
|
#: settings.json:27
|
||||||
|
msgid "Video"
|
||||||
|
msgstr "Video"
|
||||||
|
|
||||||
|
#: settings.json:31 settings.json:69
|
||||||
|
msgid "3D Movie"
|
||||||
|
msgstr "3D-Film"
|
||||||
|
|
||||||
|
#: settings.json:35 settings.json:73
|
||||||
|
msgid "4k Movie"
|
||||||
|
msgstr "4k-Film"
|
||||||
|
|
||||||
|
#: settings.json:39 settings.json:77
|
||||||
|
msgid "HD Movie"
|
||||||
|
msgstr "HD-Film"
|
||||||
|
|
||||||
|
#: settings.json:43 settings.json:81
|
||||||
|
msgid "SD Movie"
|
||||||
|
msgstr "SD-Film"
|
||||||
|
|
||||||
|
#: settings.json:47 settings.json:85
|
||||||
|
msgid "HD Series"
|
||||||
|
msgstr "HD-Serie"
|
||||||
|
|
||||||
|
#: settings.json:51 settings.json:89
|
||||||
|
msgid "SD Series"
|
||||||
|
msgstr "SD-Serie"
|
||||||
|
|
||||||
|
#: settings.json:55 settings.json:93
|
||||||
|
msgid "Clip"
|
||||||
|
msgstr "Clip"
|
||||||
|
|
||||||
|
#: settings.json:65
|
||||||
|
msgid "Porn"
|
||||||
|
msgstr "Pornographie"
|
||||||
|
|
||||||
|
#: settings.json:97
|
||||||
|
msgid "Pictures"
|
||||||
|
msgstr "Bilder"
|
||||||
|
|
||||||
|
#: settings.json:107
|
||||||
|
msgid "Games"
|
||||||
|
msgstr "Spiele"
|
||||||
|
|
||||||
|
#: settings.json:111 settings.json:141
|
||||||
|
msgid "Windows"
|
||||||
|
msgstr "Windows"
|
||||||
|
|
||||||
|
#: settings.json:115 settings.json:145
|
||||||
|
msgid "Mac"
|
||||||
|
msgstr "Mac"
|
||||||
|
|
||||||
|
#: settings.json:119 settings.json:153
|
||||||
|
msgid "iOS"
|
||||||
|
msgstr "iOS"
|
||||||
|
|
||||||
|
#: settings.json:123 settings.json:157
|
||||||
|
msgid "Android"
|
||||||
|
msgstr "Android"
|
||||||
|
|
||||||
|
#: settings.json:127
|
||||||
|
msgid "Consoles"
|
||||||
|
msgstr "Konsolen"
|
||||||
|
|
||||||
|
#: settings.json:137
|
||||||
|
msgid "Application"
|
||||||
|
msgstr "Anwendungen"
|
||||||
|
|
||||||
|
#: settings.json:149
|
||||||
|
msgid "*nix"
|
||||||
|
msgstr "*nix"
|
||||||
|
|
||||||
|
#: settings.json:171
|
||||||
|
msgid "eBook"
|
||||||
|
msgstr "eBook"
|
||||||
|
|
||||||
|
#: settings.json:175
|
||||||
|
msgid "Comic"
|
||||||
|
msgstr "Comic"
|
||||||
|
|
||||||
|
#: settings.json:179
|
||||||
|
msgid "Picture"
|
||||||
|
msgstr "Bild"
|
||||||
|
|
||||||
|
#: templates/categories.html:9 templates/index.html:6
|
||||||
|
msgid "Categories"
|
||||||
|
msgstr "Kategorien"
|
||||||
|
|
||||||
|
#: templates/create.html:5 templates/create.html:125 templates/index.html:7
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Erstellen"
|
||||||
|
|
||||||
|
#: templates/create.html:11
|
||||||
|
msgid "Create new torrent"
|
||||||
|
msgstr "Neuen Torrent erstellen"
|
||||||
|
|
||||||
|
#: templates/create.html:30
|
||||||
|
msgid "Torrent file"
|
||||||
|
msgstr "Torrentdatei"
|
||||||
|
|
||||||
|
#: templates/create.html:36
|
||||||
|
msgid "File info"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templates/create.html:39 templates/result.html:13
|
||||||
|
msgid "Size"
|
||||||
|
msgstr "Größe"
|
||||||
|
|
||||||
|
#: templates/create.html:43
|
||||||
|
msgid "Tracker"
|
||||||
|
msgstr "Tracker"
|
||||||
|
|
||||||
|
#: templates/create.html:47
|
||||||
|
msgid "Detected files"
|
||||||
|
msgstr "Erkannte Dateien"
|
||||||
|
|
||||||
|
#: templates/create.html:56
|
||||||
|
msgid "Category"
|
||||||
|
msgstr "Kategorie"
|
||||||
|
|
||||||
|
#: templates/create.html:61
|
||||||
|
msgid "Select Category"
|
||||||
|
msgstr "Kategorie wählen"
|
||||||
|
|
||||||
|
#: templates/create.html:69
|
||||||
|
msgid "Select Subcategory"
|
||||||
|
msgstr "Unterkategorie wählen"
|
||||||
|
|
||||||
|
#: templates/create.html:76 templates/result.html:12
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Name"
|
||||||
|
|
||||||
|
#: templates/create.html:78
|
||||||
|
msgid "e.g. Attack of the Killer Tomatoes"
|
||||||
|
msgstr "z.B. Angriff der Killertomaten"
|
||||||
|
|
||||||
|
#: templates/create.html:82
|
||||||
|
msgid "Audio quality"
|
||||||
|
msgstr "Audioqualität"
|
||||||
|
|
||||||
|
#: templates/create.html:84
|
||||||
|
msgid "e.g. English, AC-3 @ 384kbps"
|
||||||
|
msgstr "z.B. Deutsch, AC-3 @ 384kbps"
|
||||||
|
|
||||||
|
#: templates/create.html:88
|
||||||
|
msgid "Video quality"
|
||||||
|
msgstr "Videoqualität"
|
||||||
|
|
||||||
|
#: templates/create.html:90
|
||||||
|
msgid "e.g. XviD, 720×400 @ 1809 kbps"
|
||||||
|
msgstr "z.B. XviD, 720x400 @ 1809 kbps"
|
||||||
|
|
||||||
|
#: templates/create.html:118
|
||||||
|
msgid "Description"
|
||||||
|
msgstr "Beschreibung"
|
||||||
|
|
||||||
|
#: templates/create.html:120
|
||||||
|
msgid "Hint: Markdown is supported in this field"
|
||||||
|
msgstr "Hinweis: In diesem Feld kann Markdown verwendet werden"
|
||||||
|
|
||||||
|
#: templates/details.html:5 templates/result.html:5
|
||||||
|
msgid "Results"
|
||||||
|
msgstr "Ergebnisse"
|
||||||
|
|
||||||
|
#: templates/index.html:5 templates/search.html:5
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "Suche"
|
||||||
|
|
||||||
|
#: templates/result.html:14
|
||||||
|
msgid "Snatches"
|
||||||
|
msgstr "Schnapper"
|
||||||
|
|
||||||
|
#: templates/result.html:15
|
||||||
|
msgid "UL"
|
||||||
|
msgstr "UL"
|
||||||
|
|
||||||
|
#: templates/result.html:16
|
||||||
|
msgid "DL"
|
||||||
|
msgstr "DL"
|
||||||
|
|
||||||
|
#: templates/result.html:22 templates/result.html:23 templates/result.html:24
|
||||||
|
msgid "N/A"
|
||||||
|
msgstr "N/V"
|
||||||
|
|
||||||
|
#: templates/search.html:15
|
||||||
|
msgid "Seach for…"
|
||||||
|
msgstr "Suche nach…"
|
||||||
|
|
||||||
|
#: templates/search.html:19
|
||||||
|
msgid "Search!"
|
||||||
|
msgstr "Suchen!"
|
Loading…
Reference in New Issue
Block a user