mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-25 11:07:22 +00:00
commit
2272013d80
10
cps/db.py
10
cps/db.py
@ -11,7 +11,7 @@ from ub import config
|
|||||||
import ub
|
import ub
|
||||||
|
|
||||||
session = None
|
session = None
|
||||||
cc_exceptions = ['datetime', 'int', 'comments', 'float', 'composite', 'series']
|
cc_exceptions = ['datetime', 'comments', 'float', 'composite', 'series']
|
||||||
cc_classes = None
|
cc_classes = None
|
||||||
engine = None
|
engine = None
|
||||||
|
|
||||||
@ -302,7 +302,6 @@ def setup_db():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
|
dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
|
||||||
#engine = create_engine('sqlite:///{0}'.format(dbpath.encode('utf-8')), echo=False, isolation_level="SERIALIZABLE")
|
|
||||||
engine = create_engine('sqlite:///'+ dbpath, echo=False, isolation_level="SERIALIZABLE")
|
engine = create_engine('sqlite:///'+ dbpath, echo=False, isolation_level="SERIALIZABLE")
|
||||||
try:
|
try:
|
||||||
conn = engine.connect()
|
conn = engine.connect()
|
||||||
@ -340,6 +339,11 @@ def setup_db():
|
|||||||
'id': Column(Integer, primary_key=True),
|
'id': Column(Integer, primary_key=True),
|
||||||
'book': Column(Integer, ForeignKey('books.id')),
|
'book': Column(Integer, ForeignKey('books.id')),
|
||||||
'value': Column(Boolean)}
|
'value': Column(Boolean)}
|
||||||
|
elif row.datatype == 'int':
|
||||||
|
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||||
|
'id': Column(Integer, primary_key=True),
|
||||||
|
'book': Column(Integer, ForeignKey('books.id')),
|
||||||
|
'value': Column(Integer)}
|
||||||
else:
|
else:
|
||||||
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
ccdict = {'__tablename__': 'custom_column_' + str(row.id),
|
||||||
'id': Column(Integer, primary_key=True),
|
'id': Column(Integer, primary_key=True),
|
||||||
@ -347,7 +351,7 @@ def setup_db():
|
|||||||
cc_classes[row.id] = type('Custom_Column_' + str(row.id), (Base,), ccdict)
|
cc_classes[row.id] = type('Custom_Column_' + str(row.id), (Base,), ccdict)
|
||||||
|
|
||||||
for cc_id in cc_ids:
|
for cc_id in cc_ids:
|
||||||
if cc_id[1] == 'bool':
|
if (cc_id[1] == 'bool') or (cc_id[1] == 'int'):
|
||||||
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]],
|
||||||
primaryjoin=(
|
primaryjoin=(
|
||||||
Books.id == cc_classes[cc_id[0]].book),
|
Books.id == cc_classes[cc_id[0]].book),
|
||||||
|
@ -52,6 +52,9 @@ except Exception as e:
|
|||||||
global_task = None
|
global_task = None
|
||||||
updater_thread = None
|
updater_thread = None
|
||||||
|
|
||||||
|
RET_SUCCESS = 1
|
||||||
|
RET_FAIL = 0
|
||||||
|
|
||||||
def update_download(book_id, user_id):
|
def update_download(book_id, user_id):
|
||||||
check = ub.session.query(ub.Downloads).filter(ub.Downloads.user_id == user_id).filter(ub.Downloads.book_id ==
|
check = ub.session.query(ub.Downloads).filter(ub.Downloads.user_id == user_id).filter(ub.Downloads.book_id ==
|
||||||
book_id).first()
|
book_id).first()
|
||||||
@ -63,6 +66,7 @@ def update_download(book_id, user_id):
|
|||||||
|
|
||||||
|
|
||||||
def make_mobi(book_id, calibrepath):
|
def make_mobi(book_id, calibrepath):
|
||||||
|
error_message = None
|
||||||
vendorpath = os.path.join(os.path.normpath(os.path.dirname(os.path.realpath(__file__)) +
|
vendorpath = os.path.join(os.path.normpath(os.path.dirname(os.path.realpath(__file__)) +
|
||||||
os.sep + "../vendor" + os.sep))
|
os.sep + "../vendor" + os.sep))
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
@ -70,24 +74,41 @@ def make_mobi(book_id, calibrepath):
|
|||||||
else:
|
else:
|
||||||
kindlegen = (os.path.join(vendorpath, u"kindlegen")).encode(sys.getfilesystemencoding())
|
kindlegen = (os.path.join(vendorpath, u"kindlegen")).encode(sys.getfilesystemencoding())
|
||||||
if not os.path.exists(kindlegen):
|
if not os.path.exists(kindlegen):
|
||||||
app.logger.error("make_mobi: kindlegen binary not found in: %s" % kindlegen)
|
error_message = _(u"kindlegen binary %(kindlepath)s not found", kindlepath=kindlegen)
|
||||||
return None
|
app.logger.error("make_mobi: " + error_message)
|
||||||
|
return error_message, RET_FAIL
|
||||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||||
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == 'EPUB').first()
|
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == 'EPUB').first()
|
||||||
if not data:
|
if not data:
|
||||||
app.logger.error("make_mobi: epub format not found for book id: %d" % book_id)
|
error_message = _(u"epub format not found for book id: %(book)d", book=book_id)
|
||||||
return None
|
app.logger.error("make_mobi: " + error_message)
|
||||||
|
return error_message, RET_FAIL
|
||||||
|
|
||||||
file_path = os.path.join(calibrepath, book.path, data.name)
|
file_path = os.path.join(calibrepath, book.path, data.name)
|
||||||
if os.path.exists(file_path + u".epub"):
|
if os.path.exists(file_path + u".epub"):
|
||||||
p = subprocess.Popen((kindlegen + " \"" + file_path + u".epub\"").encode(sys.getfilesystemencoding()),
|
try:
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
p = subprocess.Popen((kindlegen + " \"" + file_path + u".epub\"").encode(sys.getfilesystemencoding()),
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||||
|
except:
|
||||||
|
error_message = _(u"kindlegen failed, no excecution permissions")
|
||||||
|
app.logger.error("make_mobi: "+error_message)
|
||||||
|
return error_message, RET_FAIL
|
||||||
|
|
||||||
# Poll process for new output until finished
|
# Poll process for new output until finished
|
||||||
while True:
|
while True:
|
||||||
nextline = p.stdout.readline()
|
nextline = p.stdout.readline()
|
||||||
if nextline == '' and p.poll() is not None:
|
if nextline == '' and p.poll() is not None:
|
||||||
break
|
break
|
||||||
if nextline != "\r\n":
|
if nextline != "\r\n":
|
||||||
|
# Format of error message (kindlegen translates its output texts):
|
||||||
|
# Error(prcgen):E23006: Language not recognized in metadata.The dc:Language field is mandatory.Aborting.
|
||||||
|
conv_error=re.search(".*\(.*\):(E\d+):\s(.*)",nextline)
|
||||||
|
# If error occoures, log in every case
|
||||||
|
if conv_error:
|
||||||
|
error_message = _(u"Kindlegen failed with Error %(error)s. Message: %(message)s",
|
||||||
|
error=conv_error.group(1), message=conv_error.group(2).decode('utf-8'))
|
||||||
|
app.logger.info("make_mobi: " + error_message)
|
||||||
|
app.logger.info(nextline.strip('\r\n'))
|
||||||
app.logger.debug(nextline.strip('\r\n'))
|
app.logger.debug(nextline.strip('\r\n'))
|
||||||
|
|
||||||
check = p.returncode
|
check = p.returncode
|
||||||
@ -99,13 +120,13 @@ def make_mobi(book_id, calibrepath):
|
|||||||
uncompressed_size=os.path.getsize(file_path + ".mobi")
|
uncompressed_size=os.path.getsize(file_path + ".mobi")
|
||||||
))
|
))
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return file_path + ".mobi"
|
return file_path + ".mobi", RET_SUCCESS
|
||||||
else:
|
else:
|
||||||
app.logger.error("make_mobi: kindlegen failed with error while converting book")
|
app.logger.error("make_mobi: kindlegen failed with error while converting book")
|
||||||
return None
|
return None, RET_FAIL
|
||||||
else:
|
else:
|
||||||
app.logger.error("make_mobie: epub not found: %s.epub" % file_path)
|
app.logger.error("make_mobi: epub not found: %s.epub" % file_path)
|
||||||
return None
|
return None, RET_FAIL
|
||||||
|
|
||||||
|
|
||||||
class StderrLogger(object):
|
class StderrLogger(object):
|
||||||
@ -204,13 +225,11 @@ def send_mail(book_id, kindle_mail, calibrepath):
|
|||||||
if 'mobi' in formats:
|
if 'mobi' in formats:
|
||||||
msg.attach(get_attachment(formats['mobi']))
|
msg.attach(get_attachment(formats['mobi']))
|
||||||
elif 'epub' in formats:
|
elif 'epub' in formats:
|
||||||
filepath = make_mobi(book.id, calibrepath)
|
data, resultCode = make_mobi(book.id, calibrepath)
|
||||||
if filepath is not None:
|
if resultCode == RET_SUCCESS:
|
||||||
msg.attach(get_attachment(filepath))
|
msg.attach(get_attachment(data))
|
||||||
elif filepath is None:
|
else:
|
||||||
return _("Could not convert epub to mobi")
|
return data #_("Could not convert epub to mobi")
|
||||||
elif 'pdf' in formats:
|
|
||||||
msg.attach(get_attachment(formats['pdf']))
|
|
||||||
elif 'pdf' in formats:
|
elif 'pdf' in formats:
|
||||||
msg.attach(get_attachment(formats['pdf']))
|
msg.attach(get_attachment(formats['pdf']))
|
||||||
else:
|
else:
|
||||||
|
@ -51,12 +51,12 @@
|
|||||||
<label for="cover_url">{{_('Cover URL (jpg)')}}</label>
|
<label for="cover_url">{{_('Cover URL (jpg)')}}</label>
|
||||||
<input type="text" class="form-control" name="cover_url" id="cover_url" value="">
|
<input type="text" class="form-control" name="cover_url" id="cover_url" value="">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="languages">{{_('Language')}}</label>
|
<label for="languages">{{_('Language')}}</label>
|
||||||
<input type="text" class="form-control typeahead" name="languages" id="languages" value="{% for language in book.languages %}{{language.language_name.strip()}}, {% endfor %}">
|
<input type="text" class="form-control typeahead" name="languages" id="languages" value="{% for language in book.languages %}{{language.language_name.strip()}}, {% endfor %}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if cc|length > 0 %}
|
{% if cc|length > 0 %}
|
||||||
{% for c in cc %}
|
{% for c in cc %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -68,6 +68,11 @@
|
|||||||
<option value="False" {% if book['custom_column_' ~ c.id]|length > 0 %}{% if book['custom_column_' ~ c.id][0].value ==false %}selected{% endif %}{% endif %}>{{_('No')}}</option>
|
<option value="False" {% if book['custom_column_' ~ c.id]|length > 0 %}{% if book['custom_column_' ~ c.id][0].value ==false %}selected{% endif %}{% endif %}>{{_('No')}}</option>
|
||||||
</select>
|
</select>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if c.datatype == 'int' %}
|
||||||
|
<input type="number" step="1" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value="{% if book['custom_column_' ~ c.id]|length > 0 %}{{ book['custom_column_' ~ c.id][0].value }}{% endif %}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if c.datatype in ['text', 'series'] and not c.is_multiple %}
|
{% if c.datatype in ['text', 'series'] and not c.is_multiple %}
|
||||||
<input type="text" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}"
|
<input type="text" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}"
|
||||||
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
||||||
@ -80,12 +85,12 @@
|
|||||||
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
||||||
value="{% for column in book['custom_column_' ~ c.id] %}{{ column.value.strip() }}{% if not loop.last %}, {% endif %}{% endfor %}"{% endif %}>
|
value="{% for column in book['custom_column_' ~ c.id] %}{{ column.value.strip() }}{% if not loop.last %}, {% endif %}{% endfor %}"{% endif %}>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if c.datatype == 'enumeration' %}
|
{% if c.datatype == 'enumeration' %}
|
||||||
<select class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}">
|
<select class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}">
|
||||||
<option></option>
|
<option></option>
|
||||||
{% for opt in c.get_display_dict().enum_values %}
|
{% for opt in c.get_display_dict().enum_values %}
|
||||||
<option
|
<option
|
||||||
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
{% if book['custom_column_' ~ c.id]|length > 0 %}
|
||||||
{% if book['custom_column_' ~ c.id][0].value == opt %}selected="selected"{% endif %}
|
{% if book['custom_column_' ~ c.id][0].value == opt %}selected="selected"{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -102,9 +107,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input name="detail_view" type="checkbox" checked> {{_('view book after edit')}}
|
<input name="detail_view" type="checkbox" checked> {{_('view book after edit')}}
|
||||||
|
@ -48,7 +48,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
|||||||
<!--<script src="pdf.js"></script>-->
|
<!--<script src="pdf.js"></script>-->
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var DEFAULT_URL = "{{ url_for('static', filename=pdffile) }}";
|
var DEFAULT_URL = "{{ url_for('serve_book', book_id=pdffile,book_format='pdf') }}";
|
||||||
var PDFWORKER_LOCATION="{{ url_for('static', filename='js/libs/pdf.worker.js') }}";
|
var PDFWORKER_LOCATION="{{ url_for('static', filename='js/libs/pdf.worker.js') }}";
|
||||||
// var IMAGE_LOCATION="{{ url_for('static', filename='css/../images') }}";
|
// var IMAGE_LOCATION="{{ url_for('static', filename='css/../images') }}";
|
||||||
var IMAGE_LOCATION="{{ url_for('static', filename='/images/') }}";
|
var IMAGE_LOCATION="{{ url_for('static', filename='/images/') }}";
|
||||||
|
@ -109,7 +109,7 @@
|
|||||||
$("#area").width($("#area").width());
|
$("#area").width($("#area").width());
|
||||||
$("#content").width($("#content").width());
|
$("#content").width($("#content").width());
|
||||||
//bind text
|
//bind text
|
||||||
$("#content").load("{{ url_for('static', filename=txtfile) }}",function(textStr) {
|
$("#content").load("{{ url_for('serve_book', book_id=txtfile,book_format='txt') }}",function(textStr) {
|
||||||
$(this).height($(this).parent().height()*0.95);
|
$(this).height($(this).parent().height()*0.95);
|
||||||
$(this).text(textStr);
|
$(this).text(textStr);
|
||||||
});
|
});
|
||||||
|
BIN
cps/translations/nl/LC_MESSAGES/messages.mo
Normal file
BIN
cps/translations/nl/LC_MESSAGES/messages.mo
Normal file
Binary file not shown.
31998
cps/translations/nl/LC_MESSAGES/messages.po
Normal file
31998
cps/translations/nl/LC_MESSAGES/messages.po
Normal file
File diff suppressed because it is too large
Load Diff
80
cps/web.py
80
cps/web.py
@ -1261,13 +1261,16 @@ def stats():
|
|||||||
kindlegen = os.path.join(vendorpath, u"kindlegen")
|
kindlegen = os.path.join(vendorpath, u"kindlegen")
|
||||||
versions['KindlegenVersion'] = _('not installed')
|
versions['KindlegenVersion'] = _('not installed')
|
||||||
if os.path.exists(kindlegen):
|
if os.path.exists(kindlegen):
|
||||||
p = subprocess.Popen(kindlegen, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
try:
|
||||||
p.wait()
|
p = subprocess.Popen(kindlegen, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
for lines in p.stdout.readlines():
|
p.wait()
|
||||||
if isinstance(lines, bytes):
|
for lines in p.stdout.readlines():
|
||||||
lines = lines.decode('utf-8')
|
if isinstance(lines, bytes):
|
||||||
if re.search('Amazon kindlegen\(', lines):
|
lines = lines.decode('utf-8')
|
||||||
versions['KindlegenVersion'] = lines
|
if re.search('Amazon kindlegen\(', lines):
|
||||||
|
versions['KindlegenVersion'] = lines
|
||||||
|
except:
|
||||||
|
versions['KindlegenVersion'] = _('Excecution permissions missing')
|
||||||
versions['PythonVersion'] = sys.version
|
versions['PythonVersion'] = sys.version
|
||||||
versions['babel'] = babelVersion
|
versions['babel'] = babelVersion
|
||||||
versions['sqlalchemy'] = sqlalchemyVersion
|
versions['sqlalchemy'] = sqlalchemyVersion
|
||||||
@ -1290,6 +1293,12 @@ def delete_book(book_id):
|
|||||||
if current_user.role_delete_books():
|
if current_user.role_delete_books():
|
||||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||||
if book:
|
if book:
|
||||||
|
# delete book from Shelfs, Downloads, Read list
|
||||||
|
ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).delete()
|
||||||
|
ub.session.query(ub.ReadBook).filter(ub.ReadBook.book_id == book_id).delete()
|
||||||
|
ub.session.query(ub.Downloads).filter(ub.Downloads.book_id == book_id).delete()
|
||||||
|
ub.session.commit()
|
||||||
|
|
||||||
if config.config_use_google_drive:
|
if config.config_use_google_drive:
|
||||||
helper.delete_book_gdrive(book) # ToDo really delete file
|
helper.delete_book_gdrive(book) # ToDo really delete file
|
||||||
else:
|
else:
|
||||||
@ -1307,7 +1316,7 @@ def delete_book(book_id):
|
|||||||
cc_string = "custom_column_" + str(c.id)
|
cc_string = "custom_column_" + str(c.id)
|
||||||
if not c.is_multiple:
|
if not c.is_multiple:
|
||||||
if len(getattr(book, cc_string)) > 0:
|
if len(getattr(book, cc_string)) > 0:
|
||||||
if c.datatype == 'bool':
|
if c.datatype == 'bool' or c.datatype == 'integer':
|
||||||
del_cc = getattr(book, cc_string)[0]
|
del_cc = getattr(book, cc_string)[0]
|
||||||
getattr(book, cc_string).remove(del_cc)
|
getattr(book, cc_string).remove(del_cc)
|
||||||
db.session.delete(del_cc)
|
db.session.delete(del_cc)
|
||||||
@ -1575,6 +1584,24 @@ def get_cover(cover_path):
|
|||||||
else:
|
else:
|
||||||
return send_from_directory(os.path.join(config.config_calibre_dir, cover_path), "cover.jpg")
|
return send_from_directory(os.path.join(config.config_calibre_dir, cover_path), "cover.jpg")
|
||||||
|
|
||||||
|
@app.route("/show/<book_id>/<book_format>")
|
||||||
|
@login_required_if_no_ano
|
||||||
|
def serve_book(book_id,book_format):
|
||||||
|
book_format = book_format.split(".")[0]
|
||||||
|
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||||
|
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == book_format.upper()).first()
|
||||||
|
app.logger.info(data.name)
|
||||||
|
if config.config_use_google_drive:
|
||||||
|
headers = Headers()
|
||||||
|
try:
|
||||||
|
headers["Content-Type"] = mimetypes.types_map['.' + book_format]
|
||||||
|
except KeyError:
|
||||||
|
headers["Content-Type"] = "application/octet-stream"
|
||||||
|
df = gdriveutils.getFileFromEbooksFolder(Gdrive.Instance().drive, book.path, data.name + "." + book_format)
|
||||||
|
return do_gdrive_download(df, headers)
|
||||||
|
else:
|
||||||
|
return send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/opds/thumb_240_240/<path:book_id>")
|
@app.route("/opds/thumb_240_240/<path:book_id>")
|
||||||
@app.route("/opds/cover_240_240/<path:book_id>")
|
@app.route("/opds/cover_240_240/<path:book_id>")
|
||||||
@ -1674,19 +1701,9 @@ def read_book(book_id, book_format):
|
|||||||
zfile.close()
|
zfile.close()
|
||||||
return render_title_template('read.html', bookid=book_id, title=_(u"Read a Book"))
|
return render_title_template('read.html', bookid=book_id, title=_(u"Read a Book"))
|
||||||
elif book_format.lower() == "pdf":
|
elif book_format.lower() == "pdf":
|
||||||
all_name = str(book_id) + "/" + book.data[0].name + ".pdf"
|
return render_title_template('readpdf.html', pdffile=book_id, title=_(u"Read a Book"))
|
||||||
tmp_file = os.path.join(book_dir, book.data[0].name) + ".pdf"
|
|
||||||
if not os.path.exists(tmp_file):
|
|
||||||
pdf_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".pdf"
|
|
||||||
copyfile(pdf_file, tmp_file)
|
|
||||||
return render_title_template('readpdf.html', pdffile=all_name, title=_(u"Read a Book"))
|
|
||||||
elif book_format.lower() == "txt":
|
elif book_format.lower() == "txt":
|
||||||
all_name = str(book_id) + "/" + book.data[0].name + ".txt"
|
return render_title_template('readtxt.html', txtfile=book_id, title=_(u"Read a Book"))
|
||||||
tmp_file = os.path.join(book_dir, book.data[0].name) + ".txt"
|
|
||||||
if not os.path.exists(all_name):
|
|
||||||
txt_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".txt"
|
|
||||||
copyfile(txt_file, tmp_file)
|
|
||||||
return render_title_template('readtxt.html', txtfile=all_name, title=_(u"Read a Book"))
|
|
||||||
elif book_format.lower() == "cbr":
|
elif book_format.lower() == "cbr":
|
||||||
all_name = str(book_id) + "/" + book.data[0].name + ".cbr"
|
all_name = str(book_id) + "/" + book.data[0].name + ".cbr"
|
||||||
tmp_file = os.path.join(book_dir, book.data[0].name) + ".cbr"
|
tmp_file = os.path.join(book_dir, book.data[0].name) + ".cbr"
|
||||||
@ -1789,10 +1806,10 @@ def login():
|
|||||||
if user and check_password_hash(user.password, form['password']):
|
if user and check_password_hash(user.password, form['password']):
|
||||||
login_user(user, remember=True)
|
login_user(user, remember=True)
|
||||||
flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success")
|
flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.nickname), category="success")
|
||||||
# test=
|
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
else:
|
else:
|
||||||
app.logger.info('Login failed for user "'+form['username']+'"')
|
ipAdress=request.headers.get('X-Forwarded-For', request.remote_addr)
|
||||||
|
app.logger.info('Login failed for user "' + form['username'] + '" IP-adress: ' + ipAdress)
|
||||||
flash(_(u"Wrong Username or Password"), category="error")
|
flash(_(u"Wrong Username or Password"), category="error")
|
||||||
|
|
||||||
return render_title_template('login.html', title=_(u"login"))
|
return render_title_template('login.html', title=_(u"login"))
|
||||||
@ -2345,7 +2362,8 @@ def edit_user(user_id):
|
|||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
to_save = request.form.to_dict()
|
to_save = request.form.to_dict()
|
||||||
if "delete" in to_save:
|
if "delete" in to_save:
|
||||||
ub.session.delete(content)
|
ub.session.query(ub.User).filter(ub.User.id == content.id).delete()
|
||||||
|
ub.session.commit()
|
||||||
flash(_(u"User '%(nick)s' deleted", nick=content.nickname), category="success")
|
flash(_(u"User '%(nick)s' deleted", nick=content.nickname), category="success")
|
||||||
return redirect(url_for('admin'))
|
return redirect(url_for('admin'))
|
||||||
else:
|
else:
|
||||||
@ -2583,6 +2601,22 @@ def edit_book(book_id):
|
|||||||
cc_class = db.cc_classes[c.id]
|
cc_class = db.cc_classes[c.id]
|
||||||
new_cc = cc_class(value=to_save[cc_string], book=book_id)
|
new_cc = cc_class(value=to_save[cc_string], book=book_id)
|
||||||
db.session.add(new_cc)
|
db.session.add(new_cc)
|
||||||
|
elif c.datatype == 'int':
|
||||||
|
if to_save[cc_string] == 'None':
|
||||||
|
to_save[cc_string] = None
|
||||||
|
if to_save[cc_string] != cc_db_value:
|
||||||
|
if cc_db_value is not None:
|
||||||
|
if to_save[cc_string] is not None:
|
||||||
|
setattr(getattr(book, cc_string)[0], 'value', to_save[cc_string])
|
||||||
|
else:
|
||||||
|
del_cc = getattr(book, cc_string)[0]
|
||||||
|
getattr(book, cc_string).remove(del_cc)
|
||||||
|
db.session.delete(del_cc)
|
||||||
|
else:
|
||||||
|
cc_class = db.cc_classes[c.id]
|
||||||
|
new_cc = cc_class(value=to_save[cc_string], book=book_id)
|
||||||
|
db.session.add(new_cc)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if c.datatype == 'rating':
|
if c.datatype == 'rating':
|
||||||
to_save[cc_string] = str(int(float(to_save[cc_string]) * 2))
|
to_save[cc_string] = str(int(float(to_save[cc_string]) * 2))
|
||||||
|
191
messages.pot
191
messages.pot
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2017-05-01 16:20+0200\n"
|
"POT-Creation-Date: 2017-06-24 12:58+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -21,31 +21,46 @@ msgstr ""
|
|||||||
msgid "not installed"
|
msgid "not installed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/helper.py:165
|
#: cps/helper.py:77
|
||||||
|
#, python-format
|
||||||
|
msgid "kindlegen binary %(kindlepath)s not found"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/helper.py:83
|
||||||
|
#, python-format
|
||||||
|
msgid "epub format not found for book id: %(book)d"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/helper.py:93
|
||||||
|
msgid "kindlegen failed, no excecution permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/helper.py:109
|
||||||
|
#, python-format
|
||||||
|
msgid "Kindlegen failed with Error %(error)s. Message: %(message)s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/helper.py:186
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Failed to send mail: %s"
|
msgid "Failed to send mail: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/helper.py:172
|
#: cps/helper.py:193
|
||||||
msgid "Calibre-web test email"
|
msgid "Calibre-web test email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/helper.py:173 cps/helper.py:185
|
#: cps/helper.py:194 cps/helper.py:206
|
||||||
msgid "This email has been sent via calibre web."
|
msgid "This email has been sent via calibre web."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/helper.py:182 cps/templates/detail.html:146
|
#: cps/helper.py:203 cps/templates/detail.html:146
|
||||||
msgid "Send to Kindle"
|
msgid "Send to Kindle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/helper.py:202 cps/helper.py:217
|
#: cps/helper.py:223 cps/helper.py:236
|
||||||
msgid "Could not find any formats suitable for sending by email"
|
msgid "Could not find any formats suitable for sending by email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/helper.py:211
|
|
||||||
msgid "Could not convert epub to mobi"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: cps/ub.py:487
|
#: cps/ub.py:487
|
||||||
msgid "Guest"
|
msgid "Guest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -103,8 +118,8 @@ msgstr ""
|
|||||||
msgid "Author: %(name)s"
|
msgid "Author: %(name)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1078 cps/web.py:1106 cps/web.py:1239 cps/web.py:1699
|
#: cps/web.py:1078 cps/web.py:1106 cps/web.py:1239 cps/web.py:1716
|
||||||
#: cps/web.py:2638
|
#: cps/web.py:2672
|
||||||
msgid "Error opening eBook. File does not exist or file is not accessible:"
|
msgid "Error opening eBook. File does not exist or file is not accessible:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -135,240 +150,244 @@ msgstr ""
|
|||||||
msgid "Category: %(name)s"
|
msgid "Category: %(name)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1284
|
#: cps/web.py:1273
|
||||||
|
msgid "Excecution permissions missing"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: cps/web.py:1287
|
||||||
msgid "Statistics"
|
msgid "Statistics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1442
|
#: cps/web.py:1451
|
||||||
msgid "Server restarted, please reload page"
|
msgid "Server restarted, please reload page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1444
|
#: cps/web.py:1453
|
||||||
msgid "Performing shutdown of server, please close window"
|
msgid "Performing shutdown of server, please close window"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1460
|
#: cps/web.py:1469
|
||||||
msgid "Update done"
|
msgid "Update done"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1538 cps/web.py:1551
|
#: cps/web.py:1547 cps/web.py:1560
|
||||||
msgid "search"
|
msgid "search"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1675 cps/web.py:1682 cps/web.py:1689 cps/web.py:1696
|
#: cps/web.py:1702 cps/web.py:1704 cps/web.py:1706 cps/web.py:1713
|
||||||
msgid "Read a Book"
|
msgid "Read a Book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1752 cps/web.py:2234
|
#: cps/web.py:1769 cps/web.py:2251
|
||||||
msgid "Please fill out all fields!"
|
msgid "Please fill out all fields!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1753 cps/web.py:1769 cps/web.py:1774 cps/web.py:1776
|
#: cps/web.py:1770 cps/web.py:1786 cps/web.py:1791 cps/web.py:1793
|
||||||
msgid "register"
|
msgid "register"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1768
|
#: cps/web.py:1785
|
||||||
msgid "An unknown error occured. Please try again later."
|
msgid "An unknown error occured. Please try again later."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1773
|
#: cps/web.py:1790
|
||||||
msgid "This username or email address is already in use."
|
msgid "This username or email address is already in use."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1791
|
#: cps/web.py:1808
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "you are now logged in as: '%(nickname)s'"
|
msgid "you are now logged in as: '%(nickname)s'"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1796
|
#: cps/web.py:1813
|
||||||
msgid "Wrong Username or Password"
|
msgid "Wrong Username or Password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1798
|
#: cps/web.py:1815
|
||||||
msgid "login"
|
msgid "login"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1815
|
#: cps/web.py:1832
|
||||||
msgid "Please configure the SMTP mail settings first..."
|
msgid "Please configure the SMTP mail settings first..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1819
|
#: cps/web.py:1836
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Book successfully send to %(kindlemail)s"
|
msgid "Book successfully send to %(kindlemail)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1823
|
#: cps/web.py:1840
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "There was an error sending this book: %(res)s"
|
msgid "There was an error sending this book: %(res)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1825 cps/web.py:2318
|
#: cps/web.py:1842 cps/web.py:2335
|
||||||
msgid "Please configure your kindle email address first..."
|
msgid "Please configure your kindle email address first..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1850
|
#: cps/web.py:1867
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Book has been added to shelf: %(sname)s"
|
msgid "Book has been added to shelf: %(sname)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1870
|
#: cps/web.py:1887
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Book has been removed from shelf: %(sname)s"
|
msgid "Book has been removed from shelf: %(sname)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1888 cps/web.py:1912
|
#: cps/web.py:1905 cps/web.py:1929
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "A shelf with the name '%(title)s' already exists."
|
msgid "A shelf with the name '%(title)s' already exists."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1893
|
#: cps/web.py:1910
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Shelf %(title)s created"
|
msgid "Shelf %(title)s created"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1895 cps/web.py:1923
|
#: cps/web.py:1912 cps/web.py:1940
|
||||||
msgid "There was an error"
|
msgid "There was an error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1896 cps/web.py:1898
|
#: cps/web.py:1913 cps/web.py:1915
|
||||||
msgid "create a shelf"
|
msgid "create a shelf"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1921
|
#: cps/web.py:1938
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Shelf %(title)s changed"
|
msgid "Shelf %(title)s changed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1924 cps/web.py:1926
|
#: cps/web.py:1941 cps/web.py:1943
|
||||||
msgid "Edit a shelf"
|
msgid "Edit a shelf"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1946
|
#: cps/web.py:1963
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "successfully deleted shelf %(name)s"
|
msgid "successfully deleted shelf %(name)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1968
|
#: cps/web.py:1985
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Shelf: '%(name)s'"
|
msgid "Shelf: '%(name)s'"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:1999
|
#: cps/web.py:2016
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change order of Shelf: '%(name)s'"
|
msgid "Change order of Shelf: '%(name)s'"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2063
|
#: cps/web.py:2080
|
||||||
msgid "Found an existing account for this email address."
|
msgid "Found an existing account for this email address."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2065 cps/web.py:2069
|
#: cps/web.py:2082 cps/web.py:2086
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s's profile"
|
msgid "%(name)s's profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2066
|
#: cps/web.py:2083
|
||||||
msgid "Profile updated"
|
msgid "Profile updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2080
|
#: cps/web.py:2097
|
||||||
msgid "Admin page"
|
msgid "Admin page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2188
|
#: cps/web.py:2205
|
||||||
msgid "Calibre-web configuration updated"
|
msgid "Calibre-web configuration updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2195 cps/web.py:2201 cps/web.py:2215
|
#: cps/web.py:2212 cps/web.py:2218 cps/web.py:2232
|
||||||
msgid "Basic Configuration"
|
msgid "Basic Configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2199
|
#: cps/web.py:2216
|
||||||
msgid "DB location is not valid, please enter correct path"
|
msgid "DB location is not valid, please enter correct path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/admin.html:34 cps/web.py:2236 cps/web.py:2288
|
#: cps/templates/admin.html:34 cps/web.py:2253 cps/web.py:2305
|
||||||
msgid "Add new user"
|
msgid "Add new user"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2280
|
#: cps/web.py:2297
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "User '%(user)s' created"
|
msgid "User '%(user)s' created"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2284
|
#: cps/web.py:2301
|
||||||
msgid "Found an existing account for this email address or nickname."
|
msgid "Found an existing account for this email address or nickname."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2306
|
#: cps/web.py:2323
|
||||||
msgid "Mail settings updated"
|
msgid "Mail settings updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2313
|
#: cps/web.py:2330
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Test E-Mail successfully send to %(kindlemail)s"
|
msgid "Test E-Mail successfully send to %(kindlemail)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2316
|
#: cps/web.py:2333
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "There was an error sending the Test E-Mail: %(res)s"
|
msgid "There was an error sending the Test E-Mail: %(res)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2320
|
#: cps/web.py:2337
|
||||||
msgid "E-Mail settings updated"
|
msgid "E-Mail settings updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2321
|
#: cps/web.py:2338
|
||||||
msgid "Edit mail settings"
|
msgid "Edit mail settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2349
|
#: cps/web.py:2367
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "User '%(nick)s' deleted"
|
msgid "User '%(nick)s' deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2445
|
#: cps/web.py:2463
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "User '%(nick)s' updated"
|
msgid "User '%(nick)s' updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2448
|
#: cps/web.py:2466
|
||||||
msgid "An unknown error occured."
|
msgid "An unknown error occured."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2451
|
#: cps/web.py:2469
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Edit User %(nick)s"
|
msgid "Edit User %(nick)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2486 cps/web.py:2490
|
#: cps/web.py:2504 cps/web.py:2508
|
||||||
msgid "unknown"
|
msgid "unknown"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2633 cps/web.py:2636 cps/web.py:2746
|
#: cps/web.py:2667 cps/web.py:2670 cps/web.py:2780
|
||||||
msgid "edit metadata"
|
msgid "edit metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2657
|
#: cps/web.py:2691
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "File extension \"%s\" is not allowed to be uploaded to this server"
|
msgid "File extension \"%s\" is not allowed to be uploaded to this server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2663
|
#: cps/web.py:2697
|
||||||
msgid "File to be uploaded must have an extension"
|
msgid "File to be uploaded must have an extension"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2680
|
#: cps/web.py:2714
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Failed to create path %s (Permission denied)."
|
msgid "Failed to create path %s (Permission denied)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2685
|
#: cps/web.py:2719
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Failed to store file %s (Permission denied)."
|
msgid "Failed to store file %s (Permission denied)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/web.py:2690
|
#: cps/web.py:2724
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Failed to delete file %s (Permission denied)."
|
msgid "Failed to delete file %s (Permission denied)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -519,7 +538,7 @@ msgid "Ok"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/admin.html:103 cps/templates/admin.html:117
|
#: cps/templates/admin.html:103 cps/templates/admin.html:117
|
||||||
#: cps/templates/book_edit.html:115 cps/templates/book_edit.html:137
|
#: cps/templates/book_edit.html:120 cps/templates/book_edit.html:142
|
||||||
#: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
|
#: cps/templates/config_edit.html:127 cps/templates/email_edit.html:36
|
||||||
#: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
|
#: cps/templates/shelf.html:53 cps/templates/shelf_edit.html:19
|
||||||
#: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
|
#: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:128
|
||||||
@ -542,12 +561,12 @@ msgstr ""
|
|||||||
msgid "Book Title"
|
msgid "Book Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:26 cps/templates/book_edit.html:176
|
#: cps/templates/book_edit.html:26 cps/templates/book_edit.html:181
|
||||||
#: cps/templates/search_form.html:10
|
#: cps/templates/search_form.html:10
|
||||||
msgid "Author"
|
msgid "Author"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:30 cps/templates/book_edit.html:178
|
#: cps/templates/book_edit.html:30 cps/templates/book_edit.html:183
|
||||||
msgid "Description"
|
msgid "Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -584,74 +603,74 @@ msgstr ""
|
|||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:110
|
#: cps/templates/book_edit.html:115
|
||||||
msgid "view book after edit"
|
msgid "view book after edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:113 cps/templates/book_edit.html:149
|
#: cps/templates/book_edit.html:118 cps/templates/book_edit.html:154
|
||||||
msgid "Get metadata"
|
msgid "Get metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:114 cps/templates/config_edit.html:125
|
#: cps/templates/book_edit.html:119 cps/templates/config_edit.html:125
|
||||||
#: cps/templates/login.html:19 cps/templates/search_form.html:79
|
#: cps/templates/login.html:19 cps/templates/search_form.html:79
|
||||||
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
|
#: cps/templates/shelf_edit.html:17 cps/templates/user_edit.html:126
|
||||||
msgid "Submit"
|
msgid "Submit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:128
|
#: cps/templates/book_edit.html:133
|
||||||
msgid "Are really you sure?"
|
msgid "Are really you sure?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:131
|
#: cps/templates/book_edit.html:136
|
||||||
msgid "Book will be deleted from Calibre database"
|
msgid "Book will be deleted from Calibre database"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:132
|
#: cps/templates/book_edit.html:137
|
||||||
msgid "and from hard disk"
|
msgid "and from hard disk"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:136
|
#: cps/templates/book_edit.html:141
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:152
|
#: cps/templates/book_edit.html:157
|
||||||
msgid "Keyword"
|
msgid "Keyword"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:153
|
#: cps/templates/book_edit.html:158
|
||||||
msgid " Search keyword "
|
msgid " Search keyword "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:155 cps/templates/layout.html:60
|
#: cps/templates/book_edit.html:160 cps/templates/layout.html:60
|
||||||
msgid "Go!"
|
msgid "Go!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:156
|
#: cps/templates/book_edit.html:161
|
||||||
msgid "Click the cover to load metadata to the form"
|
msgid "Click the cover to load metadata to the form"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:160 cps/templates/book_edit.html:173
|
#: cps/templates/book_edit.html:165 cps/templates/book_edit.html:178
|
||||||
msgid "Loading..."
|
msgid "Loading..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:163
|
#: cps/templates/book_edit.html:168
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:174
|
#: cps/templates/book_edit.html:179
|
||||||
msgid "Search error!"
|
msgid "Search error!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:175
|
#: cps/templates/book_edit.html:180
|
||||||
msgid "No Result! Please try anonther keyword."
|
msgid "No Result! Please try anonther keyword."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:177 cps/templates/detail.html:76
|
#: cps/templates/book_edit.html:182 cps/templates/detail.html:76
|
||||||
#: cps/templates/search_form.html:14
|
#: cps/templates/search_form.html:14
|
||||||
msgid "Publisher"
|
msgid "Publisher"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: cps/templates/book_edit.html:179
|
#: cps/templates/book_edit.html:184
|
||||||
msgid "Source"
|
msgid "Source"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ Calibre Web is a web app providing a clean interface for browsing, reading and d
|
|||||||
- full graphical setup
|
- full graphical setup
|
||||||
- User management
|
- User management
|
||||||
- Admin interface
|
- Admin interface
|
||||||
- User Interface in english, french, german, polish, russian, simplified chinese, spanish
|
- User Interface in dutch, english, french, german, polish, russian, simplified chinese, spanish
|
||||||
- OPDS feed for eBook reader apps
|
- OPDS feed for eBook reader apps
|
||||||
- Filter and search by titles, authors, tags, series and language
|
- Filter and search by titles, authors, tags, series and language
|
||||||
- Create custom book collection (shelves)
|
- Create custom book collection (shelves)
|
||||||
|
Loading…
Reference in New Issue
Block a user