Bugfix Publisher (upper/lower case, remove publisher, publisher visibility on new users)

404 messages on non existing categorys, languages, series
Updated Testresult
pull/703/head
Ozzieisaacs 6 years ago
commit 6ec9bc9e5c

@ -142,6 +142,17 @@ var languages = new Bloodhound({
} }
}); });
var publishers = new Bloodhound({
name: "publisher",
datumTokenizer: function datumTokenizer(datum) {
return [datum.name];
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: getPath() + "/get_publishers_json?q=%QUERY"
}
});
function sourceSplit(query, cb, split, source) { function sourceSplit(query, cb, split, source) {
var bhAdapter = source.ttAdapter(); var bhAdapter = source.ttAdapter();
@ -224,6 +235,20 @@ promiseLanguages.done(function() {
); );
}); });
var promisePublishers = publishers.initialize();
promisePublishers.done(function() {
$("#publisher").typeahead(
{
highlight: true, minLength: 0,
hint: true
}, {
name: "publishers",
displayKey: "name",
source: publishers.ttAdapter()
}
);
});
$("#search").on("change input.typeahead:selected", function() { $("#search").on("change input.typeahead:selected", function() {
var form = $("form").serialize(); var form = $("form").serialize();
$.getJSON( getPath() + "/get_matching_tags", form, function( data ) { $.getJSON( getPath() + "/get_matching_tags", form, function( data ) {

@ -101,7 +101,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="publisher">{{_('Publisher')}}</label> <label for="publisher">{{_('Publisher')}}</label>
<input type="text" class="form-control typeahead" name="publisher" id="publisher" value="{% if book.publishers|length > 0 %}{{book.publishers[0].name}}{% endif %}" disabled> <input type="text" class="form-control typeahead" name="publisher" id="publisher" value="{% if book.publishers|length > 0 %}{{book.publishers[0].name}}{% endif %}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="languages">{{_('Language')}}</label> <label for="languages">{{_('Language')}}</label>

@ -143,6 +143,10 @@
<input type="checkbox" name="show_author" id="show_author" {% if content.show_author() %}checked{% endif %}> <input type="checkbox" name="show_author" id="show_author" {% if content.show_author() %}checked{% endif %}>
<label for="show_author">{{_('Show author selection')}}</label> <label for="show_author">{{_('Show author selection')}}</label>
</div> </div>
<div class="form-group">
<input type="checkbox" name="show_publisher" id="show_publisher" {% if content.show_publisher() %}checked{% endif %}>
<label for="show_publisher">{{_('Show publisher selection')}}</label>
</div>
<div class="form-group"> <div class="form-group">
<input type="checkbox" name="show_read_and_unread" id="show_read_and_unread" {% if content.show_read_and_unread() %}checked{% endif %}> <input type="checkbox" name="show_read_and_unread" id="show_read_and_unread" {% if content.show_read_and_unread() %}checked{% endif %}>
<label for="show_read_and_unread">{{_('Show read and unread')}}</label> <label for="show_read_and_unread">{{_('Show read and unread')}}</label>

@ -120,13 +120,17 @@
</div> </div>
{% endif %} {% endif %}
{% if entry.publishers|length > 0 %} {% if entry.publishers|length > 0 %}
<div class="publishers"> <div class="publishers">
<p> <p>
<span>{{_('Publisher')}}:{% for publisher in entry.publishers %} {{publisher.name}}{% if not loop.last %},{% endif %}{% endfor %}</span> <span>{{_('Publisher')}}:
</p> <a href="{{url_for('publisher', book_id=entry.publishers[0].id ) }}">{{entry.publishers[0].name}}</a>
</span>
</p>
</div> </div>
{% endif %} {% endif %}
{% if entry.pubdate[:10] != '0101-01-01' %} {% if entry.pubdate[:10] != '0101-01-01' %}
<p>{{_('Publishing date')}}: {{entry.pubdate|formatdate}} </p> <p>{{_('Publishing date')}}: {{entry.pubdate|formatdate}} </p>
{% endif %} {% endif %}

@ -43,6 +43,9 @@
<author> <author>
<name>{{entry.authors[0].name}}</name> <name>{{entry.authors[0].name}}</name>
</author> </author>
<publisher>
<name>{{entry.publishers[0].name}}</name>
</publisher>
<dcterms:language>{{entry.language}}</dcterms:language> <dcterms:language>{{entry.language}}</dcterms:language>
{% for tag in entry.tags %} {% for tag in entry.tags %}
<category scheme="http://www.bisg.org/standards/bisac_subject/index.html" <category scheme="http://www.bisg.org/standards/bisac_subject/index.html"

@ -39,7 +39,7 @@
<updated>{{ current_time }}</updated> <updated>{{ current_time }}</updated>
<content type="text">{{_('Show Random Books')}}</content> <content type="text">{{_('Show Random Books')}}</content>
</entry> </entry>
{% if not current_user.is_anonymous %} {% if not current_user.is_anonymous %}
<entry> <entry>
<title>{{_('Read Books')}}</title> <title>{{_('Read Books')}}</title>
<link rel="subsection" href="{{url_for('feed_read_books')}}" type="application/atom+xml;profile=opds-catalog"/> <link rel="subsection" href="{{url_for('feed_read_books')}}" type="application/atom+xml;profile=opds-catalog"/>
@ -47,7 +47,7 @@
<updated>{{ current_time }}</updated> <updated>{{ current_time }}</updated>
<content type="text">{{_('Read Books')}}</content> <content type="text">{{_('Read Books')}}</content>
</entry> </entry>
{% endif %} {% endif %}
<entry> <entry>
<title>{{_('Unread Books')}}</title> <title>{{_('Unread Books')}}</title>
<link rel="subsection" href="{{url_for('feed_unread_books')}}" type="application/atom+xml;profile=opds-catalog"/> <link rel="subsection" href="{{url_for('feed_unread_books')}}" type="application/atom+xml;profile=opds-catalog"/>
@ -61,35 +61,42 @@
<id>{{url_for('feed_authorindex')}}</id> <id>{{url_for('feed_authorindex')}}</id>
<updated>{{ current_time }}</updated> <updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by Author')}}</content> <content type="text">{{_('Books ordered by Author')}}</content>
</entry> </entry>
<entry> <entry>
<title>{{_('Publishers')}}</title>
<link rel="subsection" href="{{url_for('feed_publisherindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_publisherindex')}}</id>
<updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by publisher')}}</content>
</entry>
<entry>
<title>{{_('Category list')}}</title> <title>{{_('Category list')}}</title>
<link rel="subsection" href="{{url_for('feed_categoryindex')}}" type="application/atom+xml;profile=opds-catalog"/> <link rel="subsection" href="{{url_for('feed_categoryindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_categoryindex')}}</id> <id>{{url_for('feed_categoryindex')}}</id>
<updated>{{ current_time }}</updated> <updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by category')}}</content> <content type="text">{{_('Books ordered by category')}}</content>
</entry> </entry>
<entry> <entry>
<title>{{_('Series list')}}</title> <title>{{_('Series list')}}</title>
<link rel="subsection" href="{{url_for('feed_seriesindex')}}" type="application/atom+xml;profile=opds-catalog"/> <link rel="subsection" href="{{url_for('feed_seriesindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_seriesindex')}}</id> <id>{{url_for('feed_seriesindex')}}</id>
<updated>{{ current_time }}</updated> <updated>{{ current_time }}</updated>
<content type="text">{{_('Books ordered by series')}}</content> <content type="text">{{_('Books ordered by series')}}</content>
</entry> </entry>
<entry> <entry>
<title>{{_('Public Shelves')}}</title> <title>{{_('Public Shelves')}}</title>
<link rel="subsection" href="{{url_for('feed_shelfindex', public="public")}}" type="application/atom+xml;profile=opds-catalog"/> <link rel="subsection" href="{{url_for('feed_shelfindex', public="public")}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_shelfindex', public="public")}}</id> <id>{{url_for('feed_shelfindex', public="public")}}</id>
<updated>{{ current_time }}</updated> <updated>{{ current_time }}</updated>
<content type="text">{{_('Books organized in public shelfs, visible to everyone')}}</content> <content type="text">{{_('Books organized in public shelfs, visible to everyone')}}</content>
</entry> </entry>
{% if not current_user.is_anonymous %} {% if not current_user.is_anonymous %}
<entry> <entry>
<title>{{_('Your Shelves')}}</title> <title>{{_('Your Shelves')}}</title>
<link rel="subsection" href="{{url_for('feed_shelfindex')}}" type="application/atom+xml;profile=opds-catalog"/> <link rel="subsection" href="{{url_for('feed_shelfindex')}}" type="application/atom+xml;profile=opds-catalog"/>
<id>{{url_for('feed_shelfindex')}}</id> <id>{{url_for('feed_shelfindex')}}</id>
<updated>{{ current_time }}</updated> <updated>{{ current_time }}</updated>
<content type="text">{{_("User's own shelfs, only visible to the current user himself")}}</content> <content type="text">{{_("User's own shelfs, only visible to the current user himself")}}</content>
</entry> </entry>
{% endif %} {% endif %}
</feed> </feed>

@ -159,6 +159,9 @@
{% if g.user.show_author() %} {% if g.user.show_author() %}
<li id="nav_author" {% if page == 'author' %}class="active"{% endif %}><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span>{{_('Authors')}}</a></li> <li id="nav_author" {% if page == 'author' %}class="active"{% endif %}><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span>{{_('Authors')}}</a></li>
{%endif%} {%endif%}
{% if g.user.show_publisher() %}
<li id="nav_publisher" {% if page == 'publisher' %}class="active"{% endif %}><a href="{{url_for('publisher_list')}}"><span class="glyphicon glyphicon-text-size"></span>{{_('Publishers')}}</a></li>
{%endif%}
{% if g.user.filter_language() == 'all' and g.user.show_language() %} {% if g.user.filter_language() == 'all' and g.user.show_language() %}
<li id="nav_lang" {% if page == 'language' %}class="active"{% endif %}><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span>{{_('Languages')}} </a></li> <li id="nav_lang" {% if page == 'language' %}class="active"{% endif %}><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span>{{_('Languages')}} </a></li>
{%endif%} {%endif%}

@ -89,6 +89,10 @@
<input type="checkbox" name="show_author" id="show_author" {% if content.show_author() %}checked{% endif %}> <input type="checkbox" name="show_author" id="show_author" {% if content.show_author() %}checked{% endif %}>
<label for="show_author">{{_('Show author selection')}}</label> <label for="show_author">{{_('Show author selection')}}</label>
</div> </div>
<div class="form-group">
<input type="checkbox" name="show_publisher" id="show_publisher" {% if content.show_publisher() %}checked{% endif %}>
<label for="show_publisher">{{_('Show publisher selection')}}</label>
</div>
<div class="form-group"> <div class="form-group">
<input type="checkbox" name="show_read_and_unread" id="show_read_and_unread" {% if content.show_read_and_unread() %}checked{% endif %}> <input type="checkbox" name="show_read_and_unread" id="show_read_and_unread" {% if content.show_read_and_unread() %}checked{% endif %}>
<label for="show_read_and_unread">{{_('Show read and unread')}}</label> <label for="show_read_and_unread">{{_('Show read and unread')}}</label>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -41,6 +41,7 @@ SIDEBAR_READ_AND_UNREAD = 256
SIDEBAR_RECENT = 512 SIDEBAR_RECENT = 512
SIDEBAR_SORTED = 1024 SIDEBAR_SORTED = 1024
MATURE_CONTENT = 2048 MATURE_CONTENT = 2048
SIDEBAR_PUBLISHER = 4096
DEFAULT_PASS = "admin123" DEFAULT_PASS = "admin123"
DEFAULT_PORT = int(os.environ.get("CALIBRE_PORT", 8083)) DEFAULT_PORT = int(os.environ.get("CALIBRE_PORT", 8083))
@ -136,6 +137,9 @@ class UserBase:
def show_author(self): def show_author(self):
return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_AUTHOR == SIDEBAR_AUTHOR)) return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_AUTHOR == SIDEBAR_AUTHOR))
def show_publisher(self):
return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_PUBLISHER == SIDEBAR_PUBLISHER))
def show_best_rated_books(self): def show_best_rated_books(self):
return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_BEST_RATED == SIDEBAR_BEST_RATED)) return bool((self.sidebar_view is not None)and(self.sidebar_view & SIDEBAR_BEST_RATED == SIDEBAR_BEST_RATED))
@ -297,7 +301,7 @@ class Settings(Base):
config_anonbrowse = Column(SmallInteger, default=0) config_anonbrowse = Column(SmallInteger, default=0)
config_public_reg = Column(SmallInteger, default=0) config_public_reg = Column(SmallInteger, default=0)
config_default_role = Column(SmallInteger, default=0) config_default_role = Column(SmallInteger, default=0)
config_default_show = Column(SmallInteger, default=2047) config_default_show = Column(SmallInteger, default=6143)
config_columns_to_ignore = Column(String) config_columns_to_ignore = Column(String)
config_use_google_drive = Column(Boolean) config_use_google_drive = Column(Boolean)
config_google_drive_folder = Column(String) config_google_drive_folder = Column(String)
@ -485,6 +489,10 @@ class Config:
return bool((self.config_default_show is not None) and return bool((self.config_default_show is not None) and
(self.config_default_show & SIDEBAR_AUTHOR == SIDEBAR_AUTHOR)) (self.config_default_show & SIDEBAR_AUTHOR == SIDEBAR_AUTHOR))
def show_publisher(self):
return bool((self.config_default_show is not None) and
(self.config_default_show & SIDEBAR_PUBLISHER == SIDEBAR_PUBLISHER))
def show_best_rated_books(self): def show_best_rated_books(self):
return bool((self.config_default_show is not None) and return bool((self.config_default_show is not None) and
(self.config_default_show & SIDEBAR_BEST_RATED == SIDEBAR_BEST_RATED)) (self.config_default_show & SIDEBAR_BEST_RATED == SIDEBAR_BEST_RATED))
@ -740,7 +748,7 @@ def create_admin_user():
user.role = ROLE_USER + ROLE_ADMIN + ROLE_DOWNLOAD + ROLE_UPLOAD + ROLE_EDIT + ROLE_DELETE_BOOKS + ROLE_PASSWD user.role = ROLE_USER + ROLE_ADMIN + ROLE_DOWNLOAD + ROLE_UPLOAD + ROLE_EDIT + ROLE_DELETE_BOOKS + ROLE_PASSWD
user.sidebar_view = DETAIL_RANDOM + SIDEBAR_LANGUAGE + SIDEBAR_SERIES + SIDEBAR_CATEGORY + SIDEBAR_HOT + \ user.sidebar_view = DETAIL_RANDOM + SIDEBAR_LANGUAGE + SIDEBAR_SERIES + SIDEBAR_CATEGORY + SIDEBAR_HOT + \
SIDEBAR_RANDOM + SIDEBAR_AUTHOR + SIDEBAR_BEST_RATED + SIDEBAR_READ_AND_UNREAD + SIDEBAR_RECENT + \ SIDEBAR_RANDOM + SIDEBAR_AUTHOR + SIDEBAR_BEST_RATED + SIDEBAR_READ_AND_UNREAD + SIDEBAR_RECENT + \
SIDEBAR_SORTED + MATURE_CONTENT SIDEBAR_SORTED + MATURE_CONTENT + SIDEBAR_PUBLISHER
user.password = generate_password_hash(DEFAULT_PASS) user.password = generate_password_hash(DEFAULT_PASS)

@ -529,6 +529,10 @@ def fill_indexpage(page, database, db_filter, order, *join):
# Modifies different Database objects, first check if elements have to be added to database, than check # Modifies different Database objects, first check if elements have to be added to database, than check
# if elements have to be deleted, because they are no longer used # if elements have to be deleted, because they are no longer used
def modify_database_object(input_elements, db_book_object, db_object, db_session, db_type): def modify_database_object(input_elements, db_book_object, db_object, db_session, db_type):
# passing input_elements not as a list may lead to undesired results
if not isinstance(input_elements, list):
raise TypeError(str(input_elements) + " should be passed as a list")
input_elements = [x for x in input_elements if x != ''] input_elements = [x for x in input_elements if x != '']
# we have all input element (authors, series, tags) names now # we have all input element (authors, series, tags) names now
# 1. search for elements to remove # 1. search for elements to remove
@ -542,13 +546,13 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
else: else:
type_elements = c_elements.name type_elements = c_elements.name
for inp_element in input_elements: for inp_element in input_elements:
if inp_element == type_elements: if inp_element.lower() == type_elements.lower():
found = True found = True
break break
# if the element was not found in the new list, add it to remove list # if the element was not found in the new list, add it to remove list
if not found: if not found:
del_elements.append(c_elements) del_elements.append(c_elements)
# 2. search for elements that need to be added # 2. search for elements that need to be added
add_elements = [] add_elements = []
for inp_element in input_elements: for inp_element in input_elements:
found = False found = False
@ -580,20 +584,46 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session
db_filter = db_object.name db_filter = db_object.name
for add_element in add_elements: for add_element in add_elements:
# check if a element with that name exists # check if a element with that name exists
new_element = db_session.query(db_object).filter(db_filter == add_element).first() db_element = db_session.query(db_object).filter(db_filter == add_element).first()
# if no element is found add it # if no element is found add it
if new_element is None: # if new_element is None:
if db_type == 'author': if db_type == 'author':
new_element = db_object(add_element, add_element.replace('|', ','), "") new_element = db_object(add_element, add_element.replace('|', ','), "")
elif db_type == 'series': elif db_type == 'series':
new_element = db_object(add_element, add_element) new_element = db_object(add_element, add_element)
elif db_type == 'custom': elif db_type == 'custom':
new_element = db_object(value=add_element) new_element = db_object(value=add_element)
else: # db_type should be tag, language or publisher elif db_type == 'publisher':
new_element = db_object(add_element) new_element = db_object(add_element, None)
else: # db_type should be tag or language
new_element = db_object(add_element)
if db_element is None:
db_session.add(new_element) db_session.add(new_element)
# add element to book db_book_object.append(new_element)
db_book_object.append(new_element) else:
if db_type == 'custom' and db_element.value != add_element:
new_element.value = add_element
# new_element = db_element
elif db_type == 'language' and db_element.lang_code != add_element:
db_element.lang_code = add_element
# new_element = db_element
elif db_type == 'series' and db_element.name != add_element:
db_element.name = add_element # = add_element # new_element = db_object(add_element, add_element)
db_element.sort = add_element
# new_element = db_element
elif db_type == 'author' and db_element.name != add_element:
db_element.name = add_element
db_element.sort = add_element.replace('|', ',')
# new_element = db_element
if db_type == 'publisher' and db_element.name != add_element:
db_element.name = add_element
db_element.sort = None
# new_element = db_element
elif db_element.name != add_element:
db_element.name = add_element
# new_element = db_element
# add element to book
db_book_object.append(db_element)
# read search results from calibre-database and return it (function is used for feed and simple search # read search results from calibre-database and return it (function is used for feed and simple search
@ -745,6 +775,26 @@ def feed_author(book_id):
return render_xml_template('feed.xml', entries=entries, pagination=pagination) return render_xml_template('feed.xml', entries=entries, pagination=pagination)
@app.route("/opds/publisher")
@requires_basic_auth_if_no_ano
def feed_publisherindex():
off = request.args.get("offset") or 0
entries = db.session.query(db.Publishers).join(db.books_publishers_link).join(db.Books).filter(common_filters())\
.group_by('books_publishers_link.publisher').order_by(db.Publishers.sort).limit(config.config_books_per_page).offset(off)
pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page,
len(db.session.query(db.Publishers).all()))
return render_xml_template('feed.xml', listelements=entries, folder='feed_publisher', pagination=pagination)
@app.route("/opds/publisher/<int:book_id>")
@requires_basic_auth_if_no_ano
def feed_publisher(book_id):
off = request.args.get("offset") or 0
entries, __, pagination = fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1),
db.Books, db.Books.publishers.any(db.Publishers.id == book_id), [db.Books.timestamp.desc()])
return render_xml_template('feed.xml', entries=entries, pagination=pagination)
@app.route("/opds/category") @app.route("/opds/category")
@requires_basic_auth_if_no_ano @requires_basic_auth_if_no_ano
def feed_categoryindex(): def feed_categoryindex():
@ -1028,6 +1078,16 @@ def get_authors_json():
return json_dumps return json_dumps
@app.route("/get_publishers_json", methods=['GET', 'POST'])
@login_required_if_no_ano
def get_publishers_json():
if request.method == "GET":
query = request.args.get('q')
entries = db.session.query(db.Publishers).filter(db.Publishers.name.ilike("%" + query + "%")).all()
json_dumps = json.dumps([dict(name=r.name.replace('|',',')) for r in entries])
return json_dumps
@app.route("/get_tags_json", methods=['GET', 'POST']) @app.route("/get_tags_json", methods=['GET', 'POST'])
@login_required_if_no_ano @login_required_if_no_ano
def get_tags_json(): def get_tags_json():
@ -1340,7 +1400,8 @@ def best_rated_books(page):
[db.Books.timestamp.desc()]) [db.Books.timestamp.desc()])
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Best rated books"), page="rated") title=_(u"Best rated books"), page="rated")
abort(404) else:
abort(404)
@app.route("/discover", defaults={'page': 1}) @app.route("/discover", defaults={'page': 1})
@ -1398,6 +1459,33 @@ def author(book_id, page):
title=name, author=author_info, other_books=other_books, page="author") title=name, author=author_info, other_books=other_books, page="author")
@app.route("/publisher")
@login_required_if_no_ano
def publisher_list():
if current_user.show_publisher():
entries = db.session.query(db.Publishers, func.count('books_publishers_link.book').label('count'))\
.join(db.books_publishers_link).join(db.Books).filter(common_filters())\
.group_by('books_publishers_link.publisher').order_by(db.Publishers.sort).all()
return render_title_template('list.html', entries=entries, folder='publisher',
title=_(u"Publisher list"), page="publisherlist")
else:
abort(404)
@app.route("/publisher/<int:book_id>", defaults={'page': 1})
@app.route('/publisher/<int:book_id>/<int:page>')
@login_required_if_no_ano
def publisher(book_id, page):
publisher = db.session.query(db.Publishers).filter(db.Publishers.id == book_id).first()
if publisher:
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.publishers.any(db.Publishers.id == book_id),
(db.Series.name, db.Books.series_index), db.books_series_link, db.Series)
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Publisher: %(name)s", name=publisher.name), page="publisher")
else:
abort(404)
def get_unique_other_books(library_books, author_books): def get_unique_other_books(library_books, author_books):
# Get all identifiers (ISBN, Goodreads, etc) and filter author's books by that list so we show fewer duplicates # Get all identifiers (ISBN, Goodreads, etc) and filter author's books by that list so we show fewer duplicates
# Note: Not all images will be shown, even though they're available on Goodreads.com. # Note: Not all images will be shown, even though they're available on Goodreads.com.
@ -1434,15 +1522,18 @@ def series_list():
@app.route("/series/<int:book_id>/<int:page>'") @app.route("/series/<int:book_id>/<int:page>'")
@login_required_if_no_ano @login_required_if_no_ano
def series(book_id, page): def series(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.series.any(db.Series.id == book_id), name = db.session.query(db.Series).filter(db.Series.id == book_id).first()
if name:
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.series.any(db.Series.id == book_id),
[db.Books.series_index]) [db.Books.series_index])
name = db.session.query(db.Series).filter(db.Series.id == book_id).first().name if entries:
if entries: return render_title_template('index.html', random=random, pagination=pagination, entries=entries,
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, title=_(u"Series: %(serie)s", serie=name.name), page="series")
title=_(u"Series: %(serie)s", serie=name), page="series") else:
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
return redirect(url_for("index"))
else: else:
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error") abort(404)
return redirect(url_for("index"))
@app.route("/language") @app.route("/language")
@ -1475,15 +1566,18 @@ def language_overview():
@app.route('/language/<name>/page/<int:page>') @app.route('/language/<name>/page/<int:page>')
@login_required_if_no_ano @login_required_if_no_ano
def language(name, page): def language(name, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.languages.any(db.Languages.lang_code == name),
[db.Books.timestamp.desc()])
try: try:
cur_l = LC.parse(name) cur_l = LC.parse(name)
name = cur_l.get_language_name(get_locale()) lang_name = cur_l.get_language_name(get_locale())
except UnknownLocaleError: except UnknownLocaleError:
name = _(isoLanguages.get(part3=name).name) try:
lang_name = _(isoLanguages.get(part3=name).name)
except KeyError:
abort(404)
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.languages.any(db.Languages.lang_code == name),
[db.Books.timestamp.desc()])
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Language: %(name)s", name=name), page="language") title=_(u"Language: %(name)s", name=lang_name), page="language")
@app.route("/category") @app.route("/category")
@ -1503,12 +1597,14 @@ def category_list():
@app.route('/category/<int:book_id>/<int:page>') @app.route('/category/<int:book_id>/<int:page>')
@login_required_if_no_ano @login_required_if_no_ano
def category(book_id, page): def category(book_id, page):
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id), name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first()
(db.Series.name, db.Books.series_index),db.books_series_link,db.Series) if name:
entries, random, pagination = fill_indexpage(page, db.Books, db.Books.tags.any(db.Tags.id == book_id),
name = db.session.query(db.Tags).filter(db.Tags.id == book_id).first().name (db.Series.name, db.Books.series_index),db.books_series_link,db.Series)
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
title=_(u"Category: %(name)s", name=name), page="category") title=_(u"Category: %(name)s", name=name.name), page="category")
else:
abort(404)
@app.route("/ajax/toggleread/<int:book_id>", methods=['POST']) @app.route("/ajax/toggleread/<int:book_id>", methods=['POST'])
@ -2761,6 +2857,8 @@ def profile():
content.sidebar_view += ub.SIDEBAR_BEST_RATED content.sidebar_view += ub.SIDEBAR_BEST_RATED
if "show_author" in to_save: if "show_author" in to_save:
content.sidebar_view += ub.SIDEBAR_AUTHOR content.sidebar_view += ub.SIDEBAR_AUTHOR
if "show_publisher" in to_save:
content.sidebar_view += ub.SIDEBAR_PUBLISHER
if "show_read_and_unread" in to_save: if "show_read_and_unread" in to_save:
content.sidebar_view += ub.SIDEBAR_READ_AND_UNREAD content.sidebar_view += ub.SIDEBAR_READ_AND_UNREAD
if "show_detail_random" in to_save: if "show_detail_random" in to_save:
@ -2871,6 +2969,8 @@ def view_configuration():
content.config_default_show = content.config_default_show + ub.SIDEBAR_RANDOM content.config_default_show = content.config_default_show + ub.SIDEBAR_RANDOM
if "show_author" in to_save: if "show_author" in to_save:
content.config_default_show = content.config_default_show + ub.SIDEBAR_AUTHOR content.config_default_show = content.config_default_show + ub.SIDEBAR_AUTHOR
if "show_publisher" in to_save:
content.config_default_show = content.config_default_show + ub.SIDEBAR_PUBLISHER
if "show_best_rated" in to_save: if "show_best_rated" in to_save:
content.config_default_show = content.config_default_show + ub.SIDEBAR_BEST_RATED content.config_default_show = content.config_default_show + ub.SIDEBAR_BEST_RATED
if "show_read_and_unread" in to_save: if "show_read_and_unread" in to_save:
@ -3120,6 +3220,8 @@ def new_user():
content.sidebar_view += ub.SIDEBAR_BEST_RATED content.sidebar_view += ub.SIDEBAR_BEST_RATED
if "show_author" in to_save: if "show_author" in to_save:
content.sidebar_view += ub.SIDEBAR_AUTHOR content.sidebar_view += ub.SIDEBAR_AUTHOR
if "show_publisher" in to_save:
content.sidebar_view += ub.SIDEBAR_PUBLISHER
if "show_detail_random" in to_save: if "show_detail_random" in to_save:
content.sidebar_view += ub.DETAIL_RANDOM content.sidebar_view += ub.DETAIL_RANDOM
if "show_sorted" in to_save: if "show_sorted" in to_save:
@ -3643,11 +3745,14 @@ def edit_book(book_id):
book.pubdate = db.Books.DEFAULT_PUBDATE book.pubdate = db.Books.DEFAULT_PUBDATE
else: else:
book.pubdate = db.Books.DEFAULT_PUBDATE book.pubdate = db.Books.DEFAULT_PUBDATE
'''if len(book.publishers):
if to_save["publisher"] != book.publishers[0].name: if to_save["publisher"]:
modify_database_object(to_save["publisher"], book.publishers, db.Publishers, db.session, 'series') publisher = to_save["publisher"].rstrip().strip()
else: if len(book.publishers) == 0 or (len(book.publishers) > 0 and publisher != book.publishers[0].name):
modify_database_object(to_save["publisher"], book.publishers, db.Publishers, db.session, 'series')''' modify_database_object([publisher], book.publishers, db.Publishers, db.session, 'publisher')
elif len(book.publishers):
modify_database_object([], book.publishers, db.Publishers, db.session, 'publisher')
# handle book languages # handle book languages
input_languages = to_save["languages"].split(',') input_languages = to_save["languages"].split(',')

@ -8,14 +8,14 @@ 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: 2018-10-15 20:28+0200\n" "POT-Creation-Date: 2018-10-28 21:32+0100\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"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n" "Generated-By: Babel 2.6.0\n"
#: cps/book_formats.py:129 cps/book_formats.py:130 cps/book_formats.py:134 #: cps/book_formats.py:129 cps/book_formats.py:130 cps/book_formats.py:134
#: cps/book_formats.py:138 cps/converter.py:11 cps/converter.py:27 #: cps/book_formats.py:138 cps/converter.py:11 cps/converter.py:27
@ -117,578 +117,587 @@ msgstr ""
msgid "Unrar binary file not found" msgid "Unrar binary file not found"
msgstr "" msgstr ""
#: cps/web.py:1111 cps/web.py:2791 #: cps/web.py:1171 cps/web.py:2889
msgid "Unknown" msgid "Unknown"
msgstr "" msgstr ""
#: cps/web.py:1120 cps/web.py:1151 #: cps/web.py:1180 cps/web.py:1211
msgid "HTTP Error" msgid "HTTP Error"
msgstr "" msgstr ""
#: cps/web.py:1122 cps/web.py:1153 #: cps/web.py:1182 cps/web.py:1213
msgid "Connection error" msgid "Connection error"
msgstr "" msgstr ""
#: cps/web.py:1124 cps/web.py:1155 #: cps/web.py:1184 cps/web.py:1215
msgid "Timeout while establishing connection" msgid "Timeout while establishing connection"
msgstr "" msgstr ""
#: cps/web.py:1126 cps/web.py:1157 #: cps/web.py:1186 cps/web.py:1217
msgid "General error" msgid "General error"
msgstr "" msgstr ""
#: cps/web.py:1132 #: cps/web.py:1192
msgid "Unexpected data while reading update information" msgid "Unexpected data while reading update information"
msgstr "" msgstr ""
#: cps/web.py:1139 #: cps/web.py:1199
msgid "No update available. You already have the latest version installed" msgid "No update available. You already have the latest version installed"
msgstr "" msgstr ""
#: cps/web.py:1164 #: cps/web.py:1224
msgid "A new update is available. Click on the button below to update to the latest version." msgid "A new update is available. Click on the button below to update to the latest version."
msgstr "" msgstr ""
#: cps/web.py:1214 #: cps/web.py:1274
msgid "Could not fetch update information" msgid "Could not fetch update information"
msgstr "" msgstr ""
#: cps/web.py:1229 #: cps/web.py:1289
msgid "Requesting update package" msgid "Requesting update package"
msgstr "" msgstr ""
#: cps/web.py:1230 #: cps/web.py:1290
msgid "Downloading update package" msgid "Downloading update package"
msgstr "" msgstr ""
#: cps/web.py:1231 #: cps/web.py:1291
msgid "Unzipping update package" msgid "Unzipping update package"
msgstr "" msgstr ""
#: cps/web.py:1232 #: cps/web.py:1292
msgid "Files are replaced" msgid "Files are replaced"
msgstr "" msgstr ""
#: cps/web.py:1233 #: cps/web.py:1293
msgid "Database connections are closed" msgid "Database connections are closed"
msgstr "" msgstr ""
#: cps/web.py:1234 #: cps/web.py:1294
msgid "Server is stopped" msgid "Server is stopped"
msgstr "" msgstr ""
#: cps/web.py:1235 #: cps/web.py:1295
msgid "Update finished, please press okay and reload page" msgid "Update finished, please press okay and reload page"
msgstr "" msgstr ""
#: cps/web.py:1255 #: cps/web.py:1315
msgid "Recently Added Books" msgid "Recently Added Books"
msgstr "" msgstr ""
#: cps/web.py:1265 #: cps/web.py:1325
msgid "Newest Books" msgid "Newest Books"
msgstr "" msgstr ""
#: cps/web.py:1277 #: cps/web.py:1337
msgid "Oldest Books" msgid "Oldest Books"
msgstr "" msgstr ""
#: cps/web.py:1289 #: cps/web.py:1349
msgid "Books (A-Z)" msgid "Books (A-Z)"
msgstr "" msgstr ""
#: cps/web.py:1300 #: cps/web.py:1360
msgid "Books (Z-A)" msgid "Books (Z-A)"
msgstr "" msgstr ""
#: cps/web.py:1329 #: cps/web.py:1389
msgid "Hot Books (most downloaded)" msgid "Hot Books (most downloaded)"
msgstr "" msgstr ""
#: cps/web.py:1342 #: cps/web.py:1402
msgid "Best rated books" msgid "Best rated books"
msgstr "" msgstr ""
#: cps/templates/index.xml:36 cps/web.py:1354 #: cps/templates/index.xml:36 cps/web.py:1415
msgid "Random Books" msgid "Random Books"
msgstr "" msgstr ""
#: cps/web.py:1369 #: cps/web.py:1430
msgid "Author list" msgid "Author list"
msgstr "" msgstr ""
#: cps/web.py:1381 cps/web.py:1444 cps/web.py:1599 cps/web.py:2157 #: cps/web.py:1442 cps/web.py:1533 cps/web.py:1695 cps/web.py:2253
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 ""
#: cps/templates/index.xml:73 cps/web.py:1428 #: cps/web.py:1470
msgid "Publisher list"
msgstr ""
#: cps/web.py:1484
#, python-format
msgid "Publisher: %(name)s"
msgstr ""
#: cps/templates/index.xml:80 cps/web.py:1516
msgid "Series list" msgid "Series list"
msgstr "" msgstr ""
#: cps/web.py:1442 #: cps/web.py:1531
#, python-format #, python-format
msgid "Series: %(serie)s" msgid "Series: %(serie)s"
msgstr "" msgstr ""
#: cps/web.py:1469 #: cps/web.py:1560
msgid "Available languages" msgid "Available languages"
msgstr "" msgstr ""
#: cps/web.py:1486 #: cps/web.py:1580
#, python-format #, python-format
msgid "Language: %(name)s" msgid "Language: %(name)s"
msgstr "" msgstr ""
#: cps/templates/index.xml:66 cps/web.py:1497 #: cps/templates/index.xml:73 cps/web.py:1591
msgid "Category list" msgid "Category list"
msgstr "" msgstr ""
#: cps/web.py:1511 #: cps/web.py:1605
#, python-format #, python-format
msgid "Category: %(name)s" msgid "Category: %(name)s"
msgstr "" msgstr ""
#: cps/templates/layout.html:71 cps/web.py:1650 #: cps/templates/layout.html:71 cps/web.py:1746
msgid "Tasks" msgid "Tasks"
msgstr "" msgstr ""
#: cps/web.py:1684 #: cps/web.py:1780
msgid "Statistics" msgid "Statistics"
msgstr "" msgstr ""
#: cps/web.py:1791 #: cps/web.py:1887
msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgid "Callback domain is not verified, please follow steps to verify domain in google developer console"
msgstr "" msgstr ""
#: cps/web.py:1866 #: cps/web.py:1962
msgid "Server restarted, please reload page" msgid "Server restarted, please reload page"
msgstr "" msgstr ""
#: cps/web.py:1869 #: cps/web.py:1965
msgid "Performing shutdown of server, please close window" msgid "Performing shutdown of server, please close window"
msgstr "" msgstr ""
#: cps/web.py:1888 #: cps/web.py:1984
msgid "Update done" msgid "Update done"
msgstr "" msgstr ""
#: cps/web.py:1958 #: cps/web.py:2054
msgid "Published after " msgid "Published after "
msgstr "" msgstr ""
#: cps/web.py:1965 #: cps/web.py:2061
msgid "Published before " msgid "Published before "
msgstr "" msgstr ""
#: cps/web.py:1979 #: cps/web.py:2075
#, python-format #, python-format
msgid "Rating <= %(rating)s" msgid "Rating <= %(rating)s"
msgstr "" msgstr ""
#: cps/web.py:1981 #: cps/web.py:2077
#, python-format #, python-format
msgid "Rating >= %(rating)s" msgid "Rating >= %(rating)s"
msgstr "" msgstr ""
#: cps/web.py:2040 cps/web.py:2049 #: cps/web.py:2136 cps/web.py:2145
msgid "search" msgid "search"
msgstr "" msgstr ""
#: cps/templates/index.xml:44 cps/templates/index.xml:48 #: cps/templates/index.xml:44 cps/templates/index.xml:48
#: cps/templates/layout.html:146 cps/web.py:2116 #: cps/templates/layout.html:146 cps/web.py:2212
msgid "Read Books" msgid "Read Books"
msgstr "" msgstr ""
#: cps/templates/index.xml:52 cps/templates/index.xml:56 #: cps/templates/index.xml:52 cps/templates/index.xml:56
#: cps/templates/layout.html:148 cps/web.py:2119 #: cps/templates/layout.html:148 cps/web.py:2215
msgid "Unread Books" msgid "Unread Books"
msgstr "" msgstr ""
#: cps/web.py:2167 cps/web.py:2169 cps/web.py:2171 cps/web.py:2183 #: cps/web.py:2263 cps/web.py:2265 cps/web.py:2267 cps/web.py:2279
msgid "Read a Book" msgid "Read a Book"
msgstr "" msgstr ""
#: cps/web.py:2249 cps/web.py:3146 #: cps/web.py:2345 cps/web.py:3248
msgid "Please fill out all fields!" msgid "Please fill out all fields!"
msgstr "" msgstr ""
#: cps/web.py:2250 cps/web.py:2271 cps/web.py:2275 cps/web.py:2280 #: cps/web.py:2346 cps/web.py:2367 cps/web.py:2371 cps/web.py:2376
#: cps/web.py:2282 #: cps/web.py:2378
msgid "register" msgid "register"
msgstr "" msgstr ""
#: cps/web.py:2270 cps/web.py:3362 #: cps/web.py:2366 cps/web.py:3464
msgid "An unknown error occurred. Please try again later." msgid "An unknown error occurred. Please try again later."
msgstr "" msgstr ""
#: cps/web.py:2273 #: cps/web.py:2369
msgid "Your e-mail is not allowed to register" msgid "Your e-mail is not allowed to register"
msgstr "" msgstr ""
#: cps/web.py:2276 #: cps/web.py:2372
msgid "Confirmation e-mail was send to your e-mail account." msgid "Confirmation e-mail was send to your e-mail account."
msgstr "" msgstr ""
#: cps/web.py:2279 #: cps/web.py:2375
msgid "This username or e-mail address is already in use." msgid "This username or e-mail address is already in use."
msgstr "" msgstr ""
#: cps/web.py:2296 cps/web.py:2392 #: cps/web.py:2392 cps/web.py:2488
#, 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:2301 #: cps/web.py:2397
msgid "Wrong Username or Password" msgid "Wrong Username or Password"
msgstr "" msgstr ""
#: cps/web.py:2307 cps/web.py:2328 #: cps/web.py:2403 cps/web.py:2424
msgid "login" msgid "login"
msgstr "" msgstr ""
#: cps/web.py:2340 cps/web.py:2371 #: cps/web.py:2436 cps/web.py:2467
msgid "Token not found" msgid "Token not found"
msgstr "" msgstr ""
#: cps/web.py:2348 cps/web.py:2379 #: cps/web.py:2444 cps/web.py:2475
msgid "Token has expired" msgid "Token has expired"
msgstr "" msgstr ""
#: cps/web.py:2356 #: cps/web.py:2452
msgid "Success! Please return to your device" msgid "Success! Please return to your device"
msgstr "" msgstr ""
#: cps/web.py:2406 #: cps/web.py:2502
msgid "Please configure the SMTP mail settings first..." msgid "Please configure the SMTP mail settings first..."
msgstr "" msgstr ""
#: cps/web.py:2410 #: cps/web.py:2506
#, python-format #, python-format
msgid "Book successfully queued for sending to %(kindlemail)s" msgid "Book successfully queued for sending to %(kindlemail)s"
msgstr "" msgstr ""
#: cps/web.py:2414 #: cps/web.py:2510
#, 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:2416 cps/web.py:3200 #: cps/web.py:2512 cps/web.py:3302
msgid "Please configure your kindle e-mail address first..." msgid "Please configure your kindle e-mail address first..."
msgstr "" msgstr ""
#: cps/web.py:2427 cps/web.py:2479 #: cps/web.py:2523 cps/web.py:2575
msgid "Invalid shelf specified" msgid "Invalid shelf specified"
msgstr "" msgstr ""
#: cps/web.py:2434 #: cps/web.py:2530
#, python-format #, python-format
msgid "Sorry you are not allowed to add a book to the the shelf: %(shelfname)s" msgid "Sorry you are not allowed to add a book to the the shelf: %(shelfname)s"
msgstr "" msgstr ""
#: cps/web.py:2442 #: cps/web.py:2538
msgid "You are not allowed to edit public shelves" msgid "You are not allowed to edit public shelves"
msgstr "" msgstr ""
#: cps/web.py:2451 #: cps/web.py:2547
#, python-format #, python-format
msgid "Book is already part of the shelf: %(shelfname)s" msgid "Book is already part of the shelf: %(shelfname)s"
msgstr "" msgstr ""
#: cps/web.py:2465 #: cps/web.py:2561
#, 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:2484 #: cps/web.py:2580
#, python-format #, python-format
msgid "You are not allowed to add a book to the the shelf: %(name)s" msgid "You are not allowed to add a book to the the shelf: %(name)s"
msgstr "" msgstr ""
#: cps/web.py:2489 #: cps/web.py:2585
msgid "User is not allowed to edit public shelves" msgid "User is not allowed to edit public shelves"
msgstr "" msgstr ""
#: cps/web.py:2507 #: cps/web.py:2603
#, python-format #, python-format
msgid "Books are already part of the shelf: %(name)s" msgid "Books are already part of the shelf: %(name)s"
msgstr "" msgstr ""
#: cps/web.py:2521 #: cps/web.py:2617
#, python-format #, python-format
msgid "Books have been added to shelf: %(sname)s" msgid "Books have been added to shelf: %(sname)s"
msgstr "" msgstr ""
#: cps/web.py:2523 #: cps/web.py:2619
#, python-format #, python-format
msgid "Could not add books to shelf: %(sname)s" msgid "Could not add books to shelf: %(sname)s"
msgstr "" msgstr ""
#: cps/web.py:2560 #: cps/web.py:2656
#, 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:2566 #: cps/web.py:2662
#, python-format #, python-format
msgid "Sorry you are not allowed to remove a book from this shelf: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf: %(sname)s"
msgstr "" msgstr ""
#: cps/web.py:2586 cps/web.py:2610 #: cps/web.py:2682 cps/web.py:2706
#, 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:2591 #: cps/web.py:2687
#, python-format #, python-format
msgid "Shelf %(title)s created" msgid "Shelf %(title)s created"
msgstr "" msgstr ""
#: cps/web.py:2593 cps/web.py:2621 #: cps/web.py:2689 cps/web.py:2717
msgid "There was an error" msgid "There was an error"
msgstr "" msgstr ""
#: cps/web.py:2594 cps/web.py:2596 #: cps/web.py:2690 cps/web.py:2692
msgid "create a shelf" msgid "create a shelf"
msgstr "" msgstr ""
#: cps/web.py:2619 #: cps/web.py:2715
#, python-format #, python-format
msgid "Shelf %(title)s changed" msgid "Shelf %(title)s changed"
msgstr "" msgstr ""
#: cps/web.py:2622 cps/web.py:2624 #: cps/web.py:2718 cps/web.py:2720
msgid "Edit a shelf" msgid "Edit a shelf"
msgstr "" msgstr ""
#: cps/web.py:2645 #: cps/web.py:2741
#, python-format #, python-format
msgid "successfully deleted shelf %(name)s" msgid "successfully deleted shelf %(name)s"
msgstr "" msgstr ""
#: cps/web.py:2672 #: cps/web.py:2768
#, python-format #, python-format
msgid "Shelf: '%(name)s'" msgid "Shelf: '%(name)s'"
msgstr "" msgstr ""
#: cps/web.py:2675 #: cps/web.py:2771
msgid "Error opening shelf. Shelf does not exist or is not accessible" msgid "Error opening shelf. Shelf does not exist or is not accessible"
msgstr "" msgstr ""
#: cps/web.py:2706 #: cps/web.py:2802
#, python-format #, python-format
msgid "Change order of Shelf: '%(name)s'" msgid "Change order of Shelf: '%(name)s'"
msgstr "" msgstr ""
#: cps/web.py:2735 cps/web.py:3152 #: cps/web.py:2831 cps/web.py:3254
msgid "E-mail is not from valid domain" msgid "E-mail is not from valid domain"
msgstr "" msgstr ""
#: cps/web.py:2737 cps/web.py:2778 cps/web.py:2781 #: cps/web.py:2833 cps/web.py:2876 cps/web.py:2879
#, python-format #, python-format
msgid "%(name)s's profile" msgid "%(name)s's profile"
msgstr "" msgstr ""
#: cps/web.py:2776 #: cps/web.py:2874
msgid "Found an existing account for this e-mail address." msgid "Found an existing account for this e-mail address."
msgstr "" msgstr ""
#: cps/web.py:2779 #: cps/web.py:2877
msgid "Profile updated" msgid "Profile updated"
msgstr "" msgstr ""
#: cps/web.py:2807 #: cps/web.py:2905
msgid "Admin page" msgid "Admin page"
msgstr "" msgstr ""
#: cps/web.py:2885 cps/web.py:3059 #: cps/web.py:2985 cps/web.py:3159
msgid "Calibre-Web configuration updated" msgid "Calibre-Web configuration updated"
msgstr "" msgstr ""
#: cps/templates/admin.html:100 cps/web.py:2898 #: cps/templates/admin.html:100 cps/web.py:2998
msgid "UI Configuration" msgid "UI Configuration"
msgstr "" msgstr ""
#: cps/web.py:2916 #: cps/web.py:3016
msgid "Import of optional Google Drive requirements missing" msgid "Import of optional Google Drive requirements missing"
msgstr "" msgstr ""
#: cps/web.py:2919 #: cps/web.py:3019
msgid "client_secrets.json is missing or not readable" msgid "client_secrets.json is missing or not readable"
msgstr "" msgstr ""
#: cps/web.py:2924 cps/web.py:2951 #: cps/web.py:3024 cps/web.py:3051
msgid "client_secrets.json is not configured for web application" msgid "client_secrets.json is not configured for web application"
msgstr "" msgstr ""
#: cps/templates/admin.html:99 cps/web.py:2954 cps/web.py:2980 cps/web.py:2992 #: cps/templates/admin.html:99 cps/web.py:3054 cps/web.py:3080 cps/web.py:3092
#: cps/web.py:3035 cps/web.py:3050 cps/web.py:3067 cps/web.py:3074 #: cps/web.py:3135 cps/web.py:3150 cps/web.py:3167 cps/web.py:3174
#: cps/web.py:3089 #: cps/web.py:3189
msgid "Basic Configuration" msgid "Basic Configuration"
msgstr "" msgstr ""
#: cps/web.py:2977 #: cps/web.py:3077
msgid "Keyfile location is not valid, please enter correct path" msgid "Keyfile location is not valid, please enter correct path"
msgstr "" msgstr ""
#: cps/web.py:2989 #: cps/web.py:3089
msgid "Certfile location is not valid, please enter correct path" msgid "Certfile location is not valid, please enter correct path"
msgstr "" msgstr ""
#: cps/web.py:3032 #: cps/web.py:3132
msgid "Logfile location is not valid, please enter correct path" msgid "Logfile location is not valid, please enter correct path"
msgstr "" msgstr ""
#: cps/web.py:3071 #: cps/web.py:3171
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:33 cps/web.py:3148 cps/web.py:3154 cps/web.py:3170 #: cps/templates/admin.html:33 cps/web.py:3250 cps/web.py:3256 cps/web.py:3272
msgid "Add new user" msgid "Add new user"
msgstr "" msgstr ""
#: cps/web.py:3160 #: cps/web.py:3262
#, python-format #, python-format
msgid "User '%(user)s' created" msgid "User '%(user)s' created"
msgstr "" msgstr ""
#: cps/web.py:3164 #: cps/web.py:3266
msgid "Found an existing account for this e-mail address or nickname." msgid "Found an existing account for this e-mail address or nickname."
msgstr "" msgstr ""
#: cps/web.py:3188 cps/web.py:3202 #: cps/web.py:3290 cps/web.py:3304
msgid "E-mail server settings updated" msgid "E-mail server settings updated"
msgstr "" msgstr ""
#: cps/web.py:3195 #: cps/web.py:3297
#, 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:3198 #: cps/web.py:3300
#, 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:3203 #: cps/web.py:3305
msgid "Edit e-mail server settings" msgid "Edit e-mail server settings"
msgstr "" msgstr ""
#: cps/web.py:3228 #: cps/web.py:3330
#, python-format #, python-format
msgid "User '%(nick)s' deleted" msgid "User '%(nick)s' deleted"
msgstr "" msgstr ""
#: cps/web.py:3337 #: cps/web.py:3439
#, python-format #, python-format
msgid "User '%(nick)s' updated" msgid "User '%(nick)s' updated"
msgstr "" msgstr ""
#: cps/web.py:3340 #: cps/web.py:3442
msgid "An unknown error occured." msgid "An unknown error occured."
msgstr "" msgstr ""
#: cps/web.py:3342 #: cps/web.py:3444
#, python-format #, python-format
msgid "Edit User %(nick)s" msgid "Edit User %(nick)s"
msgstr "" msgstr ""
#: cps/web.py:3359 #: cps/web.py:3461
#, python-format #, python-format
msgid "Password for user %(user)s reset" msgid "Password for user %(user)s reset"
msgstr "" msgstr ""
#: cps/web.py:3373 cps/web.py:3574 #: cps/web.py:3475 cps/web.py:3676
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 ""
#: cps/web.py:3398 cps/web.py:3854 #: cps/web.py:3500 cps/web.py:3959
msgid "edit metadata" msgid "edit metadata"
msgstr "" msgstr ""
#: cps/web.py:3491 cps/web.py:3724 #: cps/web.py:3593 cps/web.py:3829
#, python-format #, python-format
msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgid "File extension '%(ext)s' is not allowed to be uploaded to this server"
msgstr "" msgstr ""
#: cps/web.py:3495 cps/web.py:3728 #: cps/web.py:3597 cps/web.py:3833
msgid "File to be uploaded must have an extension" msgid "File to be uploaded must have an extension"
msgstr "" msgstr ""
#: cps/web.py:3507 cps/web.py:3748 #: cps/web.py:3609 cps/web.py:3853
#, python-format #, python-format
msgid "Failed to create path %(path)s (Permission denied)." msgid "Failed to create path %(path)s (Permission denied)."
msgstr "" msgstr ""
#: cps/web.py:3512 #: cps/web.py:3614
#, python-format #, python-format
msgid "Failed to store file %(file)s." msgid "Failed to store file %(file)s."
msgstr "" msgstr ""
#: cps/web.py:3528 #: cps/web.py:3630
#, python-format #, python-format
msgid "File format %(ext)s added to %(book)s" msgid "File format %(ext)s added to %(book)s"
msgstr "" msgstr ""
#: cps/web.py:3546 #: cps/web.py:3648
#, python-format #, python-format
msgid "Failed to create path for cover %(path)s (Permission denied)." msgid "Failed to create path for cover %(path)s (Permission denied)."
msgstr "" msgstr ""
#: cps/web.py:3553 #: cps/web.py:3655
#, python-format #, python-format
msgid "Failed to store cover-file %(cover)s." msgid "Failed to store cover-file %(cover)s."
msgstr "" msgstr ""
#: cps/web.py:3556 #: cps/web.py:3658
msgid "Cover-file is not a valid image file" msgid "Cover-file is not a valid image file"
msgstr "" msgstr ""
#: cps/web.py:3586 cps/web.py:3595 cps/web.py:3599 #: cps/web.py:3688 cps/web.py:3697 cps/web.py:3701
msgid "unknown" msgid "unknown"
msgstr "" msgstr ""
#: cps/web.py:3618 #: cps/web.py:3720
msgid "Cover is not a jpg file, can't save" msgid "Cover is not a jpg file, can't save"
msgstr "" msgstr ""
#: cps/web.py:3663 #: cps/web.py:3768
#, python-format #, python-format
msgid "%(langname)s is not a valid language" msgid "%(langname)s is not a valid language"
msgstr "" msgstr ""
#: cps/web.py:3694 #: cps/web.py:3799
msgid "Metadata successfully updated" msgid "Metadata successfully updated"
msgstr "" msgstr ""
#: cps/web.py:3703 #: cps/web.py:3808
msgid "Error editing book, please check logfile for details" msgid "Error editing book, please check logfile for details"
msgstr "" msgstr ""
#: cps/web.py:3753 #: cps/web.py:3858
#, python-format #, python-format
msgid "Failed to store file %(file)s (Permission denied)." msgid "Failed to store file %(file)s (Permission denied)."
msgstr "" msgstr ""
#: cps/web.py:3758 #: cps/web.py:3863
#, python-format #, python-format
msgid "Failed to delete file %(file)s (Permission denied)." msgid "Failed to delete file %(file)s (Permission denied)."
msgstr "" msgstr ""
#: cps/web.py:3840 #: cps/web.py:3945
#, python-format #, python-format
msgid "File %(file)s uploaded" msgid "File %(file)s uploaded"
msgstr "" msgstr ""
#: cps/web.py:3870 #: cps/web.py:3975
msgid "Source or destination format for conversion missing" msgid "Source or destination format for conversion missing"
msgstr "" msgstr ""
#: cps/web.py:3880 #: cps/web.py:3985
#, python-format #, python-format
msgid "Book successfully queued for converting to %(book_format)s" msgid "Book successfully queued for converting to %(book_format)s"
msgstr "" msgstr ""
#: cps/web.py:3884 #: cps/web.py:3989
#, python-format #, python-format
msgid "There was an error converting this book: %(res)s" msgid "There was an error converting this book: %(res)s"
msgstr "" msgstr ""
@ -880,10 +889,10 @@ msgstr ""
#: cps/templates/admin.html:151 cps/templates/admin.html:165 #: cps/templates/admin.html:151 cps/templates/admin.html:165
#: cps/templates/book_edit.html:178 cps/templates/book_edit.html:200 #: cps/templates/book_edit.html:178 cps/templates/book_edit.html:200
#: cps/templates/config_edit.html:212 cps/templates/config_view_edit.html:164 #: cps/templates/config_edit.html:212 cps/templates/config_view_edit.html:168
#: cps/templates/email_edit.html:40 cps/templates/email_edit.html:75 #: cps/templates/email_edit.html:40 cps/templates/email_edit.html:75
#: cps/templates/shelf.html:62 cps/templates/shelf_edit.html:19 #: cps/templates/shelf.html:62 cps/templates/shelf_edit.html:19
#: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:151 #: cps/templates/shelf_order.html:12 cps/templates/user_edit.html:155
msgid "Back" msgid "Back"
msgstr "" msgstr ""
@ -979,12 +988,12 @@ msgstr ""
msgid "Upload Cover from local drive" msgid "Upload Cover from local drive"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:96 cps/templates/detail.html:131 #: cps/templates/book_edit.html:96 cps/templates/detail.html:135
msgid "Publishing date" msgid "Publishing date"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:103 cps/templates/book_edit.html:261 #: cps/templates/book_edit.html:103 cps/templates/book_edit.html:261
#: cps/templates/book_edit.html:278 cps/templates/detail.html:126 #: cps/templates/book_edit.html:278 cps/templates/detail.html:127
#: cps/templates/search_form.html:14 #: cps/templates/search_form.html:14
msgid "Publisher" msgid "Publisher"
msgstr "" msgstr ""
@ -1014,9 +1023,9 @@ msgid "Get metadata"
msgstr "" msgstr ""
#: cps/templates/book_edit.html:177 cps/templates/config_edit.html:210 #: cps/templates/book_edit.html:177 cps/templates/config_edit.html:210
#: cps/templates/config_view_edit.html:163 cps/templates/login.html:20 #: cps/templates/config_view_edit.html:167 cps/templates/login.html:20
#: cps/templates/search_form.html:153 cps/templates/shelf_edit.html:17 #: cps/templates/search_form.html:153 cps/templates/shelf_edit.html:17
#: cps/templates/user_edit.html:149 #: cps/templates/user_edit.html:153
msgid "Submit" msgid "Submit"
msgstr "" msgstr ""
@ -1052,7 +1061,7 @@ msgstr ""
msgid "Loading..." msgid "Loading..."
msgstr "" msgstr ""
#: cps/templates/book_edit.html:239 cps/templates/layout.html:221 #: cps/templates/book_edit.html:239 cps/templates/layout.html:224
msgid "Close" msgid "Close"
msgstr "" msgstr ""
@ -1234,31 +1243,31 @@ msgstr ""
msgid "Default settings for new users" msgid "Default settings for new users"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:70 cps/templates/user_edit.html:106 #: cps/templates/config_view_edit.html:70 cps/templates/user_edit.html:110
msgid "Admin user" msgid "Admin user"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:74 cps/templates/user_edit.html:115 #: cps/templates/config_view_edit.html:74 cps/templates/user_edit.html:119
msgid "Allow Downloads" msgid "Allow Downloads"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:78 cps/templates/user_edit.html:119 #: cps/templates/config_view_edit.html:78 cps/templates/user_edit.html:123
msgid "Allow Uploads" msgid "Allow Uploads"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:82 cps/templates/user_edit.html:123 #: cps/templates/config_view_edit.html:82 cps/templates/user_edit.html:127
msgid "Allow Edit" msgid "Allow Edit"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:86 cps/templates/user_edit.html:127 #: cps/templates/config_view_edit.html:86 cps/templates/user_edit.html:131
msgid "Allow Delete books" msgid "Allow Delete books"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:90 cps/templates/user_edit.html:132 #: cps/templates/config_view_edit.html:90 cps/templates/user_edit.html:136
msgid "Allow Changing Password" msgid "Allow Changing Password"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:94 cps/templates/user_edit.html:136 #: cps/templates/config_view_edit.html:94 cps/templates/user_edit.html:140
msgid "Allow Editing Public Shelfs" msgid "Allow Editing Public Shelfs"
msgstr "" msgstr ""
@ -1303,14 +1312,18 @@ msgid "Show author selection"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:148 cps/templates/user_edit.html:94 #: cps/templates/config_view_edit.html:148 cps/templates/user_edit.html:94
msgid "Show read and unread" msgid "Show publisher selection"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:152 cps/templates/user_edit.html:98 #: cps/templates/config_view_edit.html:152 cps/templates/user_edit.html:98
msgid "Show read and unread"
msgstr ""
#: cps/templates/config_view_edit.html:156 cps/templates/user_edit.html:102
msgid "Show random books in detail view" msgid "Show random books in detail view"
msgstr "" msgstr ""
#: cps/templates/config_view_edit.html:156 cps/templates/user_edit.html:111 #: cps/templates/config_view_edit.html:160 cps/templates/user_edit.html:115
msgid "Show mature content" msgid "Show mature content"
msgstr "" msgstr ""
@ -1330,19 +1343,19 @@ msgstr ""
msgid "language" msgid "language"
msgstr "" msgstr ""
#: cps/templates/detail.html:168 #: cps/templates/detail.html:172
msgid "Read" msgid "Read"
msgstr "" msgstr ""
#: cps/templates/detail.html:178 #: cps/templates/detail.html:182
msgid "Description:" msgid "Description:"
msgstr "" msgstr ""
#: cps/templates/detail.html:191 cps/templates/search.html:14 #: cps/templates/detail.html:195 cps/templates/search.html:14
msgid "Add to shelf" msgid "Add to shelf"
msgstr "" msgstr ""
#: cps/templates/detail.html:253 #: cps/templates/detail.html:257
msgid "Edit metadata" msgid "Edit metadata"
msgstr "" msgstr ""
@ -1402,7 +1415,7 @@ msgstr ""
msgid "Do you really want to delete this domain rule?" msgid "Do you really want to delete this domain rule?"
msgstr "" msgstr ""
#: cps/templates/feed.xml:21 cps/templates/layout.html:205 #: cps/templates/feed.xml:21 cps/templates/layout.html:208
msgid "Next" msgid "Next"
msgstr "" msgstr ""
@ -1455,27 +1468,35 @@ msgstr ""
msgid "Books ordered by Author" msgid "Books ordered by Author"
msgstr "" msgstr ""
#: cps/templates/index.xml:66 cps/templates/layout.html:163
msgid "Publishers"
msgstr ""
#: cps/templates/index.xml:70 #: cps/templates/index.xml:70
msgid "Books ordered by category" msgid "Books ordered by publisher"
msgstr "" msgstr ""
#: cps/templates/index.xml:77 #: cps/templates/index.xml:77
msgid "Books ordered by category"
msgstr ""
#: cps/templates/index.xml:84
msgid "Books ordered by series" msgid "Books ordered by series"
msgstr "" msgstr ""
#: cps/templates/index.xml:80 cps/templates/layout.html:166 #: cps/templates/index.xml:87 cps/templates/layout.html:169
msgid "Public Shelves" msgid "Public Shelves"
msgstr "" msgstr ""
#: cps/templates/index.xml:84 #: cps/templates/index.xml:91
msgid "Books organized in public shelfs, visible to everyone" msgid "Books organized in public shelfs, visible to everyone"
msgstr "" msgstr ""
#: cps/templates/index.xml:88 cps/templates/layout.html:170 #: cps/templates/index.xml:95 cps/templates/layout.html:173
msgid "Your Shelves" msgid "Your Shelves"
msgstr "" msgstr ""
#: cps/templates/index.xml:92 #: cps/templates/index.xml:99
msgid "User's own shelfs, only visible to the current user himself" msgid "User's own shelfs, only visible to the current user himself"
msgstr "" msgstr ""
@ -1544,23 +1565,23 @@ msgstr ""
msgid "Categories" msgid "Categories"
msgstr "" msgstr ""
#: cps/templates/layout.html:163 cps/templates/search_form.html:74 #: cps/templates/layout.html:166 cps/templates/search_form.html:74
msgid "Languages" msgid "Languages"
msgstr "" msgstr ""
#: cps/templates/layout.html:175 #: cps/templates/layout.html:178
msgid "Create a Shelf" msgid "Create a Shelf"
msgstr "" msgstr ""
#: cps/templates/layout.html:176 cps/templates/stats.html:3 #: cps/templates/layout.html:179 cps/templates/stats.html:3
msgid "About" msgid "About"
msgstr "" msgstr ""
#: cps/templates/layout.html:190 #: cps/templates/layout.html:193
msgid "Previous" msgid "Previous"
msgstr "" msgstr ""
#: cps/templates/layout.html:217 #: cps/templates/layout.html:220
msgid "Book Details" msgid "Book Details"
msgstr "" msgstr ""
@ -1879,11 +1900,11 @@ msgstr ""
msgid "Show all" msgid "Show all"
msgstr "" msgstr ""
#: cps/templates/user_edit.html:143 #: cps/templates/user_edit.html:147
msgid "Delete this user" msgid "Delete this user"
msgstr "" msgstr ""
#: cps/templates/user_edit.html:158 #: cps/templates/user_edit.html:162
msgid "Recent Downloads" msgid "Recent Downloads"
msgstr "" msgstr ""

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save