mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 23:33:01 +00:00 
			
		
		
		
	Further migration to flask_babel
Bugfix sort order Bugfix tasklist
This commit is contained in:
		| @@ -200,7 +200,7 @@ def admin(): | |||||||
|                     form_date -= timedelta(hours=int(commit[20:22]), minutes=int(commit[23:])) |                     form_date -= timedelta(hours=int(commit[20:22]), minutes=int(commit[23:])) | ||||||
|                 elif commit[19] == '-': |                 elif commit[19] == '-': | ||||||
|                     form_date += timedelta(hours=int(commit[20:22]), minutes=int(commit[23:])) |                     form_date += timedelta(hours=int(commit[20:22]), minutes=int(commit[23:])) | ||||||
|             commit = format_datetime(form_date - tz, format='short', locale=locale) |             commit = format_datetime(form_date - tz, format='short') | ||||||
|         else: |         else: | ||||||
|             commit = version['version'] |             commit = version['version'] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| from babel import Locale |  | ||||||
| from babel import negotiate_locale | from babel import negotiate_locale | ||||||
| from flask_babel import Babel | from flask_babel import Babel, Locale | ||||||
| from babel.core import UnknownLocaleError | from babel.core import UnknownLocaleError | ||||||
| from flask import request, g | from flask import request, g | ||||||
|  |  | ||||||
|   | |||||||
| @@ -919,7 +919,7 @@ class CalibreDB: | |||||||
|                                  .count()) |                                  .count()) | ||||||
|                 if no_lang_count: |                 if no_lang_count: | ||||||
|                     tags.append([Category(_("None"), "none"), no_lang_count]) |                     tags.append([Category(_("None"), "none"), no_lang_count]) | ||||||
|             return sorted(tags, key=lambda x: x[0].name, reverse=reverse_order) |             return sorted(tags, key=lambda x: x[0].name.lower(), reverse=reverse_order) | ||||||
|         else: |         else: | ||||||
|             if not languages: |             if not languages: | ||||||
|                 languages = self.session.query(Languages) \ |                 languages = self.session.query(Languages) \ | ||||||
|   | |||||||
| @@ -22,15 +22,16 @@ | |||||||
|  |  | ||||||
| # custom jinja filters | # custom jinja filters | ||||||
|  |  | ||||||
|  | from markupsafe import escape | ||||||
| import datetime | import datetime | ||||||
| import mimetypes | import mimetypes | ||||||
| from uuid import uuid4 | from uuid import uuid4 | ||||||
|  |  | ||||||
| from babel.dates import format_date | # from babel.dates import format_date | ||||||
| from flask import Blueprint, request, url_for | from flask import Blueprint, request, url_for | ||||||
| from flask_babel import get_locale | from flask_babel import format_date | ||||||
| from flask_login import current_user | from flask_login import current_user | ||||||
| from markupsafe import escape |  | ||||||
| from . import constants, logger | from . import constants, logger | ||||||
|  |  | ||||||
| jinjia = Blueprint('jinjia', __name__) | jinjia = Blueprint('jinjia', __name__) | ||||||
| @@ -76,7 +77,7 @@ def mimetype_filter(val): | |||||||
| @jinjia.app_template_filter('formatdate') | @jinjia.app_template_filter('formatdate') | ||||||
| def formatdate_filter(val): | def formatdate_filter(val): | ||||||
|     try: |     try: | ||||||
|         return format_date(val, format='medium', locale=get_locale()) |         return format_date(val, format='medium') | ||||||
|     except AttributeError as e: |     except AttributeError as e: | ||||||
|         log.error('Babel error: %s, Current user locale: %s, Current User: %s', e, |         log.error('Babel error: %s, Current user locale: %s, Current User: %s', e, | ||||||
|                   current_user.locale, |                   current_user.locale, | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ from datetime import datetime | |||||||
| from flask import Blueprint, request, redirect, url_for, flash | from flask import Blueprint, request, redirect, url_for, flash | ||||||
| from flask import session as flask_session | from flask import session as flask_session | ||||||
| from flask_login import current_user | from flask_login import current_user | ||||||
| from flask_babel import get_locale, format_date | from flask_babel import format_date | ||||||
| from flask_babel import gettext as _ | from flask_babel import gettext as _ | ||||||
| from sqlalchemy.sql.expression import func, not_, and_, or_, text | from sqlalchemy.sql.expression import func, not_, and_, or_, text | ||||||
| from sqlalchemy.sql.functions import coalesce | from sqlalchemy.sql.functions import coalesce | ||||||
| @@ -193,14 +193,14 @@ def extend_search_term(searchterm, | |||||||
|         try: |         try: | ||||||
|             searchterm.extend([_(u"Published after ") + |             searchterm.extend([_(u"Published after ") + | ||||||
|                                format_date(datetime.strptime(pub_start, "%Y-%m-%d"), |                                format_date(datetime.strptime(pub_start, "%Y-%m-%d"), | ||||||
|                                            format='medium', locale=get_locale())]) |                                            format='medium')]) | ||||||
|         except ValueError: |         except ValueError: | ||||||
|             pub_start = u"" |             pub_start = u"" | ||||||
|     if pub_end: |     if pub_end: | ||||||
|         try: |         try: | ||||||
|             searchterm.extend([_(u"Published before ") + |             searchterm.extend([_(u"Published before ") + | ||||||
|                                format_date(datetime.strptime(pub_end, "%Y-%m-%d"), |                                format_date(datetime.strptime(pub_end, "%Y-%m-%d"), | ||||||
|                                            format='medium', locale=get_locale())]) |                                            format='medium')]) | ||||||
|         except ValueError: |         except ValueError: | ||||||
|             pub_end = u"" |             pub_end = u"" | ||||||
|     elements = {'tag': db.Tags, 'serie':db.Series, 'shelf':ub.Shelf} |     elements = {'tag': db.Tags, 'serie':db.Series, 'shelf':ub.Shelf} | ||||||
| @@ -291,22 +291,19 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): | |||||||
|             if column_start: |             if column_start: | ||||||
|                 search_term.extend([u"{} >= {}".format(c.name, |                 search_term.extend([u"{} >= {}".format(c.name, | ||||||
|                                                        format_date(datetime.strptime(column_start, "%Y-%m-%d").date(), |                                                        format_date(datetime.strptime(column_start, "%Y-%m-%d").date(), | ||||||
|                                                                    format='medium', |                                                                    format='medium') | ||||||
|                                                                    locale=get_locale()) |  | ||||||
|                                                        )]) |                                                        )]) | ||||||
|                 cc_present = True |                 cc_present = True | ||||||
|             if column_end: |             if column_end: | ||||||
|                 search_term.extend([u"{} <= {}".format(c.name, |                 search_term.extend([u"{} <= {}".format(c.name, | ||||||
|                                                        format_date(datetime.strptime(column_end, "%Y-%m-%d").date(), |                                                        format_date(datetime.strptime(column_end, "%Y-%m-%d").date(), | ||||||
|                                                                    format='medium', |                                                                    format='medium') | ||||||
|                                                                    locale=get_locale()) |  | ||||||
|                                                        )]) |                                                        )]) | ||||||
|                 cc_present = True |                 cc_present = True | ||||||
|         elif term.get('custom_column_' + str(c.id)): |         elif term.get('custom_column_' + str(c.id)): | ||||||
|             search_term.extend([(u"{}: {}".format(c.name, term.get('custom_column_' + str(c.id))))]) |             search_term.extend([(u"{}: {}".format(c.name, term.get('custom_column_' + str(c.id))))]) | ||||||
|             cc_present = True |             cc_present = True | ||||||
|  |  | ||||||
|  |  | ||||||
|     if any(tags.values()) or author_name or book_title or publisher or pub_start or pub_end or rating_low \ |     if any(tags.values()) or author_name or book_title or publisher or pub_start or pub_end or rating_low \ | ||||||
|        or rating_high or description or cc_present or read_status: |        or rating_high or description or cc_present or read_status: | ||||||
|         search_term, pub_start, pub_end = extend_search_term(search_term, |         search_term, pub_start, pub_end = extend_search_term(search_term, | ||||||
|   | |||||||
| @@ -22,7 +22,6 @@ import inspect | |||||||
| import json | import json | ||||||
| import os | import os | ||||||
| import sys | import sys | ||||||
| from dataclasses import asdict |  | ||||||
|  |  | ||||||
| from flask import Blueprint, Response, request, url_for | from flask import Blueprint, Response, request, url_for | ||||||
| from flask_login import current_user | from flask_login import current_user | ||||||
| @@ -57,9 +56,10 @@ for f in modules: | |||||||
|         try: |         try: | ||||||
|             importlib.import_module("cps.metadata_provider." + a) |             importlib.import_module("cps.metadata_provider." + a) | ||||||
|             new_list.append(a) |             new_list.append(a) | ||||||
|         except (ImportError, IndentationError, SyntaxError) as e: |         except (IndentationError, SyntaxError) as e: | ||||||
|             log.error("Import error for metadata source: {} - {}".format(a, e)) |             log.error("Syntax error for metadata source: {} - {}".format(a, e)) | ||||||
|             pass |         except ImportError as e: | ||||||
|  |             log.debug("Import error for metadata source: {} - {}".format(a, e)) | ||||||
|  |  | ||||||
|  |  | ||||||
| def list_classes(provider_list): | def list_classes(provider_list): | ||||||
|   | |||||||
| @@ -19,12 +19,13 @@ from markupsafe import escape | |||||||
| from flask import Blueprint, jsonify | from flask import Blueprint, jsonify | ||||||
| from flask_login import login_required, current_user | from flask_login import login_required, current_user | ||||||
| from flask_babel import gettext as _ | from flask_babel import gettext as _ | ||||||
| from flask_babel import get_locale, format_datetime | from flask_babel import format_datetime | ||||||
| from babel.units import format_unit | from babel.units import format_unit | ||||||
|  |  | ||||||
| from . import logger | from . import logger | ||||||
| from .render_template import render_title_template | from .render_template import render_title_template | ||||||
| from .services.worker import WorkerThread, STAT_WAITING, STAT_FAIL, STAT_STARTED, STAT_FINISH_SUCCESS | from .services.worker import WorkerThread, STAT_WAITING, STAT_FAIL, STAT_STARTED, STAT_FINISH_SUCCESS, STAT_ENDED, \ | ||||||
|  |     STAT_CANCELLED | ||||||
|  |  | ||||||
| tasks = Blueprint('tasks', __name__) | tasks = Blueprint('tasks', __name__) | ||||||
|  |  | ||||||
| @@ -50,11 +51,11 @@ def get_tasks_status(): | |||||||
| # helper function to apply localize status information in tasklist entries | # helper function to apply localize status information in tasklist entries | ||||||
| def render_task_status(tasklist): | def render_task_status(tasklist): | ||||||
|     rendered_tasklist = list() |     rendered_tasklist = list() | ||||||
|     for __, user, __, task in tasklist: |     for __, user, __, task, __ in tasklist: | ||||||
|         if user == current_user.name or current_user.role_admin(): |         if user == current_user.name or current_user.role_admin(): | ||||||
|             ret = {} |             ret = {} | ||||||
|             if task.start_time: |             if task.start_time: | ||||||
|                 ret['starttime'] = format_datetime(task.start_time, format='short', locale=get_locale()) |                 ret['starttime'] = format_datetime(task.start_time, format='short') | ||||||
|                 ret['runtime'] = format_runtime(task.runtime) |                 ret['runtime'] = format_runtime(task.runtime) | ||||||
|  |  | ||||||
|             # localize the task status |             # localize the task status | ||||||
| @@ -67,12 +68,22 @@ def render_task_status(tasklist): | |||||||
|                     ret['status'] = _(u'Started') |                     ret['status'] = _(u'Started') | ||||||
|                 elif task.stat == STAT_FINISH_SUCCESS: |                 elif task.stat == STAT_FINISH_SUCCESS: | ||||||
|                     ret['status'] = _(u'Finished') |                     ret['status'] = _(u'Finished') | ||||||
|  |                 elif task.stat == STAT_ENDED: | ||||||
|  |                     ret['status'] = _(u'Ended') | ||||||
|  |                 elif task.stat == STAT_CANCELLED: | ||||||
|  |                     ret['status'] = _(u'Cancelled') | ||||||
|                 else: |                 else: | ||||||
|                     ret['status'] = _(u'Unknown Status') |                     ret['status'] = _(u'Unknown Status') | ||||||
|  |  | ||||||
|             ret['taskMessage'] = "{}: {}".format(_(task.name), task.message) |             ret['taskMessage'] = "{}: {}".format(task.name, task.message) if task.message else task.name | ||||||
|             ret['progress'] = "{} %".format(int(task.progress * 100)) |             ret['progress'] = "{} %".format(int(task.progress * 100)) | ||||||
|             ret['user'] = escape(user)  # prevent xss |             ret['user'] = escape(user)  # prevent xss | ||||||
|  |  | ||||||
|  |             # Hidden fields | ||||||
|  |             ret['task_id'] = task.id | ||||||
|  |             ret['stat'] = task.stat | ||||||
|  |             ret['is_cancellable'] = task.is_cancellable | ||||||
|  |  | ||||||
|             rendered_tasklist.append(ret) |             rendered_tasklist.append(ret) | ||||||
|  |  | ||||||
|     return rendered_tasklist |     return rendered_tasklist | ||||||
| @@ -82,7 +93,7 @@ def render_task_status(tasklist): | |||||||
| def format_runtime(runtime): | def format_runtime(runtime): | ||||||
|     ret_val = "" |     ret_val = "" | ||||||
|     if runtime.days: |     if runtime.days: | ||||||
|         ret_val = format_unit(runtime.days, 'duration-day', length="long", locale=get_locale()) + ', ' |         ret_val = format_unit(runtime.days, 'duration-day', length="long") + ', ' | ||||||
|     minutes, seconds = divmod(runtime.seconds, 60) |     minutes, seconds = divmod(runtime.seconds, 60) | ||||||
|     hours, minutes = divmod(minutes, 60) |     hours, minutes = divmod(minutes, 60) | ||||||
|     # ToDo: locale.number_symbols._data['timeSeparator'] -> localize time separator ? |     # ToDo: locale.number_symbols._data['timeSeparator'] -> localize time separator ? | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								cps/web.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								cps/web.py
									
									
									
									
									
								
							| @@ -24,7 +24,6 @@ import mimetypes | |||||||
| import chardet  # dependency of requests | import chardet  # dependency of requests | ||||||
| import copy | import copy | ||||||
|  |  | ||||||
| from babel import Locale |  | ||||||
| from flask import Blueprint, jsonify | from flask import Blueprint, jsonify | ||||||
| from flask import request, redirect, send_from_directory, make_response, flash, abort, url_for | from flask import request, redirect, send_from_directory, make_response, flash, abort, url_for | ||||||
| from flask import session as flask_session | from flask import session as flask_session | ||||||
| @@ -40,7 +39,7 @@ from werkzeug.datastructures import Headers | |||||||
| from werkzeug.security import generate_password_hash, check_password_hash | from werkzeug.security import generate_password_hash, check_password_hash | ||||||
|  |  | ||||||
| from . import constants, logger, isoLanguages, services | from . import constants, logger, isoLanguages, services | ||||||
| from . import babel, db, ub, config, app | from . import db, ub, config, app | ||||||
| from . import calibre_db, kobo_sync_status | from . import calibre_db, kobo_sync_status | ||||||
| from .search import render_search_results, render_adv_search_results | from .search import render_search_results, render_adv_search_results | ||||||
| from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download | from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download | ||||||
| @@ -50,6 +49,7 @@ from .helper import check_valid_domain, check_email, check_username, \ | |||||||
|     edit_book_read_status |     edit_book_read_status | ||||||
| from .pagination import Pagination | from .pagination import Pagination | ||||||
| from .redirect import redirect_back | from .redirect import redirect_back | ||||||
|  | from .babel import get_available_locale | ||||||
| from .usermanagement import login_required_if_no_ano | from .usermanagement import login_required_if_no_ano | ||||||
| from .kobo_sync_status import remove_synced_book | from .kobo_sync_status import remove_synced_book | ||||||
| from .render_template import render_title_template | from .render_template import render_title_template | ||||||
| @@ -960,7 +960,7 @@ def publisher_list(): | |||||||
|                            .count()) |                            .count()) | ||||||
|         if no_publisher_count: |         if no_publisher_count: | ||||||
|             entries.append([db.Category(_("None"), "-1"), no_publisher_count]) |             entries.append([db.Category(_("None"), "-1"), no_publisher_count]) | ||||||
|         entries = sorted(entries, key=lambda x: x[0].name, reverse=not order_no) |         entries = sorted(entries, key=lambda x: x[0].name.lower(), reverse=not order_no) | ||||||
|         char_list = generate_char_list(entries) |         char_list = generate_char_list(entries) | ||||||
|         return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list, |         return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list, | ||||||
|                                      title=_(u"Publishers"), page="publisherlist", data="publisher", order=order_no) |                                      title=_(u"Publishers"), page="publisherlist", data="publisher", order=order_no) | ||||||
| @@ -990,7 +990,7 @@ def series_list(): | |||||||
|                             .count()) |                             .count()) | ||||||
|             if no_series_count: |             if no_series_count: | ||||||
|                 entries.append([db.Category(_("None"), "-1"), no_series_count]) |                 entries.append([db.Category(_("None"), "-1"), no_series_count]) | ||||||
|             entries = sorted(entries, key=lambda x: x[0].name, reverse=not order_no) |             entries = sorted(entries, key=lambda x: x[0].name.lower(), reverse=not order_no) | ||||||
|             return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list, |             return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list, | ||||||
|                                          title=_(u"Series"), page="serieslist", data="series", order=order_no) |                                          title=_(u"Series"), page="serieslist", data="series", order=order_no) | ||||||
|         else: |         else: | ||||||
| @@ -1092,7 +1092,7 @@ def category_list(): | |||||||
|                          .count()) |                          .count()) | ||||||
|         if no_tag_count: |         if no_tag_count: | ||||||
|             entries.append([db.Category(_("None"), "-1"), no_tag_count]) |             entries.append([db.Category(_("None"), "-1"), no_tag_count]) | ||||||
|         entries = sorted(entries, key=lambda x: x[0].name, reverse=not order_no) |         entries = sorted(entries, key=lambda x: x[0].name.lower(), reverse=not order_no) | ||||||
|         char_list = generate_char_list(entries) |         char_list = generate_char_list(entries) | ||||||
|         return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list, |         return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list, | ||||||
|                                      title=_(u"Categories"), page="catlist", data="category", order=order_no) |                                      title=_(u"Categories"), page="catlist", data="category", order=order_no) | ||||||
| @@ -1417,7 +1417,7 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations, | |||||||
| @login_required | @login_required | ||||||
| def profile(): | def profile(): | ||||||
|     languages = calibre_db.speaking_language() |     languages = calibre_db.speaking_language() | ||||||
|     translations = babel.list_translations() + [Locale('en')] |     translations = get_available_locale() | ||||||
|     kobo_support = feature_support['kobo'] and config.config_kobo_sync |     kobo_support = feature_support['kobo'] and config.config_kobo_sync | ||||||
|     if feature_support['oauth'] and config.config_login_type == 2: |     if feature_support['oauth'] and config.config_login_type == 2: | ||||||
|         oauth_status = get_oauth_status() |         oauth_status = get_oauth_status() | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| # GDrive Integration | # GDrive Integration | ||||||
| google-api-python-client>=1.7.11,<2.46.0 | google-api-python-client>=1.7.11,<2.50.0 | ||||||
| gevent>20.6.0,<22.0.0 | gevent>20.6.0,<22.0.0 | ||||||
| greenlet>=0.4.17,<1.2.0 | greenlet>=0.4.17,<1.2.0 | ||||||
| httplib2>=0.9.2,<0.21.0 | httplib2>=0.9.2,<0.21.0 | ||||||
| @@ -13,7 +13,7 @@ rsa>=3.4.2,<4.9.0 | |||||||
|  |  | ||||||
| # Gmail | # Gmail | ||||||
| google-auth-oauthlib>=0.4.3,<0.6.0 | google-auth-oauthlib>=0.4.3,<0.6.0 | ||||||
| google-api-python-client>=1.7.11,<2.46.0 | google-api-python-client>=1.7.11,<2.50.0 | ||||||
|  |  | ||||||
| # goodreads | # goodreads | ||||||
| goodreads>=0.3.2,<0.4.0 | goodreads>=0.3.2,<0.4.0 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ozzie Isaacs
					Ozzie Isaacs