Add translation capability
This commit is contained in:
parent
2c220afced
commit
9c053b5021
15 changed files with 342 additions and 132 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,5 +1,7 @@
|
|||
*.swp
|
||||
*.swo
|
||||
*.mo
|
||||
*.pot
|
||||
backup
|
||||
uploadTest
|
||||
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_
|
57
indexer.py
57
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 <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])
|
||||
message = _("Successfully created torrent <a href=\"/search?h={}\">{}</a>").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/<filename>")
|
||||
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 <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:
|
||||
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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -75,8 +75,9 @@ function fillDetectedFilelist(file) {
|
|||
|
||||
function fillSubcategory(value) {
|
||||
var subSelect = $('#subcategory')
|
||||
var selText = $(':first-child', subSelect).text()
|
||||
subSelect.empty();
|
||||
subSelect.append($('<option value="-1" selected>--- Select Subcategory ---</selected>'))
|
||||
subSelect.append($('<option value="-1" selected>'+selText+'</selected>'))
|
||||
if (value >= 0) {
|
||||
var subcategories = null
|
||||
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) {
|
||||
units = ["B", "kB", "MB", "GB", "TB", "PB", "To damn high"]
|
||||
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" %}
|
||||
{% block content %}
|
||||
<link href="{{ url_for("static", filename="css/categories.css") }}" rel="stylesheet">
|
||||
<h2 class="headline">Categories</h2>
|
||||
<h2 class="headline">{{ _("Categories") }}</h2>
|
||||
<div id="categories">
|
||||
{% for category in categories %}
|
||||
<div>
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
vim: ts=2 noexpandtab
|
||||
-->
|
||||
{% extends "index.html" %}
|
||||
{% block title %}{{ super() }} - {{ getLocalString(language, "create") }}{% endblock%}
|
||||
{% block title %}{{ super() }} - {{ _("Create") }}{% endblock%}
|
||||
{% set active_page = "create" %}
|
||||
{% block content %}
|
||||
<link href="{{ url_for("static", filename="css/create.css") }}" rel="stylesheet">
|
||||
<script src="{{ url_for("static", filename="js/create.js") }}"></script>
|
||||
<div>
|
||||
<h2 class="headline">{{ getLocalString(language, "create_new_torrent") }}</h2>
|
||||
<h2 class="headline">{{ _("Create new torrent") }}</h2>
|
||||
{% if errors %}
|
||||
{% for error in errors %}
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
|
@ -27,24 +27,24 @@ vim: ts=2 noexpandtab
|
|||
{% endif %}
|
||||
<form class="form-horizontal" action="/create" method="post" enctype="multipart/form-data" onsubmit="return validateForm()">
|
||||
<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">
|
||||
<input name="torrentFile" class="file" type="file" size="50" maxlength="100000" accept="application/x-bittorrent" onchange="setButtonToFilename(event)">
|
||||
</div>
|
||||
</div>
|
||||
<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="detectedGroup sizeGroup">
|
||||
<h5>{{ getLocalString(language, "size") }}:</h5>
|
||||
<h5>{{ _("Size") }}:</h5>
|
||||
<p class="detectedSize"></p>
|
||||
</div>
|
||||
<div class="detectedGroup trackerGroup">
|
||||
<h5>{{ getLocalString(language, "tracker") }}:</h5>
|
||||
<h5>{{ _("Tracker") }}:</h5>
|
||||
<p class="detectedTracker"></p>
|
||||
</div>
|
||||
<div class="detectedGroup filesGroup">
|
||||
<h5>{{ getLocalString(language, "detected_files") }}:</h5>
|
||||
<h5>{{ _("Detected files") }}:</h5>
|
||||
<div class="detectedFiles">
|
||||
<ul>
|
||||
</ul>
|
||||
|
@ -53,12 +53,12 @@ vim: ts=2 noexpandtab
|
|||
</div>
|
||||
</div>
|
||||
<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="row row-container">
|
||||
<div class="col-md-6 category-column">
|
||||
<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 %}
|
||||
<option value="{{ category.id }}">{{ category.label }}</option>
|
||||
{% endfor %}
|
||||
|
@ -66,28 +66,28 @@ vim: ts=2 noexpandtab
|
|||
</div>
|
||||
<div class="col-md-6 subcategory-column">
|
||||
<select class="form-control dropdown" id="subcategory" name="subcategory">
|
||||
<option value="-1" selected>--- Select Subcategory ---</option>
|
||||
<option value="-1" selected>--- {{ _("Select Subcategory") }} ---</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<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 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">
|
||||
<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 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">
|
||||
<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>
|
||||
<!--
|
||||
|
@ -115,14 +115,14 @@ vim: ts=2 noexpandtab
|
|||
</div>
|
||||
-->
|
||||
<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">
|
||||
<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 class="form-group">
|
||||
<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>
|
||||
</form>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
vim: ts=2 noexpandtab
|
||||
-->
|
||||
{% extends "index.html" %}
|
||||
{% block title %}{{ super() }} - Results{% endblock%}
|
||||
{% block title %}{{ super() }} - {{ _("Results") }}{% endblock%}
|
||||
{% set active_page = "search" %}
|
||||
{% block content %}
|
||||
<link href="{{ url_for("static", filename="css/details.css") }}" rel="stylesheet">
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
vim: ts=2 noexpandtab
|
||||
-->
|
||||
{% set navigation_bar = [
|
||||
("/", "search", "Search", "glyphicon-search"),
|
||||
("/categories", "categories", "Categories", "glyphicon-th"),
|
||||
("/create", "create", "Create", "glyphicon-plus")
|
||||
("/", "search", _("Search"), "glyphicon-search"),
|
||||
("/categories", "categories", _("Categories"), "glyphicon-th"),
|
||||
("/create", "create", _("Create"), "glyphicon-plus")
|
||||
] -%}
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
@ -23,7 +23,6 @@ vim: ts=2 noexpandtab
|
|||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
var global_strings = {{json.dumps(strings)|safe}};
|
||||
var global_categories = {{json.dumps(categories)|safe}};
|
||||
</script>
|
||||
<div class="site-wrapper">
|
||||
|
|
|
@ -2,26 +2,26 @@
|
|||
vim: ts=2 noexpandtab
|
||||
-->
|
||||
{% extends "index.html" %}
|
||||
{% block title %}{{ super() }} - Results{% endblock%}
|
||||
{% block title %}{{ super() }} - {{ _("Results") }}{% endblock%}
|
||||
{% set active_page = "search" %}
|
||||
{% block content %}
|
||||
<link href="{{ url_for("static", filename="css/result.css") }}" rel="stylesheet">
|
||||
<script src="{{ url_for("static", filename="js/main.js") }}"></script>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
<th>Snatches</th>
|
||||
<th>UL</th>
|
||||
<th>DL</th>
|
||||
<th>{{ _("Name") }}</th>
|
||||
<th>{{ _("Size") }}</th>
|
||||
<th>{{ _("Snatches") }}</th>
|
||||
<th>{{ _("UL") }}</th>
|
||||
<th>{{ _("DL") }}</th>
|
||||
</tr>
|
||||
{% for result in results %}
|
||||
<tr>
|
||||
<td><a href="/download/{{ result[0] }}">{{ result[1] }}</a></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>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
vim: ts=2 noexpandtab
|
||||
-->
|
||||
{% extends "index.html" %}
|
||||
{% block title %}{{ super() }} - Search{% endblock%}
|
||||
{% block title %}{{ super() }} - {{ _("Search") }}{% endblock%}
|
||||
{% set active_page = "search" %}
|
||||
{% block content %}
|
||||
<link href="{{ url_for("static", filename="css/search.css") }}" rel="stylesheet">
|
||||
|
@ -12,11 +12,11 @@ vim: ts=2 noexpandtab
|
|||
<form action="search" >
|
||||
<div class="form-group">
|
||||
<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">
|
||||
<button class="btn btn-default" type="submit">
|
||||
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
||||
{{ getLocalString(language, "search") }}!
|
||||
{{ _("Search!") }}
|
||||
</button>
|
||||
</span>
|
||||
</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 a new issue