diff --git a/.gitattributes b/.gitattributes index 92739fe9..8266c99a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ constants.py ident export-subst /test export-ignore +/library export-ignore cps/static/css/libs/* linguist-vendored cps/static/js/libs/* linguist-vendored diff --git a/.gitignore b/.gitignore index 14da8a03..ff08f874 100644 --- a/.gitignore +++ b/.gitignore @@ -28,8 +28,10 @@ cps/cache .idea/ *.bak *.log.* +.key settings.yaml gdrive_credentials client_secrets.json gmail.json +/.key diff --git a/.key b/.key deleted file mode 100644 index 905cf23a..00000000 --- a/.key +++ /dev/null @@ -1 +0,0 @@ -onLmA_LND5S8jNSvi8nNSGwevE13f7t8pW-wgWAXZgo= \ No newline at end of file diff --git a/README.md b/README.md index c558e21d..db8efe31 100755 --- a/README.md +++ b/README.md @@ -1,99 +1,118 @@ -# About +# Calibre-Web -Calibre-Web is a web app providing a clean interface for browsing, reading and downloading eBooks using a valid [Calibre](https://calibre-ebook.com) database. +Calibre-Web is a web app that offers a clean and intuitive interface for browsing, reading, and downloading eBooks using a valid [Calibre](https://calibre-ebook.com) database. -[![GitHub License](https://img.shields.io/github/license/janeczku/calibre-web?style=flat-square)](https://github.com/janeczku/calibre-web/blob/master/LICENSE) -[![GitHub commit activity](https://img.shields.io/github/commit-activity/w/janeczku/calibre-web?logo=github&style=flat-square&label=commits)]() -[![GitHub all releases](https://img.shields.io/github/downloads/janeczku/calibre-web/total?logo=github&style=flat-square)](https://github.com/janeczku/calibre-web/releases) +[![License](https://img.shields.io/github/license/janeczku/calibre-web?style=flat-square)](https://github.com/janeczku/calibre-web/blob/master/LICENSE) +![Commit Activity](https://img.shields.io/github/commit-activity/w/janeczku/calibre-web?logo=github&style=flat-square&label=commits) +[![All Releases](https://img.shields.io/github/downloads/janeczku/calibre-web/total?logo=github&style=flat-square)](https://github.com/janeczku/calibre-web/releases) [![PyPI](https://img.shields.io/pypi/v/calibreweb?logo=pypi&logoColor=fff&style=flat-square)](https://pypi.org/project/calibreweb/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/calibreweb?logo=pypi&logoColor=fff&style=flat-square)](https://pypi.org/project/calibreweb/) [![Discord](https://img.shields.io/discord/838810113564344381?label=Discord&logo=discord&style=flat-square)](https://discord.gg/h2VsJ2NEfB) +
+Table of Contents (click to expand) + +1. [About](#calibre-web) +2. [Features](#features) +3. [Installation](#installation) + - [Installation via pip (recommended)](#installation-via-pip-recommended) + - [Quick start](#quick-start) + - [Requirements](#requirements) +4. [Docker Images](#docker-images) +5. [Contributor Recognition](#contributor-recognition) +6. [Contact](#contact) +7. [Contributing to Calibre-Web](#contributing-to-calibre-web) + +
+ + *This software is a fork of [library](https://github.com/mutschler/calibreserver) and licensed under the GPL v3 License.* ![Main screen](https://github.com/janeczku/calibre-web/wiki/images/main_screen.png) ## Features -- Bootstrap 3 HTML5 interface -- full graphical setup -- User management with fine-grained per-user permissions +- Modern and responsive Bootstrap 3 HTML5 interface +- Full graphical setup +- Comprehensive user management with fine-grained per-user permissions - Admin interface -- User Interface in brazilian, czech, dutch, english, finnish, french, galician, german, greek, hungarian, italian, japanese, khmer, korean, polish, russian, simplified and traditional chinese, spanish, swedish, turkish, ukrainian, vietnamese -- OPDS feed for eBook reader apps -- Filter and search by titles, authors, tags, series, book format and language -- Create a custom book collection (shelves) -- Support for editing eBook metadata and deleting eBooks from Calibre library -- Support for downloading eBook metadata from various sources, sources can be extended via external plugins -- Support for converting eBooks through Calibre binaries -- Restrict eBook download to logged-in users -- Support for public user registration -- Send eBooks to E-Readers with the click of a button -- Sync your Kobo devices through Calibre-Web with your Calibre library -- Support for reading eBooks directly in the browser (.txt, .epub, .pdf, .cbr, .cbt, .cbz, .djvu) -- Upload new books in many formats, including audio formats (.mp3, .m4a, .m4b) -- Support for Calibre Custom Columns -- Ability to hide content based on categories and Custom Column content per user +- Multilingual user interface supporting 20+ languages ([supported languages](https://github.com/janeczku/calibre-web/wiki/Translation-Status)) +- OPDS feed for eBook reader apps +- Advanced search and filtering options +- Custom book collection (shelves) creation +- eBook metadata editing and deletion support +- Metadata download from various sources (extensible via plugins) +- eBook conversion through Calibre binaries +- eBook download restriction to logged-in users +- Public user registration support +- Send eBooks to E-Readers with a single click +- Sync Kobo devices with your Calibre library +- In-browser eBook reading support for multiple formats +- Upload new books in various formats, including audio formats +- Calibre Custom Columns support +- Content hiding based on categories and Custom Column content per user - Self-update capability -- "Magic Link" login to make it easy to log on eReaders -- Login via LDAP, google/github oauth and via proxy authentication +- "Magic Link" login for easy access on eReaders +- LDAP, Google/GitHub OAuth, and proxy authentication support ## Installation #### Installation via pip (recommended) -1. To avoid problems with already installed python dependencies, it's recommended to create a virtual environment for Calibre-Web -2. Install Calibre-Web via pip with the command `pip install calibreweb` (Depending on your OS and or distro the command could also be `pip3`). -3. Optional features can also be installed via pip, please refer to [this page](https://github.com/janeczku/calibre-web/wiki/Dependencies-in-Calibre-Web-Linux-and-Windows) for details -4. Calibre-Web can be started afterwards by typing `cps` +1. Create a virtual environment for Calibre-Web to avoid conflicts with existing Python dependencies +2. Install Calibre-Web via pip: `pip install calibreweb` (or `pip3` depending on your OS/distro) +3. Install optional features via pip as needed, see [this page](https://github.com/janeczku/calibre-web/wiki/Dependencies-in-Calibre-Web-Linux-and-Windows) for details +4. Start Calibre-Web by typing `cps` -In the Wiki there are also examples for: a [manual installation](https://github.com/janeczku/calibre-web/wiki/Manual-installation), [installation on Linux Mint](https://github.com/janeczku/calibre-web/wiki/How-To:Install-Calibre-Web-in-Linux-Mint-19-or-20), [installation on a Cloud Provider](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-on-a-Cloud-Provider). +*Note: Raspberry Pi OS users may encounter issues during installation. If so, please update pip (`./venv/bin/python3 -m pip install --upgrade pip`) and/or install cargo (`sudo apt install cargo`) before retrying the installation.* -## Quick start +Refer to the Wiki for additional installation examples: [manual installation](https://github.com/janeczku/calibre-web/wiki/Manual-installation), [Linux Mint](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-in-Linux-Mint-19-or-20), [Cloud Provider](https://github.com/janeczku/calibre-web/wiki/How-To:-Install-Calibre-Web-on-a-Cloud-Provider). -Point your browser to `http://localhost:8083` or `http://localhost:8083/opds` for the OPDS catalog \ -Login with default admin login \ -Set `Location of Calibre database` to the path of the folder where your Calibre library (metadata.db) lives, push "submit" button \ -Optionally a Google Drive can be used to host the calibre library [-> Using Google Drive integration](https://github.com/janeczku/calibre-web/wiki/G-Drive-Setup#using-google-drive-integration) \ -Afterwards you can configure your Calibre-Web instance ([Basic Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#basic-configuration) and [UI Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#ui-configuration) on admin page) +## Quick Start -#### Default admin login: -*Username:* admin\ -*Password:* admin123 +1. Open your browser and navigate to `http://localhost:8083` or `http://localhost:8083/opds` for the OPDS catalog +2. Log in with the default admin credentials +3. If you don't have a Calibre database, you can use [this database](https://github.com/janeczku/calibre-web/raw/master/library/metadata.db) (move it out of the Calibre-Web folder to prevent overwriting during updates) +4. Set `Location of Calibre database` to the path of the folder containing your Calibre library (metadata.db) and click "Save" +5. Optionally, use Google Drive to host your Calibre library by following the [Google Drive integration guide](https://github.com/janeczku/calibre-web/wiki/G-Drive-Setup#using-google-drive-integration) +6. Configure your Calibre-Web instance via the admin page, referring to the [Basic Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#basic-configuration) and [UI Configuration](https://github.com/janeczku/calibre-web/wiki/Configuration#ui-configuration) guides +#### Default Admin Login: +- **Username:** admin +- **Password:** admin123 ## Requirements -python 3.5+ - -Optionally, to enable on-the-fly conversion from one ebook format to another when using the send-to-ereader feature, or during editing of ebooks metadata: - -[Download and install](https://calibre-ebook.com/download) the Calibre desktop program for your platform and enter the folder including program name (normally /opt/calibre/ebook-convert, or C:\Program Files\calibre\ebook-convert.exe) in the field "calibre's converter tool" on the setup page. - -[Download](https://github.com/pgaskin/kepubify/releases/latest) Kepubify tool for your platform and place the binary starting with `kepubify` in Linux: `/opt/kepubify` Windows: `C:\Program Files\kepubify`. +- Python 3.5+ +- [Imagemagick](https://imagemagick.org/script/download.php) for cover extraction from EPUBs (Windows users may need to install [Ghostscript](https://ghostscript.com/releases/gsdnld.html) for PDF cover extraction) +- Optional: [Calibre desktop program](https://calibre-ebook.com/download) for on-the-fly conversion and metadata editing (set "calibre's converter tool" path on the setup page) +- Optional: [Kepubify tool](https://github.com/pgaskin/kepubify/releases/latest) for Kobo device support (place the binary in `/opt/kepubify` on Linux or `C:\Program Files\kepubify` on Windows) ## Docker Images -A pre-built Docker image is available in these Docker Hub repository (maintained by the LinuxServer team): +Pre-built Docker images are available in the following Docker Hub repositories (maintained by the LinuxServer team): -#### **LinuxServer - x64, armhf, aarch64** -+ Docker Hub - [https://hub.docker.com/r/linuxserver/calibre-web](https://hub.docker.com/r/linuxserver/calibre-web) -+ Github - [https://github.com/linuxserver/docker-calibre-web](https://github.com/linuxserver/docker-calibre-web) -+ Github - (Optional Calibre layer) - [https://github.com/linuxserver/docker-calibre-web/tree/calibre](https://github.com/linuxserver/docker-calibre-web/tree/calibre) +#### **LinuxServer - x64, aarch64** +- [Docker Hub](https://hub.docker.com/r/linuxserver/calibre-web) +- [GitHub](https://github.com/linuxserver/docker-calibre-web) +- [GitHub - Optional Calibre layer](https://github.com/linuxserver/docker-mods/tree/universal-calibre) - This image has the option to pull in an extra docker manifest layer to include the Calibre `ebook-convert` binary. Just include the environmental variable `DOCKER_MODS=linuxserver/calibre-web:calibre` in your docker run/docker compose file. **(x64 only)** - - If you do not need this functionality then this can be omitted, keeping the image as lightweight as possible. - - Both the Calibre-Web and Calibre-Mod images are rebuilt automatically on new releases of Calibre-Web and Calibre respectively, and on updates to any included base image packages on a weekly basis if required. - + The "path to convertertool" should be set to `/usr/bin/ebook-convert` - + The "path to unrar" should be set to `/usr/bin/unrar` + Include the environment variable `DOCKER_MODS=linuxserver/mods:universal-calibre` in your Docker run/compose file to add the Calibre `ebook-convert` binary (x64 only). Omit this variable for a lightweight image. -# Contact + Both the Calibre-Web and Calibre-Mod images are automatically rebuilt on new releases and updates. -Just reach us out on [Discord](https://discord.gg/h2VsJ2NEfB) + - Set "path to convertertool" to `/usr/bin/ebook-convert` + - Set "path to unrar" to `/usr/bin/unrar` -For further information, How To's and FAQ please check the [Wiki](https://github.com/janeczku/calibre-web/wiki) +## Contributor Recognition -# Contributing to Calibre-Web +We would like to thank all the [contributors](https://github.com/janeczku/calibre-web/graphs/contributors) and maintainers of Calibre-Web for their valuable input and dedication to the project. Your contributions are greatly appreciated. -Please have a look at our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md) +## Contact + +Join us on [Discord](https://discord.gg/h2VsJ2NEfB) + +For more information, How To's, and FAQs, please visit the [Wiki](https://github.com/janeczku/calibre-web/wiki) + +## Contributing to Calibre-Web + +Check out our [Contributing Guidelines](https://github.com/janeczku/calibre-web/blob/master/CONTRIBUTING.md) diff --git a/SECURITY.md b/SECURITY.md index f37c62dc..e4ab1a8d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -38,6 +38,13 @@ To receive fixes for security vulnerabilities it is required to always upgrade t | V 0.6.18 | Possible SQL Injection is prevented in user table Thanks to Iman Sharafaldin (Forward Security) |CVE-2022-30765| | V 0.6.18 | The SSRF protection no longer can be bypassed by IPV6/IPV4 embedding. Thanks to @416e6e61 |CVE-2022-0939| | V 0.6.18 | The SSRF protection no longer can be bypassed to connect to other servers in the local network. Thanks to @michaellrowley |CVE-2022-0990| +| V 0.6.20 | Credentials for emails are now stored encrypted || +| V 0.6.20 | Login is rate limited || +| V 0.6.20 | Passwordstrength can be forced || +| V 0.6.21 | SMTP server credentials are no longer returned to client || +| V 0.6.21 | Cross-site scripting (XSS) stored in href bypasses filter using data wrapper no longer possible || +| V 0.6.21 | Cross-site scripting (XSS) is no longer possible via pathchooser || +| V 0.6.21 | Error Handling at non existent rating, language, and user downloaded books was fixed || ## Statement regarding Log4j (CVE-2021-44228 and related) diff --git a/babel.cfg b/babel.cfg index 9c7ce3a7..2b7116e7 100644 --- a/babel.cfg +++ b/babel.cfg @@ -2,4 +2,3 @@ # has to be executed with jinja2 >=2.9 to have autoescape enabled automatically [jinja2: **/templates/**.*ml] -extensions=jinja2.ext.with_ diff --git a/cps.py b/cps.py index e4f9c520..f97d0f5a 100755 --- a/cps.py +++ b/cps.py @@ -21,7 +21,7 @@ import os import sys -# Add local path to sys.path so we can import cps +# Add local path to sys.path, so we can import cps path = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, path) diff --git a/cps/MyLoginManager.py b/cps/MyLoginManager.py index 2f06be94..39e7e4a5 100644 --- a/cps/MyLoginManager.py +++ b/cps/MyLoginManager.py @@ -21,15 +21,32 @@ # along with this program. If not, see . -from flask_login import LoginManager -from flask import session - +from flask_login import LoginManager, confirm_login +from flask import session, current_app +from flask_login.utils import decode_cookie +from flask_login.signals import user_loaded_from_cookie class MyLoginManager(LoginManager): def _session_protection_failed(self): - _session = session._get_current_object() + sess = session._get_current_object() ident = self._session_identifier_generator() - if(_session and not (len(_session) == 1 - and _session.get('csrf_token', None))) and ident != _session.get('_id', None): + if(sess and not (len(sess) == 1 + and sess.get('csrf_token', None))) and ident != sess.get('_id', None): return super(). _session_protection_failed() return False + + def _load_user_from_remember_cookie(self, cookie): + user_id = decode_cookie(cookie) + if user_id is not None: + session["_user_id"] = user_id + session["_fresh"] = False + user = None + if self._user_callback: + user = self._user_callback(user_id) + if user is not None: + app = current_app._get_current_object() + user_loaded_from_cookie.send(app, user=user) + # if session was restored from remember me cookie make login valid + confirm_login() + return user + return None diff --git a/cps/__init__.py b/cps/__init__.py index 1ba1f778..f4f8dbf2 100644 --- a/cps/__init__.py +++ b/cps/__init__.py @@ -36,11 +36,16 @@ from .reverseproxy import ReverseProxied from .server import WebServer from .dep_check import dependency_check from .updater import Updater -from .babel import babel +from .babel import babel, get_locale from . import config_sql from . import cache_buster from . import ub, db +try: + from flask_limiter import Limiter + limiter_present = True +except ImportError: + limiter_present = False try: from flask_wtf.csrf import CSRFProtect wtf_present = True @@ -59,7 +64,8 @@ mimetypes.add_type('application/x-mobi8-ebook', '.azw3') mimetypes.add_type('application/x-cbr', '.cbr') mimetypes.add_type('application/x-cbz', '.cbz') mimetypes.add_type('application/x-cbt', '.cbt') -mimetypes.add_type('image/vnd.djvu', '.djvu') +mimetypes.add_type('application/x-cb7', '.cb7') +mimetypes.add_type('image/vnd.djv', '.djv') mimetypes.add_type('application/mpeg', '.mpeg') mimetypes.add_type('application/mpeg', '.mp3') mimetypes.add_type('application/mp4', '.m4a') @@ -81,10 +87,10 @@ app.config.update( lm = MyLoginManager() -config = config_sql._ConfigSQL() - cli_param = CliParameter() +config = config_sql.ConfigSQL() + if wtf_present: csrf = CSRFProtect() else: @@ -96,33 +102,36 @@ web_server = WebServer() updater_thread = Updater() +if limiter_present: + limiter = Limiter(key_func=True, headers_enabled=True, auto_check=False, swallow_errors=True) +else: + limiter = None def create_app(): - lm.login_view = 'web.login' - lm.anonymous_user = ub.Anonymous - lm.session_protection = 'strong' - if csrf: csrf.init_app(app) cli_param.init() - ub.init_db(cli_param.settings_path, cli_param.user_credentials) - + ub.init_db(cli_param.settings_path) # pylint: disable=no-member - config_sql.load_configuration(config, ub.session, cli_param) + encrypt_key, error = config_sql.get_encryption_key(os.path.dirname(cli_param.settings_path)) - db.CalibreDB.update_config(config) - db.CalibreDB.setup_db(config.config_calibre_dir, cli_param.settings_path) - calibre_db.init_db() + config_sql.load_configuration(ub.session, encrypt_key) + config.init_config(ub.session, encrypt_key, cli_param) - updater_thread.init_updater(config, web_server) - # Perform dry run of updater and exit afterwards - if cli_param.dry_run: - updater_thread.dry_run() - sys.exit(0) - updater_thread.start() + if error: + log.error(error) + ub.password_change(cli_param.user_credentials) + + if not limiter: + log.info('*** "flask-limiter" is needed for calibre-web to run. ' + 'Please install it using pip: "pip install flask-limiter" ***') + print('*** "flask-limiter" is needed for calibre-web to run. ' + 'Please install it using pip: "pip install flask-limiter" ***') + web_server.stop(True) + sys.exit(8) if sys.version_info < (3, 0): log.info( '*** Python2 is EOL since end of 2019, this version of Calibre-Web is no longer supporting Python2, ' @@ -139,8 +148,24 @@ def create_app(): 'Please install it using pip: "pip install flask-WTF" ***') web_server.stop(True) sys.exit(7) + + lm.login_view = 'web.login' + lm.anonymous_user = ub.Anonymous + lm.session_protection = 'strong' if config.config_session == 1 else "basic" + + db.CalibreDB.update_config(config) + db.CalibreDB.setup_db(config.config_calibre_dir, cli_param.settings_path) + calibre_db.init_db() + + updater_thread.init_updater(config, web_server) + # Perform dry run of updater and exit afterwards + if cli_param.dry_run: + updater_thread.dry_run() + sys.exit(0) + updater_thread.start() + for res in dependency_check() + dependency_check(True): - log.info('*** "{}" version does not fit the requirements. ' + log.info('*** "{}" version does not meet the requirements. ' 'Should: {}, Found: {}, please consider installing required version ***' .format(res['name'], res['target'], @@ -150,14 +175,16 @@ def create_app(): if os.environ.get('FLASK_DEBUG'): cache_buster.init_cache_busting(app) log.info('Starting Calibre Web...') - Principal(app) lm.init_app(app) app.secret_key = os.getenv('SECRET_KEY', config_sql.get_flask_session_key(ub.session)) web_server.init_app(app, config) - - babel.init_app(app) + if hasattr(babel, "localeselector"): + babel.init_app(app) + babel.localeselector(get_locale) + else: + babel.init_app(app, locale_selector=get_locale) from . import services @@ -165,9 +192,13 @@ def create_app(): services.ldap.init_app(app, config) if services.goodreads_support: services.goodreads_support.connect(config.config_goodreads_api_key, - config.config_goodreads_api_secret, + config.config_goodreads_api_secret_e, config.config_use_goodreads) config.store_calibre_uuid(calibre_db, db.Library_Id) + # Configure rate limiter + app.config.update(RATELIMIT_ENABLED=config.config_ratelimiter) + limiter.init_app(app) + # Register scheduled tasks from .schedule import register_scheduled_tasks, register_startup_tasks register_scheduled_tasks(config.schedule_reconnect) diff --git a/cps/about.py b/cps/about.py index 31e843b9..7b6cc71a 100644 --- a/cps/about.py +++ b/cps/about.py @@ -81,4 +81,4 @@ def stats(): categories = calibre_db.session.query(db.Tags).count() series = calibre_db.session.query(db.Series).count() return render_title_template('stats.html', bookcounter=counter, authorcounter=authors, versions=collect_stats(), - categorycounter=categories, seriecounter=series, title=_(u"Statistics"), page="stat") + categorycounter=categories, seriecounter=series, title=_("Statistics"), page="stat") diff --git a/cps/admin.py b/cps/admin.py index 758680a2..5a91375a 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -22,7 +22,6 @@ import os import re -import base64 import json import operator import time @@ -31,9 +30,11 @@ import string from datetime import datetime, timedelta from datetime import time as datetime_time from functools import wraps +from urllib.parse import urlparse from flask import Blueprint, flash, redirect, url_for, abort, request, make_response, send_from_directory, g, Response -from flask_login import login_required, current_user, logout_user, confirm_login +from markupsafe import Markup +from flask_login import login_required, current_user, logout_user from flask_babel import gettext as _ from flask_babel import get_locale, format_time, format_datetime, format_timedelta from flask import session as flask_session @@ -101,25 +102,26 @@ def admin_required(f): @admi.before_app_request def before_request(): - # make remember me function work - if current_user.is_authenticated: - confirm_login() - if not ub.check_user_session(current_user.id, flask_session.get('_id')) and 'opds' not in request.path: - logout_user() + try: + if not ub.check_user_session(current_user.id, + flask_session.get('_id')) and 'opds' not in request.path \ + and config.config_session == 1: + logout_user() + except AttributeError: + pass # ? fails on requesting /ajax/emailstat during restart ? g.constants = constants - g.user = current_user + g.google_site_verification = os.getenv('GOOGLE_SITE_VERIFICATION', '') g.allow_registration = config.config_public_reg g.allow_anonymous = config.config_anonbrowse g.allow_upload = config.config_uploading g.current_theme = config.config_theme g.config_authors_max = config.config_authors_max - g.shelves_access = ub.session.query(ub.Shelf).filter( - or_(ub.Shelf.is_public == 1, ub.Shelf.user_id == current_user.id)).order_by(ub.Shelf.name).all() if '/static/' not in request.path and not config.db_configured and \ request.endpoint not in ('admin.ajax_db_config', 'admin.simulatedbchange', 'admin.db_configuration', 'web.login', + 'web.login_post', 'web.logout', 'admin.load_dialogtexts', 'admin.ajax_pathchooser'): @@ -144,9 +146,9 @@ def shutdown(): ub.dispose() if task == 0: - show_text['text'] = _(u'Server restarted, please reload page') + show_text['text'] = _('Server restarted, please reload page.') else: - show_text['text'] = _(u'Performing shutdown of server, please close window') + show_text['text'] = _('Performing Server shutdown, please close window.') # stop gevent/tornado server web_server.stop(task == 0) return json.dumps(show_text) @@ -154,10 +156,10 @@ def shutdown(): if task == 2: log.warning("reconnecting to calibre database") calibre_db.reconnect_db(config, ub.app_DB_path) - show_text['text'] = _(u'Reconnect successful') + show_text['text'] = _('Success! Database Reconnected') return json.dumps(show_text) - show_text['text'] = _(u'Unknown command') + show_text['text'] = _('Unknown command') return json.dumps(show_text), 400 @@ -168,7 +170,7 @@ def queue_metadata_backup(): show_text = {} log.warning("Queuing all books for metadata backup") helper.set_all_metadata_dirty() - show_text['text'] = _(u'Books successfully queued for Metadata Backup') + show_text['text'] = _('Success! Books queued for Metadata Backup, please check Tasks for result') return json.dumps(show_text) @@ -201,7 +203,7 @@ def update_thumbnails(): def admin(): version = updater_thread.get_current_version_info() if version is False: - commit = _(u'Unknown') + commit = _('Unknown') else: if 'datetime' in version: commit = version['datetime'] @@ -218,15 +220,15 @@ def admin(): commit = version['version'] all_user = ub.session.query(ub.User).all() - email_settings = config.get_mail_settings() + # email_settings = mail_config.get_mail_settings() schedule_time = format_time(datetime_time(hour=config.schedule_start_time), format="short") t = timedelta(hours=config.schedule_duration // 60, minutes=config.schedule_duration % 60) schedule_duration = format_timedelta(t, threshold=.99) - return render_title_template("admin.html", allUser=all_user, email=email_settings, config=config, commit=commit, + return render_title_template("admin.html", allUser=all_user, config=config, commit=commit, feature_support=feature_support, schedule_time=schedule_time, schedule_duration=schedule_duration, - title=_(u"Admin page"), page="admin") + title=_("Admin page"), page="admin") @admi.route("/admin/dbconfig", methods=["GET", "POST"]) @@ -246,7 +248,7 @@ def configuration(): config=config, provider=oauthblueprints, feature_support=feature_support, - title=_(u"Basic Configuration"), page="config") + title=_("Basic Configuration"), page="config") @admi.route("/admin/ajaxconfig", methods=["POST"]) @@ -284,7 +286,7 @@ def view_configuration(): restrictColumns=restrict_columns, languages=languages, translations=translations, - title=_(u"UI Configuration"), page="uiconfig") + title=_("UI Configuration"), page="uiconfig") @admi.route("/admin/usertable") @@ -318,7 +320,7 @@ def edit_user_table(): all_roles=constants.ALL_ROLES, kobo_support=kobo_support, sidebar_settings=constants.sidebar_settings, - title=_(u"Edit Users"), + title=_("Edit Users"), page="usertable") @@ -489,7 +491,7 @@ def edit_list_user(param): ub.User.id != user.id).count(): return Response( json.dumps([{'type': "danger", - 'message': _(u"No admin user remaining, can't remove admin role", + 'message': _("No admin user remaining, can't remove admin role", nick=user.name)}]), mimetype='application/json') user.role &= ~value else: @@ -566,13 +568,13 @@ def update_view_configuration(): calibre_db.update_title_sort(config) if not check_valid_read_column(to_save.get("config_read_column", "0")): - flash(_(u"Invalid Read Column"), category="error") + flash(_("Invalid Read Column"), category="error") log.debug("Invalid Read column") return view_configuration() _config_int(to_save, "config_read_column") if not check_valid_restricted_column(to_save.get("config_restricted_column", "0")): - flash(_(u"Invalid Restricted Column"), category="error") + flash(_("Invalid Restricted Column"), category="error") log.debug("Invalid Restricted Column") return view_configuration() _config_int(to_save, "config_restricted_column") @@ -592,7 +594,7 @@ def update_view_configuration(): config.config_default_show |= constants.DETAIL_RANDOM config.save() - flash(_(u"Calibre-Web configuration updated"), category="success") + flash(_("Calibre-Web configuration updated"), category="success") log.debug("Calibre-Web configuration updated") before_request() @@ -1037,7 +1039,8 @@ def pathchooser(): for f in folders: try: - data = {"name": f, "fullpath": os.path.join(cwd, f)} + sanitized_f = str(Markup.escape(f)) + data = {"name": sanitized_f, "fullpath": os.path.join(cwd, sanitized_f)} data["sort"] = data["fullpath"].lower() except Exception: continue @@ -1088,7 +1091,7 @@ def _config_checkbox_int(to_save, x): def _config_string(to_save, x): - return config.set_from_dictionary(to_save, x, lambda y: y.strip() if y else y) + return config.set_from_dictionary(to_save, x, lambda y: y.strip().strip(u'\u200B\u200C\u200D\ufeff') if y else y) def _configuration_gdrive_helper(to_save): @@ -1162,7 +1165,6 @@ def _configuration_logfile_helper(to_save): def _configuration_ldap_helper(to_save): reboot_required = False - reboot_required |= _config_string(to_save, "config_ldap_provider_url") reboot_required |= _config_int(to_save, "config_ldap_port") reboot_required |= _config_int(to_save, "config_ldap_authentication") reboot_required |= _config_string(to_save, "config_ldap_dn") @@ -1178,9 +1180,14 @@ def _configuration_ldap_helper(to_save): reboot_required |= _config_string(to_save, "config_ldap_key_path") _config_string(to_save, "config_ldap_group_name") _config_checkbox(to_save, "config_ldap_autocreate_user") - if to_save.get("config_ldap_serv_password", "") != "": + + address = urlparse(to_save.get("config_ldap_provider_url", "")) + to_save["config_ldap_provider_url"] = (address.hostname or address.path).strip("/") + reboot_required |= _config_string(to_save, "config_ldap_provider_url") + + if to_save.get("config_ldap_serv_password_e", "") != "": reboot_required |= 1 - config.set_from_dictionary(to_save, "config_ldap_serv_password", base64.b64encode, encode='UTF-8') + config.set_from_dictionary(to_save, "config_ldap_serv_password_e") config.save() if not config.config_ldap_provider_url \ @@ -1192,7 +1199,7 @@ def _configuration_ldap_helper(to_save): if config.config_ldap_authentication > constants.LDAP_AUTH_ANONYMOUS: if config.config_ldap_authentication > constants.LDAP_AUTH_UNAUTHENTICATE: - if not config.config_ldap_serv_username or not bool(config.config_ldap_serv_password): + if not config.config_ldap_serv_username or not bool(config.config_ldap_serv_password_e): return reboot_required, _configuration_result(_('Please Enter a LDAP Service Account and Password')) else: if not config.config_ldap_serv_username: @@ -1256,16 +1263,16 @@ def new_user(): content.default_language = config.config_default_language return render_title_template("user_edit.html", new_user=1, content=content, config=config, translations=translations, - languages=languages, title=_(u"Add new user"), page="newuser", + languages=languages, title=_("Add New User"), page="newuser", kobo_support=kobo_support, registered_oauth=oauth_check) -@admi.route("/admin/mailsettings") +@admi.route("/admin/mailsettings", methods=["GET"]) @login_required @admin_required def edit_mailsettings(): content = config.get_mail_settings() - return render_title_template("email_edit.html", content=content, title=_(u"Edit E-mail Server Settings"), + return render_title_template("email_edit.html", content=content, title=_("Edit Email Server Settings"), page="mailset", feature_support=feature_support) @@ -1284,7 +1291,7 @@ def update_mailsettings(): elif to_save.get("gmail"): try: config.mail_gmail_token = services.gmail.setup_gmail(config.mail_gmail_token) - flash(_(u"Gmail Account Verification Successful"), category="success") + flash(_("Success! Gmail Account Verified."), category="success") except Exception as ex: flash(str(ex), category="error") log.error(ex) @@ -1293,7 +1300,8 @@ def update_mailsettings(): else: _config_int(to_save, "mail_port") _config_int(to_save, "mail_use_ssl") - _config_string(to_save, "mail_password") + if to_save.get("mail_password_e", ""): + _config_string(to_save, "mail_password_e") _config_int(to_save, "mail_size", lambda y: int(y) * 1024 * 1024) config.mail_server = to_save.get('mail_server', "").strip() config.mail_from = to_save.get('mail_from', "").strip() @@ -1303,24 +1311,24 @@ def update_mailsettings(): except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") return edit_mailsettings() except Exception as e: - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") return edit_mailsettings() if to_save.get("test"): if current_user.email: result = send_test_mail(current_user.email, current_user.name) if result is None: - flash(_(u"Test e-mail queued for sending to %(email)s, please check Tasks for result", + flash(_("Test e-mail queued for sending to %(email)s, please check Tasks for result", email=current_user.email), category="info") else: - flash(_(u"There was an error sending the Test e-mail: %(res)s", res=result), category="error") + flash(_("There was an error sending the Test e-mail: %(res)s", res=result), category="error") else: - flash(_(u"Please configure your e-mail address first..."), category="error") + flash(_("Please configure your e-mail address first..."), category="error") else: - flash(_(u"E-mail server settings updated"), category="success") + flash(_("Email Server Settings updated"), category="success") return edit_mailsettings() @@ -1343,7 +1351,7 @@ def edit_scheduledtasks(): config=content, starttime=time_field, duration=duration_field, - title=_(u"Edit Scheduled Tasks Settings")) + title=_("Edit Scheduled Tasks Settings")) @admi.route("/admin/scheduledtasks", methods=["POST"]) @@ -1353,23 +1361,24 @@ def update_scheduledtasks(): error = False to_save = request.form.to_dict() if 0 <= int(to_save.get("schedule_start_time")) <= 23: - _config_int(to_save, "schedule_start_time") + _config_int( to_save, "schedule_start_time") else: - flash(_(u"Invalid start time for task specified"), category="error") + flash(_("Invalid start time for task specified"), category="error") error = True if 0 < int(to_save.get("schedule_duration")) <= 60: _config_int(to_save, "schedule_duration") else: - flash(_(u"Invalid duration for task specified"), category="error") + flash(_("Invalid duration for task specified"), category="error") error = True _config_checkbox(to_save, "schedule_generate_book_covers") _config_checkbox(to_save, "schedule_generate_series_covers") + _config_checkbox(to_save, "schedule_metadata_backup") _config_checkbox(to_save, "schedule_reconnect") if not error: try: config.save() - flash(_(u"Scheduled tasks settings updated"), category="success") + flash(_("Scheduled tasks settings updated"), category="success") # Cancel any running tasks schedule.end_scheduled_tasks() @@ -1379,7 +1388,7 @@ def update_scheduledtasks(): except IntegrityError: ub.session.rollback() log.error("An unknown error occurred while saving scheduled tasks settings") - flash(_(u"An unknown error occurred. Please try again later."), category="error") + flash(_("Oops! An unknown error occurred. Please try again later."), category="error") except OperationalError: ub.session.rollback() log.error("Settings DB is not Writeable") @@ -1394,7 +1403,7 @@ def update_scheduledtasks(): def edit_user(user_id): content = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first() # type: ub.User if not content or (not config.config_anonbrowse and content.name == "Guest"): - flash(_(u"User not found"), category="error") + flash(_("User not found"), category="error") return redirect(url_for('admin.admin')) languages = calibre_db.speaking_language(return_all_languages=True) translations = get_available_locale() @@ -1413,7 +1422,7 @@ def edit_user(user_id): registered_oauth=oauth_check, mail_configured=config.get_mail_server_configured(), kobo_support=kobo_support, - title=_(u"Edit User %(nick)s", nick=content.name), + title=_("Edit User %(nick)s", nick=content.name), page="edituser") @@ -1424,14 +1433,14 @@ def reset_user_password(user_id): if current_user is not None and current_user.is_authenticated: ret, message = reset_password(user_id) if ret == 1: - log.debug(u"Password for user %s reset", message) - flash(_(u"Password for user %(user)s reset", user=message), category="success") + log.debug("Password for user %s reset", message) + flash(_("Success! Password for user %(user)s reset", user=message), category="success") elif ret == 0: - log.error(u"An unknown error occurred. Please try again later.") - flash(_(u"An unknown error occurred. Please try again later."), category="error") + log.error("An unknown error occurred. Please try again later.") + flash(_("Oops! An unknown error occurred. Please try again later."), category="error") else: - log.error(u"Please configure the SMTP mail settings first...") - flash(_(u"Please configure the SMTP mail settings first..."), category="error") + log.error("Please configure the SMTP mail settings.") + flash(_("Oops! Please configure the SMTP mail settings."), category="error") return redirect(url_for('admin.admin')) @@ -1442,7 +1451,7 @@ def view_logfile(): logfiles = {0: logger.get_logfile(config.config_logfile), 1: logger.get_accesslogfile(config.config_access_logfile)} return render_title_template("logviewer.html", - title=_(u"Logfile viewer"), + title=_("Logfile viewer"), accesslog_enable=config.config_access_log, log_enable=bool(config.config_logfile != logger.LOG_TO_STDOUT), logfiles=logfiles, @@ -1492,7 +1501,7 @@ def download_debug(): @admin_required def get_update_status(): if feature_support['updater']: - log.info(u"Update status requested") + log.info("Update status requested") return updater_thread.get_available_updates(request.method) else: return '' @@ -1687,7 +1696,7 @@ def _db_configuration_update_helper(): except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - _db_configuration_result(_(u"Database error: %(error)s.", error=e.orig), gdrive_error) + _db_configuration_result(_("Oops! Database Error: %(error)s.", error=e.orig), gdrive_error) try: metadata_db = os.path.join(to_save['config_calibre_dir'], "metadata.db") if config.config_use_google_drive and is_gdrive_ready() and not os.path.exists(metadata_db): @@ -1719,7 +1728,7 @@ def _db_configuration_update_helper(): _config_string(to_save, "config_calibre_dir") calibre_db.update_config(config) if not os.access(os.path.join(config.config_calibre_dir, "metadata.db"), os.W_OK): - flash(_(u"DB is not Writeable"), category="warning") + flash(_("DB is not Writeable"), category="warning") config.save() return _db_configuration_result(None, gdrive_error) @@ -1776,10 +1785,11 @@ def _configuration_update_helper(): # Goodreads configuration _config_checkbox(to_save, "config_use_goodreads") _config_string(to_save, "config_goodreads_api_key") - _config_string(to_save, "config_goodreads_api_secret") + if to_save.get("config_goodreads_api_secret_e", ""): + _config_string(to_save, "config_goodreads_api_secret_e") if services.goodreads_support: services.goodreads_support.connect(config.config_goodreads_api_key, - config.config_goodreads_api_secret, + config.config_goodreads_api_secret_e, config.config_use_goodreads) _config_int(to_save, "config_updatechannel") @@ -1792,10 +1802,25 @@ def _configuration_update_helper(): if config.config_login_type == constants.LOGIN_OAUTH: reboot_required |= _configuration_oauth_helper(to_save) + # logfile configuration reboot, message = _configuration_logfile_helper(to_save) if message: return message reboot_required |= reboot + + # security configuration + _config_checkbox(to_save, "config_password_policy") + _config_checkbox(to_save, "config_password_number") + _config_checkbox(to_save, "config_password_lower") + _config_checkbox(to_save, "config_password_upper") + _config_checkbox(to_save, "config_password_special") + if 0 < int(to_save.get("config_password_min_length", "0")) < 41: + _config_int(to_save, "config_password_min_length") + else: + return _configuration_result(_('Password length has to be between 1 and 40')) + reboot_required |= _config_int(to_save, "config_session") + reboot_required |= _config_checkbox(to_save, "config_ratelimiter") + # Rarfile Content configuration _config_string(to_save, "config_rarfile_location") if "config_rarfile_location" in to_save: @@ -1805,7 +1830,7 @@ def _configuration_update_helper(): except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - _configuration_result(_(u"Database error: %(error)s.", error=e.orig)) + _configuration_result(_("Oops! Database Error: %(error)s.", error=e.orig)) config.save() if reboot_required: @@ -1821,7 +1846,7 @@ def _configuration_result(error_flash=None, reboot=False): config.load() resp['result'] = [{'type': "danger", 'message': error_flash}] else: - resp['result'] = [{'type': "success", 'message': _(u"Calibre-Web configuration updated")}] + resp['result'] = [{'type': "success", 'message': _("Calibre-Web configuration updated")}] resp['reboot'] = reboot resp['config_upload'] = config.config_upload_formats return Response(json.dumps(resp), mimetype='application/json') @@ -1852,7 +1877,7 @@ def _db_configuration_result(error_flash=None, gdrive_error=None): gdriveError=gdrive_error, gdrivefolders=gdrivefolders, feature_support=feature_support, - title=_(u"Database Configuration"), page="dbconfig") + title=_("Database Configuration"), page="dbconfig") def _handle_new_user(to_save, content, languages, translations, kobo_support): @@ -1864,11 +1889,11 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support): content.sidebar_view |= constants.DETAIL_RANDOM content.role = constants.selected_roles(to_save) - content.password = generate_password_hash(to_save["password"]) try: if not to_save["name"] or not to_save["email"] or not to_save["password"]: log.info("Missing entries on new user") - raise Exception(_(u"Please fill out all fields!")) + raise Exception(_("Oops! Please complete all fields.")) + content.password = generate_password_hash(helper.valid_password(to_save.get("password", ""))) content.email = check_email(to_save["email"]) # Query username, if not existing, change content.name = check_username(to_save["name"]) @@ -1876,13 +1901,13 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support): content.kindle_mail = valid_email(to_save["kindle_mail"]) if config.config_public_reg and not check_valid_domain(content.email): log.info("E-mail: {} for new user is not from valid domain".format(content.email)) - raise Exception(_(u"E-mail is not from valid domain")) + raise Exception(_("E-mail is not from valid domain")) except Exception as ex: flash(str(ex), category="error") return render_title_template("user_edit.html", new_user=1, content=content, config=config, translations=translations, - languages=languages, title=_(u"Add new user"), page="newuser", + languages=languages, title=_("Add new user"), page="newuser", kobo_support=kobo_support, registered_oauth=oauth_check) try: content.allowed_tags = config.config_allowed_tags @@ -1893,17 +1918,17 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support): content.kobo_only_shelves_sync = to_save.get("kobo_only_shelves_sync", 0) == "on" ub.session.add(content) ub.session.commit() - flash(_(u"User '%(user)s' created", user=content.name), category="success") + flash(_("User '%(user)s' created", user=content.name), category="success") log.debug("User {} created".format(content.name)) return redirect(url_for('admin.admin')) except IntegrityError: ub.session.rollback() log.error("Found an existing account for {} or {}".format(content.name, content.email)) - flash(_("Found an existing account for this e-mail address or name."), category="error") + flash(_("Oops! An account already exists for this Email. or name."), category="error") except OperationalError as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") def _delete_user(content): @@ -1931,10 +1956,10 @@ def _delete_user(content): log.info("User {} deleted".format(content.name)) return _("User '%(nick)s' deleted", nick=content.name) else: - log.warning(_("Can't delete Guest User")) + # log.warning(_("Can't delete Guest User")) raise Exception(_("Can't delete Guest User")) else: - log.warning("No admin user remaining, can't delete user") + # log.warning("No admin user remaining, can't delete user") raise Exception(_("No admin user remaining, can't delete user")) @@ -1952,14 +1977,6 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support): log.warning("No admin user remaining, can't remove admin role from {}".format(content.name)) flash(_("No admin user remaining, can't remove admin role"), category="error") return redirect(url_for('admin.admin')) - if to_save.get("password"): - content.password = generate_password_hash(to_save["password"]) - anonymous = content.is_anonymous - content.role = constants.selected_roles(to_save) - if anonymous: - content.role |= constants.ROLE_ANONYMOUS - else: - content.role &= ~constants.ROLE_ANONYMOUS val = [int(k[5:]) for k in to_save if k.startswith('show_')] sidebar, __ = get_sidebar_config() @@ -1987,9 +2004,18 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support): if to_save.get("locale"): content.locale = to_save["locale"] try: + anonymous = content.is_anonymous + content.role = constants.selected_roles(to_save) + if anonymous: + content.role |= constants.ROLE_ANONYMOUS + else: + content.role &= ~constants.ROLE_ANONYMOUS + if to_save.get("password", ""): + content.password = generate_password_hash(helper.valid_password(to_save.get("password", ""))) + new_email = valid_email(to_save.get("email", content.email)) if not new_email: - raise Exception(_(u"E-Mail Address can't be empty and has to be a valid E-Mail")) + raise Exception(_("Email can't be empty and has to be a valid Email")) if new_email != content.email: content.email = check_email(new_email) # Query username, if not existing, change @@ -2011,19 +2037,19 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support): content=content, config=config, registered_oauth=oauth_check, - title=_(u"Edit User %(nick)s", nick=content.name), + title=_("Edit User %(nick)s", nick=content.name), page="edituser") try: ub.session_commit() - flash(_(u"User '%(nick)s' updated", nick=content.name), category="success") + flash(_("User '%(nick)s' updated", nick=content.name), category="success") except IntegrityError as ex: ub.session.rollback() log.error("An unknown error occurred while changing user: {}".format(str(ex))) - flash(_(u"An unknown error occurred. Please try again later."), category="error") + flash(_("Oops! An unknown error occurred. Please try again later."), category="error") except OperationalError as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") return "" diff --git a/cps/babel.py b/cps/babel.py index 4da808bc..e6c32806 100644 --- a/cps/babel.py +++ b/cps/babel.py @@ -1,7 +1,8 @@ from babel import negotiate_locale from flask_babel import Babel, Locale from babel.core import UnknownLocaleError -from flask import request, g +from flask import request +from flask_login import current_user from . import logger @@ -9,14 +10,12 @@ log = logger.create() babel = Babel() - -@babel.localeselector def get_locale(): # if a user is logged in, use the locale from the user settings - user = getattr(g, 'user', None) - if user is not None and hasattr(user, "locale"): - if user.name != 'Guest': # if the account is the guest account bypass the config lang settings - return user.locale + if current_user is not None and hasattr(current_user, "locale"): + # if the account is the guest account bypass the config lang settings + if current_user.name != 'Guest': + return current_user.locale preferred = list() if request.accept_languages: diff --git a/cps/cli.py b/cps/cli.py index 6f58dcc4..e9b97b9d 100644 --- a/cps/cli.py +++ b/cps/cli.py @@ -48,6 +48,7 @@ class CliParameter(object): 'works only in combination with keyfile') parser.add_argument('-k', metavar='path', help='path and name to SSL keyfile, e.g. /opt/test.key, ' 'works only in combination with certfile') + parser.add_argument('-o', metavar='path', help='path and name Calibre-Web logfile') parser.add_argument('-v', '--version', action='version', help='Shows version number and exits Calibre-Web', version=version_info()) parser.add_argument('-i', metavar='ip-address', help='Server IP-Address to listen') @@ -60,6 +61,7 @@ class CliParameter(object): parser.add_argument('-r', action='store_true', help='Enable public database reconnect route under /reconnect') args = parser.parse_args() + self.logpath = args.o or "" self.settings_path = args.p or os.path.join(_CONFIG_DIR, DEFAULT_SETTINGS_FILE) self.gd_path = args.g or os.path.join(_CONFIG_DIR, DEFAULT_GDRIVE_FILE) diff --git a/cps/comic.py b/cps/comic.py index 8f3a6f61..4242bb2f 100644 --- a/cps/comic.py +++ b/cps/comic.py @@ -36,6 +36,12 @@ try: from comicapi import __version__ as comic_version except ImportError: comic_version = '' + try: + from comicapi.comicarchive import load_archive_plugins + import comicapi.utils + comicapi.utils.add_rar_paths() + except ImportError: + load_archive_plugins = None except (ImportError, LookupError) as e: log.debug('Cannot import comicapi, extracting comic metadata will not work: %s', e) import zipfile @@ -46,6 +52,12 @@ except (ImportError, LookupError) as e: except (ImportError, SyntaxError) as e: log.debug('Cannot import rarfile, extracting cover files from rar files will not work: %s', e) use_rarfile = False + try: + import py7zr + use_7zip = True + except (ImportError, SyntaxError) as e: + log.debug('Cannot import py7zr, extracting cover files from CB7 files will not work: %s', e) + use_7zip = False use_comic_meta = False @@ -78,23 +90,40 @@ def _extract_cover_from_archive(original_file_extension, tmp_file_name, rar_exec if len(ext) > 1: extension = ext[1].lower() if extension in cover.COVER_EXTENSIONS: - cover_data = cf.read(name) + cover_data = cf.read([name]) break except Exception as ex: - log.debug('Rarfile failed with error: {}'.format(ex)) + log.error('Rarfile failed with error: {}'.format(ex)) + elif original_file_extension.upper() == '.CB7' and use_7zip: + cf = py7zr.SevenZipFile(tmp_file_name) + for name in cf.getnames(): + ext = os.path.splitext(name) + if len(ext) > 1: + extension = ext[1].lower() + if extension in cover.COVER_EXTENSIONS: + try: + cover_data = cf.read(name)[name].read() + except (py7zr.Bad7zFile, OSError) as ex: + log.error('7Zip file failed with error: {}'.format(ex)) + break return cover_data, extension def _extract_cover(tmp_file_name, original_file_extension, rar_executable): cover_data = extension = None if use_comic_meta: - archive = ComicArchive(tmp_file_name, rar_exe_path=rar_executable) - for index, name in enumerate(archive.getPageNameList()): + try: + archive = ComicArchive(tmp_file_name, rar_exe_path=rar_executable) + except TypeError: + archive = ComicArchive(tmp_file_name) + name_list = archive.getPageNameList if hasattr(archive, "getPageNameList") else archive.get_page_name_list + for index, name in enumerate(name_list()): ext = os.path.splitext(name) if len(ext) > 1: extension = ext[1].lower() if extension in cover.COVER_EXTENSIONS: - cover_data = archive.getPage(index) + get_page = archive.getPage if hasattr(archive, "getPageNameList") else archive.get_page + cover_data = get_page(index) break else: cover_data, extension = _extract_cover_from_archive(original_file_extension, tmp_file_name, rar_executable) @@ -103,17 +132,26 @@ def _extract_cover(tmp_file_name, original_file_extension, rar_executable): def get_comic_info(tmp_file_path, original_file_name, original_file_extension, rar_executable): if use_comic_meta: - archive = ComicArchive(tmp_file_path, rar_exe_path=rar_executable) - if archive.seemsToBeAComicArchive(): - if archive.hasMetadata(MetaDataStyle.CIX): + try: + archive = ComicArchive(tmp_file_path, rar_exe_path=rar_executable) + except TypeError: + load_archive_plugins(force=True, rar=rar_executable) + archive = ComicArchive(tmp_file_path) + if hasattr(archive, "seemsToBeAComicArchive"): + seems_archive = archive.seemsToBeAComicArchive + else: + seems_archive = archive.seems_to_be_a_comic_archive + if seems_archive(): + has_metadata = archive.hasMetadata if hasattr(archive, "hasMetadata") else archive.has_metadata + if has_metadata(MetaDataStyle.CIX): style = MetaDataStyle.CIX - elif archive.hasMetadata(MetaDataStyle.CBI): + elif has_metadata(MetaDataStyle.CBI): style = MetaDataStyle.CBI else: style = None - # if style is not None: - loaded_metadata = archive.readMetadata(style) + read_metadata = archive.readMetadata if hasattr(archive, "readMetadata") else archive.read_metadata + loaded_metadata = read_metadata(style) lang = loaded_metadata.language or "" loaded_metadata.language = isoLanguages.get_lang3(lang) @@ -138,7 +176,7 @@ def get_comic_info(tmp_file_path, original_file_name, original_file_extension, r file_path=tmp_file_path, extension=original_file_extension, title=original_file_name, - author=u'Unknown', + author='Unknown', cover=_extract_cover(tmp_file_path, original_file_extension, rar_executable), description="", tags="", diff --git a/cps/config_sql.py b/cps/config_sql.py index 61463754..4c3896eb 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -23,6 +23,10 @@ import json from sqlalchemy import Column, String, Integer, SmallInteger, Boolean, BLOB, JSON from sqlalchemy.exc import OperationalError from sqlalchemy.sql.expression import text +from sqlalchemy import exists +from cryptography.fernet import Fernet +import cryptography.exceptions +from base64 import urlsafe_b64decode try: # Compatibility with sqlalchemy 2.0 from sqlalchemy.orm import declarative_base @@ -56,7 +60,8 @@ class _Settings(_Base): mail_port = Column(Integer, default=25) mail_use_ssl = Column(SmallInteger, default=0) mail_login = Column(String, default='mail@example.com') - mail_password = Column(String, default='mypassword') + mail_password_e = Column(String) + mail_password = Column(String) mail_from = Column(String, default='automailer ') mail_size = Column(Integer, default=25*1024*1024) mail_server_type = Column(SmallInteger, default=0) @@ -69,19 +74,18 @@ class _Settings(_Base): config_certfile = Column(String) config_keyfile = Column(String) config_trustedhosts = Column(String, default='') - config_calibre_web_title = Column(String, default=u'Calibre-Web') + config_calibre_web_title = Column(String, default='Calibre-Web') config_books_per_page = Column(Integer, default=60) config_random_books = Column(Integer, default=4) config_authors_max = Column(Integer, default=0) config_read_column = Column(Integer, default=0) - config_title_regex = Column(String, default=r'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+') - # config_mature_content_tags = Column(String, default='') + config_title_regex = Column(String, default=r'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines|Le|La|Les|L\'|Un|Une)\s+') config_theme = Column(Integer, default=0) config_log_level = Column(SmallInteger, default=logger.DEFAULT_LOG_LEVEL) - config_logfile = Column(String) + config_logfile = Column(String, default=logger.DEFAULT_LOG_FILE) config_access_log = Column(SmallInteger, default=0) - config_access_logfile = Column(String) + config_access_logfile = Column(String, default=logger.DEFAULT_ACCESS_LOG) config_uploading = Column(SmallInteger, default=0) config_anonbrowse = Column(SmallInteger, default=0) @@ -107,6 +111,7 @@ class _Settings(_Base): config_use_goodreads = Column(Boolean, default=False) config_goodreads_api_key = Column(String) + config_goodreads_api_secret_e = Column(String) config_goodreads_api_secret = Column(String) config_register_email = Column(Boolean, default=False) config_login_type = Column(Integer, default=0) @@ -117,7 +122,8 @@ class _Settings(_Base): config_ldap_port = Column(SmallInteger, default=389) config_ldap_authentication = Column(SmallInteger, default=constants.LDAP_AUTH_SIMPLE) config_ldap_serv_username = Column(String, default='cn=admin,dc=example,dc=org') - config_ldap_serv_password = Column(String, default="") + config_ldap_serv_password_e = Column(String) + config_ldap_serv_password = Column(String) config_ldap_encryption = Column(SmallInteger, default=0) config_ldap_cacert_path = Column(String, default="") config_ldap_cert_path = Column(String, default="") @@ -148,24 +154,35 @@ class _Settings(_Base): schedule_generate_book_covers = Column(Boolean, default=False) schedule_generate_series_covers = Column(Boolean, default=False) schedule_reconnect = Column(Boolean, default=False) + schedule_metadata_backup = Column(Boolean, default=False) + + config_password_policy = Column(Boolean, default=True) + config_password_min_length = Column(Integer, default=8) + config_password_number = Column(Boolean, default=True) + config_password_lower = Column(Boolean, default=True) + config_password_upper = Column(Boolean, default=True) + config_password_special = Column(Boolean, default=True) + config_session = Column(Integer, default=1) + config_ratelimiter = Column(Boolean, default=True) def __repr__(self): return self.__class__.__name__ # Class holds all application specific settings in calibre-web -class _ConfigSQL(object): +class ConfigSQL(object): # pylint: disable=no-member def __init__(self): - pass + self.__dict__["dirty"] = list() - def init_config(self, session, cli): + def init_config(self, session, secret_key, cli): self._session = session self._settings = None self.db_configured = None self.config_calibre_dir = None - self.load() + self._fernet = Fernet(secret_key) self.cli = cli + self.load() change = False if self.config_converterpath == None: # pylint: disable=access-member-before-definition @@ -294,10 +311,10 @@ class _ConfigSQL(object): setattr(self, field, new_value) return True - def toDict(self): + def to_dict(self): storage = {} for k, v in self.__dict__.items(): - if k[0] != '_' and not k.endswith("password") and not k.endswith("secret") and not k == "cli": + if k[0] != '_' and not k.endswith("_e") and not k == "cli": storage[k] = v return storage @@ -311,7 +328,13 @@ class _ConfigSQL(object): column = s.__class__.__dict__.get(k) if column.default is not None: v = column.default.arg - setattr(self, k, v) + if k.endswith("_e") and v is not None: + try: + setattr(self, k, self._fernet.decrypt(v).decode()) + except cryptography.fernet.InvalidToken: + setattr(self, k, "") + else: + setattr(self, k, v) have_metadata_db = bool(self.config_calibre_dir) if have_metadata_db: @@ -319,30 +342,37 @@ class _ConfigSQL(object): have_metadata_db = os.path.isfile(db_file) self.db_configured = have_metadata_db constants.EXTENSIONS_UPLOAD = [x.lstrip().rstrip().lower() for x in self.config_upload_formats.split(',')] + from . import cli_param if os.environ.get('FLASK_DEBUG'): logfile = logger.setup(logger.LOG_TO_STDOUT, logger.logging.DEBUG) else: # pylint: disable=access-member-before-definition - logfile = logger.setup(self.config_logfile, self.config_log_level) - if logfile != self.config_logfile: - log.warning("Log path %s not valid, falling back to default", self.config_logfile) + logfile = logger.setup(cli_param.logpath or self.config_logfile, self.config_log_level) + if logfile != os.path.abspath(self.config_logfile): + if logfile != os.path.abspath(cli_param.logpath): + log.warning("Log path %s not valid, falling back to default", self.config_logfile) self.config_logfile = logfile + s.config_logfile = logfile self._session.merge(s) try: self._session.commit() except OperationalError as e: log.error('Database error: %s', e) self._session.rollback() + self.__dict__["dirty"] = list() def save(self): """Apply all configuration values to the underlying storage.""" s = self._read_from_storage() # type: _Settings - for k, v in self.__dict__.items(): + for k in self.dirty: if k[0] == '_': continue if hasattr(s, k): - setattr(s, k, v) + if k.endswith("_e"): + setattr(s, k, self._fernet.encrypt(self.__dict__[k].encode())) + else: + setattr(s, k, self.__dict__[k]) log.debug("_ConfigSQL updating storage") self._session.merge(s) @@ -358,7 +388,6 @@ class _ConfigSQL(object): log.error(error) log.warning("invalidating configuration") self.db_configured = False - # self.config_calibre_dir = None self.save() def store_calibre_uuid(self, calibre_db, Library_table): @@ -370,8 +399,40 @@ class _ConfigSQL(object): except AttributeError: pass + def __setattr__(self, attr_name, attr_value): + super().__setattr__(attr_name, attr_value) + self.__dict__["dirty"].append(attr_name) -def _migrate_table(session, orm_class): + +def _encrypt_fields(session, secret_key): + try: + session.query(exists().where(_Settings.mail_password_e)).scalar() + except OperationalError: + with session.bind.connect() as conn: + conn.execute(text("ALTER TABLE settings ADD column 'mail_password_e' String")) + conn.execute(text("ALTER TABLE settings ADD column 'config_goodreads_api_secret_e' String")) + conn.execute(text("ALTER TABLE settings ADD column 'config_ldap_serv_password_e' String")) + session.commit() + crypter = Fernet(secret_key) + settings = session.query(_Settings.mail_password, _Settings.config_goodreads_api_secret, + _Settings.config_ldap_serv_password).first() + if settings.mail_password: + session.query(_Settings).update( + {_Settings.mail_password_e: crypter.encrypt(settings.mail_password.encode())}) + if settings.config_goodreads_api_secret: + session.query(_Settings).update( + {_Settings.config_goodreads_api_secret_e: + crypter.encrypt(settings.config_goodreads_api_secret.encode())}) + if settings.config_ldap_serv_password: + session.query(_Settings).update( + {_Settings.config_ldap_serv_password_e: + crypter.encrypt(settings.config_ldap_serv_password.encode())}) + session.commit() + + +def _migrate_table(session, orm_class, secret_key=None): + if secret_key: + _encrypt_fields(session, secret_key) changed = False for column_name, column in orm_class.__dict__.items(): @@ -447,22 +508,18 @@ def autodetect_kepubify_binary(): return "" -def _migrate_database(session): +def _migrate_database(session, secret_key): # make sure the table is created, if it does not exist _Base.metadata.create_all(session.bind) - _migrate_table(session, _Settings) + _migrate_table(session, _Settings, secret_key) _migrate_table(session, _Flask_Settings) -def load_configuration(conf, session, cli): - _migrate_database(session) - +def load_configuration(session, secret_key): + _migrate_database(session, secret_key) if not session.query(_Settings).count(): session.add(_Settings()) session.commit() - # conf = _ConfigSQL() - conf.init_config(session, cli) - # return conf def get_flask_session_key(_session): @@ -472,3 +529,25 @@ def get_flask_session_key(_session): _session.add(flask_settings) _session.commit() return flask_settings.flask_session_key + + +def get_encryption_key(key_path): + key_file = os.path.join(key_path, ".key") + generate = True + error = "" + if os.path.exists(key_file) and os.path.getsize(key_file) > 32: + with open(key_file, "rb") as f: + key = f.read() + try: + urlsafe_b64decode(key) + generate = False + except ValueError: + pass + if generate: + key = Fernet.generate_key() + try: + with open(key_file, "wb") as f: + f.write(key) + except PermissionError as e: + error = e + return key, error diff --git a/cps/constants.py b/cps/constants.py index d0076067..87ce6f59 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -34,6 +34,8 @@ UPDATER_AVAILABLE = True # Base dir is parent of current file, necessary if called from different folder BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)) +# if executable file the files should be placed in the parent dir (parallel to the exe file) + STATIC_DIR = os.path.join(BASE_DIR, 'cps', 'static') TEMPLATES_DIR = os.path.join(BASE_DIR, 'cps', 'templates') TRANSLATIONS_DIR = os.path.join(BASE_DIR, 'cps', 'translations') @@ -49,6 +51,9 @@ if HOME_CONFIG: CONFIG_DIR = os.environ.get('CALIBRE_DBPATH', home_dir) else: CONFIG_DIR = os.environ.get('CALIBRE_DBPATH', BASE_DIR) + if getattr(sys, 'frozen', False): + CONFIG_DIR = os.path.abspath(os.path.join(CONFIG_DIR, os.pardir)) + DEFAULT_SETTINGS_FILE = "app.db" DEFAULT_GDRIVE_FILE = "gdrive.db" @@ -144,10 +149,10 @@ del env_CALIBRE_PORT EXTENSIONS_AUDIO = {'mp3', 'mp4', 'ogg', 'opus', 'wav', 'flac', 'm4a', 'm4b'} EXTENSIONS_CONVERT_FROM = ['pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', - 'txt', 'htmlz', 'rtf', 'odt', 'cbz', 'cbr'] + 'txt', 'htmlz', 'rtf', 'odt', 'cbz', 'cbr', 'prc'] EXTENSIONS_CONVERT_TO = ['pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'htmlz', 'rtf', 'odt'] -EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'kepub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', +EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'kepub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'cb7', 'djvu', 'djv', 'prc', 'doc', 'docx', 'fb2', 'html', 'rtf', 'lit', 'odt', 'mp3', 'mp4', 'ogg', 'opus', 'wav', 'flac', 'm4a', 'm4b'} @@ -163,7 +168,8 @@ def selected_roles(dictionary): BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' 'series_id, languages, publisher, pubdate, identifiers') -STABLE_VERSION = {'version': '0.6.19'} +# python build process likes to have x.y.zbw -> b for beta and w a counting number +STABLE_VERSION = {'version': '0.6.22 Beta'} NIGHTLY_VERSION = dict() NIGHTLY_VERSION[0] = '$Format:%H$' diff --git a/cps/db.py b/cps/db.py index aaedcd06..ceb692ec 100644 --- a/cps/db.py +++ b/cps/db.py @@ -111,66 +111,73 @@ class Identifiers(Base): def format_type(self): format_type = self.type.lower() if format_type == 'amazon': - return u"Amazon" + return "Amazon" elif format_type.startswith("amazon_"): - return u"Amazon.{0}".format(format_type[7:]) + return "Amazon.{0}".format(format_type[7:]) elif format_type == "isbn": - return u"ISBN" + return "ISBN" elif format_type == "doi": - return u"DOI" + return "DOI" elif format_type == "douban": - return u"Douban" + return "Douban" elif format_type == "goodreads": - return u"Goodreads" + return "Goodreads" elif format_type == "babelio": - return u"Babelio" + return "Babelio" elif format_type == "google": - return u"Google Books" + return "Google Books" elif format_type == "kobo": - return u"Kobo" + return "Kobo" elif format_type == "litres": - return u"ЛитРес" + return "ЛитРес" elif format_type == "issn": - return u"ISSN" + return "ISSN" elif format_type == "isfdb": - return u"ISFDB" + return "ISFDB" if format_type == "lubimyczytac": - return u"Lubimyczytac" + return "Lubimyczytac" + if format_type == "databazeknih": + return "Databáze knih" else: return self.type def __repr__(self): format_type = self.type.lower() if format_type == "amazon" or format_type == "asin": - return u"https://amazon.com/dp/{0}".format(self.val) + return "https://amazon.com/dp/{0}".format(self.val) elif format_type.startswith('amazon_'): - return u"https://amazon.{0}/dp/{1}".format(format_type[7:], self.val) + return "https://amazon.{0}/dp/{1}".format(format_type[7:], self.val) elif format_type == "isbn": - return u"https://www.worldcat.org/isbn/{0}".format(self.val) + return "https://www.worldcat.org/isbn/{0}".format(self.val) elif format_type == "doi": - return u"https://dx.doi.org/{0}".format(self.val) + return "https://dx.doi.org/{0}".format(self.val) elif format_type == "goodreads": - return u"https://www.goodreads.com/book/show/{0}".format(self.val) + return "https://www.goodreads.com/book/show/{0}".format(self.val) elif format_type == "babelio": - return u"https://www.babelio.com/livres/titre/{0}".format(self.val) + return "https://www.babelio.com/livres/titre/{0}".format(self.val) elif format_type == "douban": - return u"https://book.douban.com/subject/{0}".format(self.val) + return "https://book.douban.com/subject/{0}".format(self.val) elif format_type == "google": - return u"https://books.google.com/books?id={0}".format(self.val) + return "https://books.google.com/books?id={0}".format(self.val) elif format_type == "kobo": - return u"https://www.kobo.com/ebook/{0}".format(self.val) + return "https://www.kobo.com/ebook/{0}".format(self.val) elif format_type == "lubimyczytac": - return u"https://lubimyczytac.pl/ksiazka/{0}/ksiazka".format(self.val) + return "https://lubimyczytac.pl/ksiazka/{0}/ksiazka".format(self.val) elif format_type == "litres": - return u"https://www.litres.ru/{0}".format(self.val) + return "https://www.litres.ru/{0}".format(self.val) elif format_type == "issn": - return u"https://portal.issn.org/resource/ISSN/{0}".format(self.val) + return "https://portal.issn.org/resource/ISSN/{0}".format(self.val) elif format_type == "isfdb": - return u"http://www.isfdb.org/cgi-bin/pl.cgi?{0}".format(self.val) + return "http://www.isfdb.org/cgi-bin/pl.cgi?{0}".format(self.val) + elif format_type == "databazeknih": + return "https://www.databazeknih.cz/knihy/{0}".format(self.val) elif self.val.lower().startswith("javascript:"): return quote(self.val) + elif self.val.lower().startswith("data:"): + link , __, __ = str.partition(self.val, ",") + return link else: - return u"{0}".format(self.val) + return "{0}".format(self.val) class Comments(Base): @@ -188,7 +195,7 @@ class Comments(Base): return self.text def __repr__(self): - return u"".format(self.text) + return "".format(self.text) class Tags(Base): @@ -203,8 +210,11 @@ class Tags(Base): def get(self): return self.name + def __eq__(self, other): + return self.name == other + def __repr__(self): - return u"".format(self.name) + return "".format(self.name) class Authors(Base): @@ -215,7 +225,7 @@ class Authors(Base): sort = Column(String(collation='NOCASE')) link = Column(String, nullable=False, default="") - def __init__(self, name, sort, link): + def __init__(self, name, sort, link=""): self.name = name self.sort = sort self.link = link @@ -223,8 +233,11 @@ class Authors(Base): def get(self): return self.name + def __eq__(self, other): + return self.name == other + def __repr__(self): - return u"".format(self.name, self.sort, self.link) + return "".format(self.name, self.sort, self.link) class Series(Base): @@ -241,8 +254,11 @@ class Series(Base): def get(self): return self.name + def __eq__(self, other): + return self.name == other + def __repr__(self): - return u"".format(self.name, self.sort) + return "".format(self.name, self.sort) class Ratings(Base): @@ -257,8 +273,11 @@ class Ratings(Base): def get(self): return self.rating + def __eq__(self, other): + return self.rating == other + def __repr__(self): - return u"".format(self.rating) + return "".format(self.rating) class Languages(Base): @@ -271,13 +290,16 @@ class Languages(Base): self.lang_code = lang_code def get(self): - if self.language_name: + if hasattr(self, "language_name"): return self.language_name else: return self.lang_code + def __eq__(self, other): + return self.lang_code == other + def __repr__(self): - return u"".format(self.lang_code) + return "".format(self.lang_code) class Publishers(Base): @@ -294,8 +316,11 @@ class Publishers(Base): def get(self): return self.name + def __eq__(self, other): + return self.name == other + def __repr__(self): - return u"".format(self.name, self.sort) + return "".format(self.name, self.sort) class Data(Base): @@ -319,7 +344,7 @@ class Data(Base): return self.name def __repr__(self): - return u"".format(self.book, self.format, self.uncompressed_size, self.name) + return "".format(self.book, self.format, self.uncompressed_size, self.name) class Metadata_Dirtied(Base): @@ -373,7 +398,7 @@ class Books(Base): self.has_cover = (has_cover != None) def __repr__(self): - return u"".format(self.title, self.sort, self.author_sort, + return "".format(self.title, self.sort, self.author_sort, self.timestamp, self.pubdate, self.series_index, self.last_modified, self.path, self.has_cover) @@ -404,7 +429,7 @@ class CustomColumns(Base): content['table'] = "custom_column_" + str(self.id) content['column'] = "value" content['datatype'] = self.datatype - content['is_multiple'] = None if not self.is_multiple else self.is_multiple + content['is_multiple'] = None if not self.is_multiple else "|" content['kind'] = "field" content['name'] = self.name content['search_terms'] = ['#' + self.label] @@ -418,9 +443,12 @@ class CustomColumns(Base): content['is_csp'] = False content['is_editable'] = self.editable content['rec_index'] = sequence + 22 # toDo why ?? - content['#value#'] = value + if isinstance(value, datetime): + content['#value#'] = {"__class__": "datetime.datetime", "__value__": value.strftime("%Y-%m-%dT%H:%M:%S+00:00")} + else: + content['#value#'] = value content['#extra#'] = extra - content['is_multiple2'] = {} + content['is_multiple2'] = {} if not self.is_multiple else {"cache_to_list": "|", "ui_to_list": ",", "list_to_ui": ", "} return json.dumps(content, ensure_ascii=False) @@ -635,7 +663,7 @@ class CalibreDB: cls.session_factory = scoped_session(sessionmaker(autocommit=False, autoflush=True, - bind=cls.engine)) + bind=cls.engine, future=True)) for inst in cls.instances: inst.init_session() @@ -822,8 +850,6 @@ class CalibreDB: # Orders all Authors in the list according to authors sort def order_authors(self, entries, list_return=False, combined=False): - # entries_copy = copy.deepcopy(entries) - # entries_copy =[] for entry in entries: if combined: sort_authors = entry.Books.author_sort.split('&') @@ -988,7 +1014,12 @@ class CalibreDB: title = title[len(prep):] + ', ' + prep return title.strip() - conn = conn or self.session.connection().connection.connection + try: + # sqlalchemy <1.4.24 + conn = conn or self.session.connection().connection.driver_connection + except AttributeError: + # sqlalchemy >1.4.24 and sqlalchemy 2.0 + conn = conn or self.session.connection().connection.connection try: conn.create_function("title_sort", 1, _title_sort) except sqliteOperationalError: diff --git a/cps/debug_info.py b/cps/debug_info.py index 6cb30edb..82ca8ca6 100644 --- a/cps/debug_info.py +++ b/cps/debug_info.py @@ -65,7 +65,7 @@ def send_debug(): file_list.remove(element) memory_zip = BytesIO() with zipfile.ZipFile(memory_zip, 'w', compression=zipfile.ZIP_DEFLATED) as zf: - zf.writestr('settings.txt', json.dumps(config.toDict(), sort_keys=True, indent=2)) + zf.writestr('settings.txt', json.dumps(config.to_dict(), sort_keys=True, indent=2)) zf.writestr('libs.txt', json.dumps(collect_stats(), sort_keys=True, indent=2, cls=lazyEncoder)) for fp in file_list: zf.write(fp, os.path.basename(fp)) diff --git a/cps/dep_check.py b/cps/dep_check.py index bc015756..34d0e24b 100644 --- a/cps/dep_check.py +++ b/cps/dep_check.py @@ -61,7 +61,7 @@ def dependency_check(optional=False): deps = load_dependencies(optional) for dep in deps: try: - dep_version_int = [int(x) for x in dep[0].split('.')] + dep_version_int = [int(x) if x.isnumeric() else 0 for x in dep[0].split('.')] low_check = [int(x) for x in dep[3].split('.')] high_check = [int(x) for x in dep[5].split('.')] except AttributeError: diff --git a/cps/editbooks.py b/cps/editbooks.py old mode 100755 new mode 100644 index 3580d667..723f72a3 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -25,21 +25,31 @@ from datetime import datetime import json from shutil import copyfile from uuid import uuid4 -from markupsafe import escape # dependency of flask +from markupsafe import escape, Markup # dependency of flask from functools import wraps try: - from lxml.html.clean import clean_html + from bleach import clean_text as clean_html + BLEACH = True except ImportError: - clean_html = None + try: + from nh3 import clean as clean_html + BLEACH = False + except ImportError: + try: + from lxml.html.clean import clean_html + BLEACH = False + except ImportError: + clean_html = None -from flask import Blueprint, request, flash, redirect, url_for, abort, Markup, Response +from flask import Blueprint, request, flash, redirect, url_for, abort, Response from flask_babel import gettext as _ from flask_babel import lazy_gettext as N_ from flask_babel import get_locale from flask_login import current_user, login_required from sqlalchemy.exc import OperationalError, IntegrityError, InterfaceError from sqlalchemy.orm.exc import StaleDataError +from sqlalchemy.sql.expression import func from . import constants, logger, isoLanguages, gdriveutils, uploader, helper, kobo_sync_status from . import config, ub, db, calibre_db @@ -107,7 +117,7 @@ def edit_book(book_id): book = calibre_db.get_filtered_book(book_id, allow_show_archived=True) # Book not found if not book: - flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), + flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), category="error") return redirect(url_for("web.index")) @@ -151,7 +161,7 @@ def edit_book(book_id): if to_save.get("cover_url", None): if not current_user.role_upload(): edit_error = True - flash(_(u"User has no rights to upload cover"), category="error") + flash(_("User has no rights to upload cover"), category="error") if to_save["cover_url"].endswith('/static/generic_cover.jpg'): book.has_cover = 0 else: @@ -226,7 +236,7 @@ def edit_book(book_id): except (OperationalError, IntegrityError, StaleDataError, InterfaceError) as e: log.error_or_exception("Database error: {}".format(e)) calibre_db.session.rollback() - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig if hasattr(e, "orig") else e), category="error") return redirect(url_for('web.show_book', book_id=book.id)) except Exception as ex: log.error_or_exception(ex) @@ -288,7 +298,7 @@ def upload(): if error: flash(error, category="error") link = '{}'.format(url_for('web.show_book', book_id=book_id), escape(title)) - upload_text = N_(u"File %(file)s uploaded", file=link) + upload_text = N_("File %(file)s uploaded", file=link) WorkerThread.add(current_user.name, TaskUpload(upload_text, escape(title))) helper.add_book_to_thumbnail_cache(book_id) @@ -302,7 +312,8 @@ def upload(): except (OperationalError, IntegrityError, StaleDataError) as e: calibre_db.session.rollback() log.error_or_exception("Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig if hasattr(e, "orig") else e), + category="error") return Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') @@ -315,7 +326,7 @@ def convert_bookformat(book_id): book_format_to = request.form.get('book_format_to', None) if (book_format_from is None) or (book_format_to is None): - flash(_(u"Source or destination format for conversion missing"), category="error") + flash(_("Source or destination format for conversion missing"), category="error") return redirect(url_for('edit-book.show_edit_book', book_id=book_id)) log.info('converting: book id: %s from: %s to: %s', book_id, book_format_from, book_format_to) @@ -323,11 +334,11 @@ def convert_bookformat(book_id): book_format_to.upper(), current_user.name) if rtn is None: - flash(_(u"Book successfully queued for converting to %(book_format)s", + flash(_("Book successfully queued for converting to %(book_format)s", book_format=book_format_to), category="success") else: - flash(_(u"There was an error converting this book: %(res)s", res=rtn), category="error") + flash(_("There was an error converting this book: %(res)s", res=rtn), category="error") return redirect(url_for('edit-book.show_edit_book', book_id=book_id)) @@ -451,7 +462,7 @@ def edit_list_book(param): calibre_db.session.rollback() log.error_or_exception("Database error: {}".format(e)) ret = Response(json.dumps({'success': False, - 'msg': 'Database error: {}'.format(e.orig)}), + 'msg': 'Database error: {}'.format(e.orig if hasattr(e, "orig") else e)}), mimetype='application/json') return ret @@ -469,7 +480,7 @@ def get_sorted_entry(field, bookid): if field == 'sort': return json.dumps({'sort': book.title}) if field == 'author_sort': - return json.dumps({'author_sort': book.author}) + return json.dumps({'authors': " & ".join([a.name for a in calibre_db.order_authors([book])])}) return "" @@ -563,7 +574,7 @@ def table_xchange_author_title(): calibre_db.session.commit() except (OperationalError, IntegrityError, StaleDataError) as e: calibre_db.session.rollback() - log.error_or_exception("Database error: %s", e) + log.error_or_exception("Database error: {}".format(e)) return json.dumps({'success': False}) if config.config_use_google_drive: @@ -573,9 +584,9 @@ def table_xchange_author_title(): def merge_metadata(to_save, meta): - if to_save.get('author_name', "") == _(u'Unknown'): + if to_save.get('author_name', "") == _('Unknown'): to_save['author_name'] = '' - if to_save.get('book_title', "") == _(u'Unknown'): + if to_save.get('book_title', "") == _('Unknown'): to_save['book_title'] = '' for s_field, m_field in [ ('tags', 'tags'), ('author_name', 'author'), ('series', 'series'), @@ -597,6 +608,8 @@ def identifier_list(to_save, book): val_key = id_val_prefix + type_key[len(id_type_prefix):] if val_key not in to_save.keys(): continue + if to_save[val_key].startswith("data:"): + to_save[val_key], __, __ = str.partition(to_save[val_key], ",") result.append(db.Identifiers(to_save[val_key], type_value, book.id)) return result @@ -611,7 +624,7 @@ def prepare_authors(authr): # we have all author names now if input_authors == ['']: - input_authors = [_(u'Unknown')] # prevent empty Author + input_authors = [_('Unknown')] # prevent empty Author renamed = list() for in_aut in input_authors: @@ -628,11 +641,11 @@ def prepare_authors(authr): def prepare_authors_on_upload(title, authr): - if title != _(u'Unknown') and authr != _(u'Unknown'): + if title != _('Unknown') and authr != _('Unknown'): entry = calibre_db.check_exists_book(authr, title) if entry: log.info("Uploaded book probably exists in library") - flash(_(u"Uploaded book probably exists in the library, consider to change before upload new: ") + flash(_("Uploaded book probably exists in the library, consider to change before upload new: ") + Markup(render_title_template('book_exists_flash.html', entry=entry)), category="warning") input_authors, renamed = prepare_authors(authr) @@ -687,7 +700,7 @@ def create_book_on_upload(modify_date, meta): modify_date |= edit_book_languages(meta.languages, db_book, upload_mode=True, invalid=invalid) if invalid: for lang in invalid: - flash(_(u"'%(langname)s' is not a valid language", langname=lang), category="warning") + flash(_("'%(langname)s' is not a valid language", langname=lang), category="warning") # handle tags modify_date |= edit_book_tags(meta.tags, db_book) @@ -737,7 +750,7 @@ def file_handling_on_upload(requested_file): meta = uploader.upload(requested_file, config.config_rarfile_location) except (IOError, OSError): log.error("File %s could not saved to temp dir", requested_file.filename) - flash(_(u"File %(filename)s could not saved to temp dir", + flash(_("File %(filename)s could not saved to temp dir", filename=requested_file.filename), category="error") return None, Response(json.dumps({"location": url_for("web.index")}), mimetype='application/json') return meta, None @@ -757,7 +770,7 @@ def move_coverfile(meta, db_book): os.unlink(meta.cover) except OSError as e: log.error("Failed to move cover file %s: %s", new_cover_path, e) - flash(_(u"Failed to Move Cover File %(file)s: %(error)s", file=new_cover_path, + flash(_("Failed to Move Cover File %(file)s: %(error)s", file=new_cover_path, error=e), category="error") @@ -771,7 +784,7 @@ def delete_whole_book(book_id, book): # check if only this book links to: # author, language, series, tags, custom columns - modify_database_object([u''], book.authors, db.Authors, calibre_db.session, 'author') + modify_database_object([''], book.authors, db.Authors, calibre_db.session, 'author') modify_database_object([u''], book.tags, db.Tags, calibre_db.session, 'tags') modify_database_object([u''], book.series, db.Series, calibre_db.session, 'series') modify_database_object([u''], book.languages, db.Languages, calibre_db.session, 'languages') @@ -892,7 +905,7 @@ def render_edit_book(book_id): cc = calibre_db.session.query(db.CustomColumns).filter(db.CustomColumns.datatype.notin_(db.cc_exceptions)).all() book = calibre_db.get_filtered_book(book_id, allow_show_archived=True) if not book: - flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), + flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), category="error") return redirect(url_for("web.index")) @@ -927,7 +940,7 @@ def render_edit_book(book_id): if kepub_possible: allowed_conversion_formats.append('kepub') return render_title_template('book_edit.html', book=book, authors=author_names, cc=cc, - title=_(u"edit metadata"), page="editbook", + title=_("edit metadata"), page="editbook", conversion_formats=allowed_conversion_formats, config=config, source_formats=valid_source_formats) @@ -988,7 +1001,10 @@ def edit_book_series_index(series_index, book): def edit_book_comments(comments, book): modify_date = False if comments: - comments = clean_html(comments) + if BLEACH: + comments = clean_html(comments, tags=None, attributes=None) + else: + comments = clean_html(comments) if len(book.comments): if book.comments[0].text != comments: book.comments[0].text = comments @@ -1012,7 +1028,7 @@ def edit_book_languages(languages, book, upload_mode=False, invalid=None): if isinstance(invalid, list): invalid.append(lang) else: - raise ValueError(_(u"'%(langname)s' is not a valid language", langname=lang)) + raise ValueError(_("'%(langname)s' is not a valid language", langname=lang)) # ToDo: Not working correct if upload_mode and len(input_l) == 1: # If the language of the file is excluded from the users view, it's not imported, to allow the user to view @@ -1123,9 +1139,10 @@ def edit_cc_data(book_id, book, to_save, cc): cc_db_value = None if to_save[cc_string].strip(): if c.datatype in ['int', 'bool', 'float', "datetime", "comments"]: - changed, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string) + change, to_save = edit_cc_data_value(book_id, book, c, to_save, cc_db_value, cc_string) else: - changed, to_save = edit_cc_data_string(book, c, to_save, cc_db_value, cc_string) + change, to_save = edit_cc_data_string(book, c, to_save, cc_db_value, cc_string) + changed |= change else: if cc_db_value is not None: # remove old cc_val @@ -1154,7 +1171,7 @@ def upload_single_file(file_request, book, book_id): # check for empty request if requested_file.filename != '': if not current_user.role_upload(): - flash(_(u"User has no rights to upload additional file formats"), category="error") + flash(_("User has no rights to upload additional file formats"), category="error") return False if '.' in requested_file.filename: file_ext = requested_file.filename.rsplit('.', 1)[-1].lower() @@ -1175,12 +1192,12 @@ def upload_single_file(file_request, book, book_id): try: os.makedirs(filepath) except OSError: - flash(_(u"Failed to create path %(path)s (Permission denied).", path=filepath), category="error") + flash(_("Failed to create path %(path)s (Permission denied).", path=filepath), category="error") return False try: requested_file.save(saved_filename) except OSError: - flash(_(u"Failed to store file %(file)s.", file=saved_filename), category="error") + flash(_("Failed to store file %(file)s.", file=saved_filename), category="error") return False file_size = os.path.getsize(saved_filename) @@ -1198,17 +1215,18 @@ def upload_single_file(file_request, book, book_id): except (OperationalError, IntegrityError, StaleDataError) as e: calibre_db.session.rollback() log.error_or_exception("Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig if hasattr(e, "orig") else e), + category="error") return False # return redirect(url_for('web.show_book', book_id=book.id)) # Queue uploader info link = '{}'.format(url_for('web.show_book', book_id=book.id), escape(book.title)) - upload_text = N_(u"File format %(ext)s added to %(book)s", ext=file_ext.upper(), book=link) + upload_text = N_("File format %(ext)s added to %(book)s", ext=file_ext.upper(), book=link) WorkerThread.add(current_user.name, TaskUpload(upload_text, escape(book.title))) return uploader.process( saved_filename, *os.path.splitext(requested_file.filename), - rarExecutable=config.config_rarfile_location) + rar_executable=config.config_rarfile_location) return None @@ -1218,7 +1236,7 @@ def upload_cover(cover_request, book): # check for empty request if requested_file.filename != '': if not current_user.role_upload(): - flash(_(u"User has no rights to upload cover"), category="error") + flash(_("User has no rights to upload cover"), category="error") return False ret, message = helper.save_cover(requested_file, book.path) if ret is True: @@ -1242,18 +1260,18 @@ def handle_title_on_edit(book, book_title): def handle_author_on_edit(book, author_name, update_stored=True): + change = False # handle author(s) input_authors, renamed = prepare_authors(author_name) - change = modify_database_object(input_authors, book.authors, db.Authors, calibre_db.session, 'author') - + # change |= modify_database_object(input_authors, book.authors, db.Authors, calibre_db.session, 'author') # Search for each author if author is in database, if not, author name and sorted author name is generated new # everything then is assembled for sorted author field in database sort_authors_list = list() for inp in input_authors: stored_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == inp).first() if not stored_author: - stored_author = helper.get_sorted_author(inp) + stored_author = helper.get_sorted_author(inp.replace('|', ',')) else: stored_author = stored_author.sort sort_authors_list.append(helper.get_sorted_author(stored_author)) @@ -1261,6 +1279,9 @@ def handle_author_on_edit(book, author_name, update_stored=True): if book.author_sort != sort_authors and update_stored: book.author_sort = sort_authors change = True + + change |= modify_database_object(input_authors, book.authors, db.Authors, calibre_db.session, 'author') + return input_authors, change, renamed @@ -1268,14 +1289,15 @@ def search_objects_remove(db_book_object, db_type, input_elements): del_elements = [] for c_elements in db_book_object: found = False - if db_type == 'languages': - type_elements = c_elements.lang_code - elif db_type == 'custom': + #if db_type == 'languages': + # type_elements = c_elements.lang_code + if db_type == 'custom': type_elements = c_elements.value else: - type_elements = c_elements.name + # type_elements = c_elements.name + type_elements = c_elements for inp_element in input_elements: - if inp_element.lower() == type_elements.lower(): + if type_elements == inp_element: found = True break # if the element was not found in the new list, add it to remove list @@ -1289,13 +1311,11 @@ def search_objects_add(db_book_object, db_type, input_elements): for inp_element in input_elements: found = False for c_elements in db_book_object: - if db_type == 'languages': - type_elements = c_elements.lang_code - elif db_type == 'custom': + if db_type == 'custom': type_elements = c_elements.value else: - type_elements = c_elements.name - if inp_element == type_elements: + type_elements = c_elements + if type_elements == inp_element: found = True break if not found: @@ -1311,6 +1331,7 @@ def remove_objects(db_book_object, db_session, del_elements): changed = True if len(del_element.books) == 0: db_session.delete(del_element) + db_session.flush() return changed @@ -1324,27 +1345,34 @@ def add_objects(db_book_object, db_object, db_session, db_type, add_elements): db_filter = db_object.name for add_element in add_elements: # check if an element with that name exists - db_element = db_session.query(db_object).filter(db_filter == add_element).first() + changed = True + # db_session.query(db.Tags).filter((func.lower(db.Tags.name).ilike("GênOt"))).all() + db_element = db_session.query(db_object).filter((func.lower(db_filter).ilike(add_element))).first() + # db_element = db_session.query(db_object).filter(func.lower(db_filter) == add_element.lower()).first() # if no element is found add it - if db_type == 'author': - new_element = db_object(add_element, helper.get_sorted_author(add_element.replace('|', ',')), "") - elif db_type == 'series': - new_element = db_object(add_element, add_element) - elif db_type == 'custom': - new_element = db_object(value=add_element) - elif db_type == 'publisher': - 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: - changed = True + if db_type == 'author': + new_element = db_object(add_element, helper.get_sorted_author(add_element.replace('|', ','))) + elif db_type == 'series': + new_element = db_object(add_element, add_element) + elif db_type == 'custom': + new_element = db_object(value=add_element) + elif db_type == 'publisher': + new_element = db_object(add_element, None) + else: # db_type should be tag or language + new_element = db_object(add_element) db_session.add(new_element) db_book_object.append(new_element) else: - db_element = create_objects_for_addition(db_element, add_element, db_type) + db_no_case = db_session.query(db_object).filter(db_filter == add_element).first() + if db_no_case: + # check for new case of element + db_element = create_objects_for_addition(db_element, add_element, db_type) + else: + db_element = create_objects_for_addition(db_element, add_element, db_type) # add element to book - changed = True db_book_object.append(db_element) + return changed @@ -1379,13 +1407,24 @@ def modify_database_object(input_elements, db_book_object, db_object, db_session 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 != ''] - # we have all input element (authors, series, tags) names now + + changed = False + # If elements are renamed (upper lower case), rename it + for rec_a, rec_b in zip(db_book_object, input_elements): + if db_type == "custom": + if rec_a.value.casefold() == rec_b.casefold() and rec_a.value != rec_b: + create_objects_for_addition(rec_a, rec_b, db_type) + else: + if rec_a.get().casefold() == rec_b.casefold() and rec_a.get() != rec_b: + create_objects_for_addition(rec_a, rec_b, db_type) + # we have all input element (authors, series, tags) names now # 1. search for elements to remove del_elements = search_objects_remove(db_book_object, db_type, input_elements) # 2. search for elements that need to be added add_elements = search_objects_add(db_book_object, db_type, input_elements) + # if there are elements to remove, we remove them now - changed = remove_objects(db_book_object, db_session, del_elements) + changed |= remove_objects(db_book_object, db_session, del_elements) # if there are elements to add, we add them now! if len(add_elements) > 0: changed |= add_objects(db_book_object, db_object, db_session, db_type, add_elements) diff --git a/cps/epub.py b/cps/epub.py index 00ce907b..50adba59 100644 --- a/cps/epub.py +++ b/cps/epub.py @@ -21,25 +21,54 @@ import zipfile from lxml import etree from . import isoLanguages, cover +from . import config, logger from .helper import split_authors from .constants import BookMeta +log = logger.create() def _extract_cover(zip_file, cover_file, cover_path, tmp_file_name): if cover_file is None: return None - else: - cf = extension = None - zip_cover_path = os.path.join(cover_path, cover_file).replace('\\', '/') - prefix = os.path.splitext(tmp_file_name)[0] - tmp_cover_name = prefix + '.' + os.path.basename(zip_cover_path) - ext = os.path.splitext(tmp_cover_name) - if len(ext) > 1: - extension = ext[1].lower() - if extension in cover.COVER_EXTENSIONS: - cf = zip_file.read(zip_cover_path) - return cover.cover_processing(tmp_file_name, cf, extension) + cf = extension = None + zip_cover_path = os.path.join(cover_path, cover_file).replace('\\', '/') + + prefix = os.path.splitext(tmp_file_name)[0] + tmp_cover_name = prefix + '.' + os.path.basename(zip_cover_path) + ext = os.path.splitext(tmp_cover_name) + if len(ext) > 1: + extension = ext[1].lower() + if extension in cover.COVER_EXTENSIONS: + cf = zip_file.read(zip_cover_path) + return cover.cover_processing(tmp_file_name, cf, extension) + +def get_epub_layout(book, book_data): + ns = { + 'n': 'urn:oasis:names:tc:opendocument:xmlns:container', + 'pkg': 'http://www.idpf.org/2007/opf', + } + file_path = os.path.normpath(os.path.join(config.config_calibre_dir, book.path, book_data.name + "." + book_data.format.lower())) + + try: + epubZip = zipfile.ZipFile(file_path) + txt = epubZip.read('META-INF/container.xml') + tree = etree.fromstring(txt) + cfname = tree.xpath('n:rootfiles/n:rootfile/@full-path', namespaces=ns)[0] + cf = epubZip.read(cfname) + + tree = etree.fromstring(cf) + p = tree.xpath('/pkg:package/pkg:metadata', namespaces=ns)[0] + + layout = p.xpath('pkg:meta[@property="rendition:layout"]/text()', namespaces=ns) + except (etree.XMLSyntaxError, KeyError, IndexError) as e: + log.error("Could not parse epub metadata of book {} during kobo sync: {}".format(book.id, e)) + layout = [] + + if len(layout) == 0: + return None + else: + return layout[0] def get_epub_info(tmp_file_path, original_file_name, original_file_extension): @@ -80,13 +109,13 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): if epub_metadata['subject'] == 'Unknown': epub_metadata['subject'] = '' - if epub_metadata['publisher'] == u'Unknown': + if epub_metadata['publisher'] == 'Unknown': epub_metadata['publisher'] = '' - if epub_metadata['date'] == u'Unknown': + if epub_metadata['date'] == 'Unknown': epub_metadata['date'] = '' - if epub_metadata['description'] == u'Unknown': + if epub_metadata['description'] == 'Unknown': description = tree.xpath("//*[local-name() = 'description']/text()") if len(description) > 0: epub_metadata['description'] = description @@ -102,7 +131,10 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): identifiers = [] for node in p.xpath('dc:identifier', namespaces=ns): - identifier_name = node.attrib.values()[-1] + try: + identifier_name = node.attrib.values()[-1] + except IndexError: + continue identifier_value = node.text if identifier_name in ('uuid', 'calibre') or identifier_value is None: continue @@ -131,40 +163,40 @@ def get_epub_info(tmp_file_path, original_file_name, original_file_extension): def parse_epub_cover(ns, tree, epub_zip, cover_path, tmp_file_path): cover_section = tree.xpath("/pkg:package/pkg:manifest/pkg:item[@id='cover-image']/@href", namespaces=ns) - cover_file = None - # if len(cover_section) > 0: for cs in cover_section: cover_file = _extract_cover(epub_zip, cs, cover_path, tmp_file_path) if cover_file: - break - if not cover_file: - meta_cover = tree.xpath("/pkg:package/pkg:metadata/pkg:meta[@name='cover']/@content", namespaces=ns) - if len(meta_cover) > 0: + return cover_file + + meta_cover = tree.xpath("/pkg:package/pkg:metadata/pkg:meta[@name='cover']/@content", namespaces=ns) + if len(meta_cover) > 0: + cover_section = tree.xpath( + "/pkg:package/pkg:manifest/pkg:item[@id='"+meta_cover[0]+"']/@href", namespaces=ns) + if not cover_section: cover_section = tree.xpath( - "/pkg:package/pkg:manifest/pkg:item[@id='"+meta_cover[0]+"']/@href", namespaces=ns) - if not cover_section: - cover_section = tree.xpath( - "/pkg:package/pkg:manifest/pkg:item[@properties='" + meta_cover[0] + "']/@href", namespaces=ns) + "/pkg:package/pkg:manifest/pkg:item[@properties='" + meta_cover[0] + "']/@href", namespaces=ns) + else: + cover_section = tree.xpath("/pkg:package/pkg:guide/pkg:reference/@href", namespaces=ns) + + cover_file = None + for cs in cover_section: + if cs.endswith('.xhtml') or cs.endswith('.html'): + markup = epub_zip.read(os.path.join(cover_path, cs)) + markup_tree = etree.fromstring(markup) + # no matter xhtml or html with no namespace + img_src = markup_tree.xpath("//*[local-name() = 'img']/@src") + # Alternative image source + if not len(img_src): + img_src = markup_tree.xpath("//attribute::*[contains(local-name(), 'href')]") + if len(img_src): + # img_src maybe start with "../"" so fullpath join then relpath to cwd + filename = os.path.relpath(os.path.join(os.path.dirname(os.path.join(cover_path, cover_section[0])), + img_src[0])) + cover_file = _extract_cover(epub_zip, filename, "", tmp_file_path) else: - cover_section = tree.xpath("/pkg:package/pkg:guide/pkg:reference/@href", namespaces=ns) - for cs in cover_section: - filetype = cs.rsplit('.', 1)[-1] - if filetype == "xhtml" or filetype == "html": # if cover is (x)html format - markup = epub_zip.read(os.path.join(cover_path, cs)) - markup_tree = etree.fromstring(markup) - # no matter xhtml or html with no namespace - img_src = markup_tree.xpath("//*[local-name() = 'img']/@src") - # Alternative image source - if not len(img_src): - img_src = markup_tree.xpath("//attribute::*[contains(local-name(), 'href')]") - if len(img_src): - # img_src maybe start with "../"" so fullpath join then relpath to cwd - filename = os.path.relpath(os.path.join(os.path.dirname(os.path.join(cover_path, cover_section[0])), - img_src[0])) - cover_file = _extract_cover(epub_zip, filename, "", tmp_file_path) - else: - cover_file = _extract_cover(epub_zip, cs, cover_path, tmp_file_path) - if cover_file: break + cover_file = _extract_cover(epub_zip, cs, cover_path, tmp_file_path) + if cover_file: + break return cover_file diff --git a/cps/fb2.py b/cps/fb2.py index c4b89fd6..81eae579 100644 --- a/cps/fb2.py +++ b/cps/fb2.py @@ -38,19 +38,19 @@ def get_fb2_info(tmp_file_path, original_file_extension): if len(last_name): last_name = last_name[0] else: - last_name = u'' + last_name = '' middle_name = element.xpath('fb:middle-name/text()', namespaces=ns) if len(middle_name): middle_name = middle_name[0] else: - middle_name = u'' + middle_name = '' first_name = element.xpath('fb:first-name/text()', namespaces=ns) if len(first_name): first_name = first_name[0] else: - first_name = u'' - return (first_name + u' ' - + middle_name + u' ' + first_name = '' + return (first_name + ' ' + + middle_name + ' ' + last_name) author = str(", ".join(map(get_author, authors))) @@ -59,12 +59,12 @@ def get_fb2_info(tmp_file_path, original_file_extension): if len(title): title = str(title[0]) else: - title = u'' + title = '' description = tree.xpath('/fb:FictionBook/fb:description/fb:publish-info/fb:book-name/text()', namespaces=ns) if len(description): description = str(description[0]) else: - description = u'' + description = '' return BookMeta( file_path=tmp_file_path, diff --git a/cps/gdrive.py b/cps/gdrive.py index 60e3d47b..832350e1 100644 --- a/cps/gdrive.py +++ b/cps/gdrive.py @@ -55,7 +55,7 @@ def authenticate_google_drive(): try: authUrl = gdriveutils.Gauth.Instance().auth.GetAuthUrl() except gdriveutils.InvalidConfigError: - flash(_(u'Google Drive setup not completed, try to deactivate and activate Google Drive again'), + flash(_('Google Drive setup not completed, try to deactivate and activate Google Drive again'), category="error") return redirect(url_for('web.index')) return redirect(authUrl) @@ -91,9 +91,9 @@ def watch_gdrive(): config.save() except HttpError as e: reason=json.loads(e.content)['error']['errors'][0] - if reason['reason'] == u'push.webhookUrlUnauthorized': - flash(_(u'Callback domain is not verified, ' - u'please follow steps to verify domain in google developer console'), category="error") + if reason['reason'] == 'push.webhookUrlUnauthorized': + flash(_('Callback domain is not verified, ' + 'please follow steps to verify domain in google developer console'), category="error") else: flash(reason['message'], category="error") diff --git a/cps/gdriveutils.py b/cps/gdriveutils.py index f83bf775..08ead47d 100644 --- a/cps/gdriveutils.py +++ b/cps/gdriveutils.py @@ -147,7 +147,7 @@ engine = create_engine('sqlite:///{0}'.format(cli_param.gd_path), echo=False) Base = declarative_base() # Open session for database connection -Session = sessionmaker() +Session = sessionmaker(autoflush=False) Session.configure(bind=engine) session = scoped_session(Session) @@ -174,30 +174,12 @@ class PermissionAdded(Base): return str(self.gdrive_id) -def migrate(): - if not engine.dialect.has_table(engine.connect(), "permissions_added"): - PermissionAdded.__table__.create(bind = engine) - for sql in session.execute(text("select sql from sqlite_master where type='table'")): - if 'CREATE TABLE gdrive_ids' in sql[0]: - currUniqueConstraint = 'UNIQUE (gdrive_id)' - if currUniqueConstraint in sql[0]: - sql=sql[0].replace(currUniqueConstraint, 'UNIQUE (gdrive_id, path)') - sql=sql.replace(GdriveId.__tablename__, GdriveId.__tablename__ + '2') - session.execute(sql) - session.execute("INSERT INTO gdrive_ids2 (id, gdrive_id, path) SELECT id, " - "gdrive_id, path FROM gdrive_ids;") - session.commit() - session.execute('DROP TABLE %s' % 'gdrive_ids') - session.execute('ALTER TABLE gdrive_ids2 RENAME to gdrive_ids') - break - if not os.path.exists(cli_param.gd_path): try: Base.metadata.create_all(engine) except Exception as ex: log.error("Error connect to database: {} - {}".format(cli_param.gd_path, ex)) raise -migrate() def getDrive(drive=None, gauth=None): @@ -344,7 +326,7 @@ def getFileFromEbooksFolder(path, fileName): def moveGdriveFileRemote(origin_file_id, new_title): - origin_file_id['title']= new_title + origin_file_id['title'] = new_title origin_file_id.Upload() @@ -422,7 +404,7 @@ def copyToDrive(drive, uploadFile, createRoot, replaceFiles, driveFile.Upload() -def uploadFileToEbooksFolder(destFile, f): +def uploadFileToEbooksFolder(destFile, f, string=False): drive = getDrive(Gdrive.Instance().drive) parent = getEbooksFolder(drive) splitDir = destFile.split('/') @@ -435,7 +417,10 @@ def uploadFileToEbooksFolder(destFile, f): else: driveFile = drive.CreateFile({'title': x, 'parents': [{"kind": "drive#fileLink", 'id': parent['id']}], }) - driveFile.SetContentFile(f) + if not string: + driveFile.SetContentFile(f) + else: + driveFile.SetContentString(f) driveFile.Upload() else: existing_Folder = drive.ListFile({'q': "title = '%s' and '%s' in parents and trashed = false" % @@ -556,7 +541,7 @@ def updateGdriveCalibreFromLocal(): # update gdrive.db on edit of books title def updateDatabaseOnEdit(ID,newPath): - sqlCheckPath = newPath if newPath[-1] == '/' else newPath + u'/' + sqlCheckPath = newPath if newPath[-1] == '/' else newPath + '/' storedPathName = session.query(GdriveId).filter(GdriveId.gdrive_id == ID).first() if storedPathName: storedPathName.path = sqlCheckPath diff --git a/cps/helper.py b/cps/helper.py old mode 100755 new mode 100644 index 212ce142..0c526d01 --- a/cps/helper.py +++ b/cps/helper.py @@ -18,6 +18,7 @@ # along with this program. If not, see . import os +import random import io import mimetypes import re @@ -77,29 +78,29 @@ def convert_book_format(book_id, calibre_path, old_book_format, new_book_format, book = calibre_db.get_book(book_id) data = calibre_db.get_book_format(book.id, old_book_format) if not data: - error_message = _(u"%(format)s format not found for book id: %(book)d", format=old_book_format, book=book_id) + error_message = _("%(format)s format not found for book id: %(book)d", format=old_book_format, book=book_id) log.error("convert_book_format: %s", error_message) return error_message file_path = os.path.join(calibre_path, book.path, data.name) if config.config_use_google_drive: if not gd.getFileFromEbooksFolder(book.path, data.name + "." + old_book_format.lower()): - error_message = _(u"%(format)s not found on Google Drive: %(fn)s", + error_message = _("%(format)s not found on Google Drive: %(fn)s", format=old_book_format, fn=data.name + "." + old_book_format.lower()) return error_message else: if not os.path.exists(file_path + "." + old_book_format.lower()): - error_message = _(u"%(format)s not found: %(fn)s", + error_message = _("%(format)s not found: %(fn)s", format=old_book_format, fn=data.name + "." + old_book_format.lower()) return error_message # read settings and append converter task to queue if ereader_mail: settings = config.get_mail_settings() - settings['subject'] = _('Send to E-Reader') # pretranslate Subject for e-mail - settings['body'] = _(u'This e-mail has been sent via Calibre-Web.') + settings['subject'] = _('Send to eReader') # pretranslate Subject for Email + settings['body'] = _('This Email has been sent via Calibre-Web.') else: settings = dict() link = '{}'.format(url_for('web.show_book', book_id=book.id), escape(book.title)) # prevent xss - txt = u"{} -> {}: {}".format( + txt = "{} -> {}: {}".format( old_book_format.upper(), new_book_format.upper(), link) @@ -111,30 +112,30 @@ def convert_book_format(book_id, calibre_path, old_book_format, new_book_format, # Texts are not lazy translated as they are supposed to get send out as is def send_test_mail(ereader_mail, user_name): - WorkerThread.add(user_name, TaskEmail(_(u'Calibre-Web test e-mail'), None, None, - config.get_mail_settings(), ereader_mail, N_(u"Test e-mail"), - _(u'This e-mail has been sent via Calibre-Web.'))) + WorkerThread.add(user_name, TaskEmail(_('Calibre-Web Test Email'), None, None, + config.get_mail_settings(), ereader_mail, N_("Test Email"), + _('This Email has been sent via Calibre-Web.'))) return # Send registration email or password reset email, depending on parameter resend (False means welcome email) def send_registration_mail(e_mail, user_name, default_password, resend=False): - txt = "Hello %s!\r\n" % user_name + txt = "Hi %s!\r\n" % user_name if not resend: - txt += "Your new account at Calibre-Web has been created. Thanks for joining us!\r\n" - txt += "Please log in to your account using the following information:\r\n" - txt += "User name: %s\r\n" % user_name + txt += "Your account at Calibre-Web has been created.\r\n" + txt += "Please log in using the following information:\r\n" + txt += "Username: %s\r\n" % user_name txt += "Password: %s\r\n" % default_password - txt += "Don't forget to change your password after first login.\r\n" - txt += "Sincerely\r\n\r\n" - txt += "Your Calibre-Web team" + txt += "Don't forget to change your password after your first login.\r\n" + txt += "Regards,\r\n\r\n" + txt += "Calibre-Web" WorkerThread.add(None, TaskEmail( - subject=_(u'Get Started with Calibre-Web'), + subject=_('Get Started with Calibre-Web'), filepath=None, attachment=None, settings=config.get_mail_settings(), recipient=e_mail, - task_message=N_(u"Registration e-mail for user: %(name)s", name=user_name), + task_message=N_("Registration Email for user: %(name)s", name=user_name), text=txt )) return @@ -145,13 +146,13 @@ def check_send_to_ereader_with_converter(formats): if 'MOBI' in formats and 'EPUB' not in formats: book_formats.append({'format': 'Epub', 'convert': 1, - 'text': _('Convert %(orig)s to %(format)s and send to E-Reader', + 'text': _('Convert %(orig)s to %(format)s and send to eReader', orig='Mobi', format='Epub')}) if 'AZW3' in formats and 'EPUB' not in formats: book_formats.append({'format': 'Epub', 'convert': 2, - 'text': _('Convert %(orig)s to %(format)s and send to E-Reader', + 'text': _('Convert %(orig)s to %(format)s and send to eReader', orig='Azw3', format='Epub')}) return book_formats @@ -159,7 +160,7 @@ def check_send_to_ereader_with_converter(formats): def check_send_to_ereader(entry): """ - returns all available book formats for sending to E-Reader + returns all available book formats for sending to eReader """ formats = list() book_formats = list() @@ -170,31 +171,27 @@ def check_send_to_ereader(entry): if 'EPUB' in formats: book_formats.append({'format': 'Epub', 'convert': 0, - 'text': _('Send %(format)s to E-Reader', format='Epub')}) - if 'MOBI' in formats: - book_formats.append({'format': 'Mobi', - 'convert': 0, - 'text': _('Send %(format)s to E-Reader', format='Mobi')}) + 'text': _('Send %(format)s to eReader', format='Epub')}) if 'PDF' in formats: book_formats.append({'format': 'Pdf', 'convert': 0, - 'text': _('Send %(format)s to E-Reader', format='Pdf')}) + 'text': _('Send %(format)s to eReader', format='Pdf')}) if 'AZW' in formats: book_formats.append({'format': 'Azw', 'convert': 0, - 'text': _('Send %(format)s to E-Reader', format='Azw')}) + 'text': _('Send %(format)s to eReader', format='Azw')}) if config.config_converterpath: book_formats.extend(check_send_to_ereader_with_converter(formats)) return book_formats else: - log.error(u'Cannot find book entry %d', entry.id) + log.error('Cannot find book entry %d', entry.id) return None # Check if a reader is existing for any of the book formats, if not, return empty list, otherwise return # list with supported formats def check_read_formats(entry): - extensions_reader = {'TXT', 'PDF', 'EPUB', 'CBZ', 'CBT', 'CBR', 'DJVU'} + extensions_reader = {'TXT', 'PDF', 'EPUB', 'CBZ', 'CBT', 'CBR', 'DJVU', 'DJV'} book_formats = list() if len(entry.data): for ele in iter(entry.data): @@ -204,30 +201,30 @@ def check_read_formats(entry): # Files are processed in the following order/priority: -# 1: If Mobi file is existing, it's directly send to E-Reader email, -# 2: If Epub file is existing, it's converted and send to E-Reader email, -# 3: If Pdf file is existing, it's directly send to E-Reader email +# 1: If epub file is existing, it's directly send to eReader email, +# 2: If mobi file is existing, it's converted and send to eReader email, +# 3: If Pdf file is existing, it's directly send to eReader email def send_mail(book_id, book_format, convert, ereader_mail, calibrepath, user_id): """Send email with attachments""" book = calibre_db.get_book(book_id) if convert == 1: # returns None if success, otherwise errormessage - return convert_book_format(book_id, calibrepath, u'epub', book_format.lower(), user_id, ereader_mail) + return convert_book_format(book_id, calibrepath, 'mobi', book_format.lower(), user_id, ereader_mail) if convert == 2: # returns None if success, otherwise errormessage - return convert_book_format(book_id, calibrepath, u'azw3', book_format.lower(), user_id, ereader_mail) + return convert_book_format(book_id, calibrepath, 'azw3', book_format.lower(), user_id, ereader_mail) for entry in iter(book.data): if entry.format.upper() == book_format.upper(): converted_file_name = entry.name + '.' + book_format.lower() link = '{}'.format(url_for('web.show_book', book_id=book_id), escape(book.title)) - email_text = N_(u"%(book)s send to E-Reader", book=link) - WorkerThread.add(user_id, TaskEmail(_(u"Send to E-Reader"), book.path, converted_file_name, + email_text = N_("%(book)s send to eReader", book=link) + WorkerThread.add(user_id, TaskEmail(_("Send to eReader"), book.path, converted_file_name, config.get_mail_settings(), ereader_mail, - email_text, _(u'This e-mail has been sent via Calibre-Web.'))) + email_text, _('This Email has been sent via Calibre-Web.'))) return - return _(u"The requested file could not be read. Maybe wrong permissions?") + return _("The requested file could not be read. Maybe wrong permissions?") def get_valid_filename(value, replace_whitespace=True, chars=128): @@ -235,16 +232,16 @@ def get_valid_filename(value, replace_whitespace=True, chars=128): Returns the given string converted to a string that can be used for a clean filename. Limits num characters to 128 max. """ - if value[-1:] == u'.': - value = value[:-1]+u'_' + if value[-1:] == '.': + value = value[:-1]+'_' value = value.replace("/", "_").replace(":", "_").strip('\0') if config.config_unicode_filename: value = (unidecode.unidecode(value)) if replace_whitespace: # *+:\"/<>? are replaced by _ - value = re.sub(r'[*+:\\\"/<>?]+', u'_', value, flags=re.U) + value = re.sub(r'[*+:\\\"/<>?]+', '_', value, flags=re.U) # pipe has to be replaced with comma - value = re.sub(r'[|]+', u',', value, flags=re.U) + value = re.sub(r'[|]+', ',', value, flags=re.U) value = value.encode('utf-8')[:chars].decode('utf-8', errors='ignore').strip() @@ -341,7 +338,7 @@ def edit_book_read_status(book_id, read_status=None): return "Custom Column No.{} does not exist in calibre database".format(config.config_read_column) except (OperationalError, InvalidRequestError) as ex: calibre_db.session.rollback() - log.error(u"Read status could not set: {}".format(ex)) + log.error("Read status could not set: {}".format(ex)) return _("Read status could not set: {}".format(ex.orig)) return "" @@ -416,8 +413,8 @@ def clean_author_database(renamed_author, calibre_path="", local_book=None, gdri g_file = gd.getFileFromEbooksFolder(all_new_path, file_format.name + '.' + file_format.format.lower()) if g_file: - gd.moveGdriveFileRemote(g_file, all_new_name + u'.' + file_format.format.lower()) - gd.updateDatabaseOnEdit(g_file['id'], all_new_name + u'.' + file_format.format.lower()) + gd.moveGdriveFileRemote(g_file, all_new_name + '.' + file_format.format.lower()) + gd.updateDatabaseOnEdit(g_file['id'], all_new_name + '.' + file_format.format.lower()) else: log.error("File {} not found on gdrive" .format(all_new_path, file_format.name + '.' + file_format.format.lower())) @@ -510,25 +507,25 @@ def update_dir_structure_gdrive(book_id, first_author, renamed_author): authordir = book.path.split('/')[0] titledir = book.path.split('/')[1] new_authordir = rename_all_authors(first_author, renamed_author, gdrive=True) - new_titledir = get_valid_filename(book.title, chars=96) + u" (" + str(book_id) + u")" + new_titledir = get_valid_filename(book.title, chars=96) + " (" + str(book_id) + ")" if titledir != new_titledir: g_file = gd.getFileFromEbooksFolder(os.path.dirname(book.path), titledir) if g_file: gd.moveGdriveFileRemote(g_file, new_titledir) - book.path = book.path.split('/')[0] + u'/' + new_titledir + book.path = book.path.split('/')[0] + '/' + new_titledir gd.updateDatabaseOnEdit(g_file['id'], book.path) # only child folder affected else: - return _(u'File %(file)s not found on Google Drive', file=book.path) # file not found + return _('File %(file)s not found on Google Drive', file=book.path) # file not found if authordir != new_authordir and authordir not in renamed_author: g_file = gd.getFileFromEbooksFolder(os.path.dirname(book.path), new_titledir) if g_file: gd.moveGdriveFolderRemote(g_file, new_authordir) - book.path = new_authordir + u'/' + book.path.split('/')[1] + book.path = new_authordir + '/' + book.path.split('/')[1] gd.updateDatabaseOnEdit(g_file['id'], book.path) else: - return _(u'File %(file)s not found on Google Drive', file=authordir) # file not found + return _('File %(file)s not found on Google Drive', file=authordir) # file not found # change location in database to new author/title path book.path = os.path.join(new_authordir, new_titledir).replace('\\', '/') @@ -600,7 +597,7 @@ def delete_book_gdrive(book, book_format): gd.deleteDatabaseEntry(g_file['id']) g_file.Trash() else: - error = _(u'Book path %(path)s not found on Google Drive', path=book.path) # file not found + error = _('Book path %(path)s not found on Google Drive', path=book.path) # file not found return error is None, error @@ -612,7 +609,7 @@ def reset_password(user_id): if not config.get_mail_server_configured(): return 2, None try: - password = generate_random_password() + password = generate_random_password(config.config_password_min_length) existing_user.password = generate_password_hash(password) ub.session.commit() send_registration_mail(existing_user.email, existing_user.name, password, True) @@ -621,11 +618,35 @@ def reset_password(user_id): ub.session.rollback() return 0, None +def generate_random_password(min_length): + min_length = max(8, min_length) - 4 + random_source = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?" + # select 1 lowercase + s = "abcdefghijklmnopqrstuvwxyz" + password = [s[c % len(s)] for c in os.urandom(1)] + # select 1 uppercase + s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + password.extend([s[c % len(s)] for c in os.urandom(1)]) + # select 1 digit + s = "01234567890" + password.extend([s[c % len(s)] for c in os.urandom(1)]) + # select 1 special symbol + s = "!@#$%&*()?" + password.extend([s[c % len(s)] for c in os.urandom(1)]) -def generate_random_password(): + # generate other characters + password.extend([random_source[c % len(random_source)] for c in os.urandom(min_length)]) + + # password_list = list(password) + # shuffle all characters + random.SystemRandom().shuffle(password) + return ''.join(password) + + +'''def generate_random_password(min_length): s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?" - passlen = 8 - return "".join(s[c % len(s)] for c in os.urandom(passlen)) + passlen = min_length + return "".join(s[c % len(s)] for c in os.urandom(passlen))''' def uniq(inpt): @@ -640,16 +661,16 @@ def uniq(inpt): def check_email(email): email = valid_email(email) if ub.session.query(ub.User).filter(func.lower(ub.User.email) == email.lower()).first(): - log.error(u"Found an existing account for this e-mail address") - raise Exception(_(u"Found an existing account for this e-mail address")) + log.error("Found an existing account for this Email address") + raise Exception(_("Found an existing account for this Email address")) return email def check_username(username): username = username.strip() if ub.session.query(ub.User).filter(func.lower(ub.User.name) == username.lower()).scalar(): - log.error(u"This username is already taken") - raise Exception(_(u"This username is already taken")) + log.error("This username is already taken") + raise Exception(_("This username is already taken")) return username @@ -660,10 +681,27 @@ def valid_email(email): # Regex according to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#validation if not re.search(r"^[\w.!#$%&'*+\\/=?^_`{|}~-]+@[\w](?:[\w-]{0,61}[\w])?(?:\.[\w](?:[\w-]{0,61}[\w])?)*$", email): - log.error(u"Invalid e-mail address format") - raise Exception(_(u"Invalid e-mail address format")) + log.error("Invalid Email address format") + raise Exception(_("Invalid Email address format")) return email +def valid_password(check_password): + if config.config_password_policy: + verify = "" + if config.config_password_min_length > 0: + verify += "^(?=.{" + str(config.config_password_min_length) + ",}$)" + if config.config_password_number: + verify += "(?=.*?\d)" + if config.config_password_lower: + verify += "(?=.*?[a-z])" + if config.config_password_upper: + verify += "(?=.*?[A-Z])" + if config.config_password_special: + verify += "(?=.*?[^A-Za-z\s0-9])" + match = re.match(verify, check_password) + if not match: + raise Exception(_("Password doesn't comply with password validation rules")) + return check_password # ################################# External interface ################################# @@ -694,28 +732,27 @@ def delete_book(book, calibrepath, book_format): return delete_book_file(book, calibrepath, book_format) -def get_cover_on_failure(use_generic_cover): - if use_generic_cover: - try: - return send_from_directory(_STATIC_DIR, "generic_cover.jpg") - except PermissionError: - log.error("No permission to access generic_cover.jpg file.") - abort(403) - abort(404) +def get_cover_on_failure(): + try: + return send_from_directory(_STATIC_DIR, "generic_cover.jpg") + except PermissionError: + log.error("No permission to access generic_cover.jpg file.") + abort(403) def get_book_cover(book_id, resolution=None): book = calibre_db.get_filtered_book(book_id, allow_show_archived=True) - return get_book_cover_internal(book, use_generic_cover_on_failure=True, resolution=resolution) + return get_book_cover_internal(book, resolution=resolution) -# Called only by kobo sync -> cover not found should be answered with 404 and not with default cover def get_book_cover_with_uuid(book_uuid, resolution=None): book = calibre_db.get_book_by_uuid(book_uuid) - return get_book_cover_internal(book, use_generic_cover_on_failure=False, resolution=resolution) + if not book: + return # allows kobo.HandleCoverImageRequest to proxy request + return get_book_cover_internal(book, resolution=resolution) -def get_book_cover_internal(book, use_generic_cover_on_failure, resolution=None): +def get_book_cover_internal(book, resolution=None): if book and book.has_cover: # Send the book cover thumbnail if it exists in cache @@ -731,16 +768,16 @@ def get_book_cover_internal(book, use_generic_cover_on_failure, resolution=None) if config.config_use_google_drive: try: if not gd.is_gdrive_ready(): - return get_cover_on_failure(use_generic_cover_on_failure) + return get_cover_on_failure() path = gd.get_cover_via_gdrive(book.path) if path: return redirect(path) else: log.error('{}/cover.jpg not found on Google Drive'.format(book.path)) - return get_cover_on_failure(use_generic_cover_on_failure) + return get_cover_on_failure() except Exception as ex: log.error_or_exception(ex) - return get_cover_on_failure(use_generic_cover_on_failure) + return get_cover_on_failure() # Send the book cover from the Calibre directory else: @@ -748,9 +785,9 @@ def get_book_cover_internal(book, use_generic_cover_on_failure, resolution=None) if os.path.isfile(os.path.join(cover_file_path, "cover.jpg")): return send_from_directory(cover_file_path, "cover.jpg") else: - return get_cover_on_failure(use_generic_cover_on_failure) + return get_cover_on_failure() else: - return get_cover_on_failure(use_generic_cover_on_failure) + return get_cover_on_failure() def get_book_cover_thumbnail(book, resolution): @@ -773,7 +810,7 @@ def get_series_thumbnail_on_failure(series_id, resolution): .filter(db.Books.has_cover == 1) \ .first() - return get_book_cover_internal(book, use_generic_cover_on_failure=True, resolution=resolution) + return get_book_cover_internal(book, resolution=resolution) def get_series_cover_thumbnail(series_id, resolution=None): @@ -837,8 +874,8 @@ def save_cover_from_filestorage(filepath, saved_filename, img): try: os.makedirs(filepath) except OSError: - log.error(u"Failed to create path for cover") - return False, _(u"Failed to create path for cover") + log.error("Failed to create path for cover") + return False, _("Failed to create path for cover") try: # upload of jgp file without wand if isinstance(img, requests.Response): @@ -853,8 +890,8 @@ def save_cover_from_filestorage(filepath, saved_filename, img): # upload of jpg/png... from hdd img.save(os.path.join(filepath, saved_filename)) except (IOError, OSError): - log.error(u"Cover-file is not a valid image file, or could not be stored") - return False, _(u"Cover-file is not a valid image file, or could not be stored") + log.error("Cover-file is not a valid image file, or could not be stored") + return False, _("Cover-file is not a valid image file, or could not be stored") return True, None @@ -1004,7 +1041,7 @@ def get_download_link(book_id, book_format, client): headers = Headers() headers["Content-Type"] = mimetypes.types_map.get('.' + book_format, "application/octet-stream") headers["Content-Disposition"] = "attachment; filename=%s.%s; filename*=UTF-8''%s.%s" % ( - quote(file_name.encode('utf-8')), book_format, quote(file_name.encode('utf-8')), book_format) + quote(file_name), book_format, quote(file_name), book_format) return do_download_file(book, book_format, client, data1, headers) else: abort(404) diff --git a/cps/iso_language_names.py b/cps/iso_language_names.py index 59be4952..4b9a8ef9 100644 --- a/cps/iso_language_names.py +++ b/cps/iso_language_names.py @@ -3320,6 +3320,384 @@ LANGUAGE_NAMES = { "zxx": "No linguistic content", "zza": "Zaza" }, + "id": { + "abk": "Abkhazian", + "ace": "Achinese", + "ach": "Acoli", + "ada": "Adangme", + "ady": "Adyghe", + "aar": "Afar", + "afh": "Afrihili", + "afr": "Afrika", + "ain": "Ainu (Japan)", + "aka": "Akan", + "akk": "Akkadian", + "sqi": "Albanian", + "ale": "Aleut", + "amh": "Amharic", + "anp": "Angika", + "ara": "Arab", + "arg": "Aragonese", + "arp": "Arapaho", + "arw": "Arawak", + "hye": "Armenia", + "asm": "Assam", + "ast": "Asturian", + "ava": "Avaric", + "ave": "Avestan", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Azerbaijani", + "ban": "Balinese", + "bal": "Baluchi", + "bam": "Bambara", + "bas": "Basa (Cameroon)", + "bak": "Bashkir", + "eus": "Basque", + "bej": "Beja", + "bel": "Belarusian", + "bem": "Bemba (Zambia)", + "ben": "Bengal", + "bit": "Berinomo", + "bho": "Bhojpuri", + "bik": "Bikol", + "byn": "Bilin", + "bin": "Bini", + "bis": "Bislama", + "zbl": "Blissymbols", + "bos": "Bosnian", + "bra": "Braj", + "bre": "Breton", + "bug": "Bugis", + "bul": "Bulgaria", + "bua": "Buriat", + "mya": "Burma", + "cad": "Caddo", + "cat": "Catalan", + "ceb": "Cebuano", + "chg": "Chagatai", + "cha": "Chamorro", + "che": "Chechen", + "chr": "Cherokee", + "chy": "Cheyenne", + "chb": "Chibcha", + "zho": "Cina", + "chn": "Chinook jargon", + "chp": "Chipewyan", + "cho": "Choctaw", + "cht": "Cholón", + "chk": "Chuukese", + "chv": "Chuvash", + "cop": "Koptik", + "cor": "Cornish", + "cos": "Corsican", + "cre": "Cree", + "mus": "Creek", + "hrv": "Kroasia", + "ces": "Ceko", + "dak": "Dakota", + "dan": "Denmark", + "dar": "Dargwa", + "del": "Delaware", + "div": "Dhivehi", + "din": "Dinka", + "doi": "Dogri (macrolanguage)", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "Belanda", + "dse": "Dutch Sign Language", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efik", + "egy": "Mesir Kuno", + "eka": "Ekajuk", + "elx": "Elamite", + "eng": "Inggris", + "enu": "Enu", + "myv": "Erzya", + "epo": "Esperanto", + "est": "Estonia", + "ewe": "Ewe", + "ewo": "Ewondo", + "fan": "Fang (Equatorial Guinea)", + "fat": "Fanti", + "fao": "Faro", + "fij": "Fiji", + "fil": "Filipino", + "fin": "Finlandia", + "fon": "Fon", + "fra": "Prancis", + "fur": "Friulian", + "ful": "Fulah", + "gaa": "Ga", + "glg": "Galician", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (Central African Republic)", + "hmj": "Ge", + "gez": "Geez", + "kat": "Georgian", + "deu": "Jerman", + "gil": "Gilbertese", + "gon": "Gondi", + "gor": "Gorontalo", + "got": "Gothik", + "grb": "Grebo", + "grn": "Guarani", + "guj": "Gujarati", + "gwi": "Gwichʼin", + "hai": "Haida", + "hau": "Hausa", + "haw": "Hawaii", + "heb": "Israel", + "her": "Herero", + "hil": "Hiligaynon", + "hin": "Hindi", + "hmo": "Hiri Motu", + "hit": "Hittite", + "hmn": "Hmong", + "hun": "Hungaria", + "hup": "Hupa", + "iba": "Iban", + "isl": "Islandia", + "ido": "Ido", + "ibo": "Igbo", + "ilo": "Iloko", + "ind": "Bahasa Indonesia", + "inh": "Ingush", + "ina": "Interlingua (International Auxiliary Language Association)", + "ile": "Interlingue", + "iku": "Inuktitut", + "ipk": "Inupiaq", + "gle": "Irlandia", + "ita": "Italia", + "jpn": "Jepang", + "jav": "Javanese", + "jrb": "Judeo-Arabic", + "jpr": "Judeo-Persian", + "kbd": "Kabardian", + "kab": "Kabyle", + "kac": "Kachin", + "kal": "Kalaallisut", + "xal": "Kalmyk", + "kam": "Kamba (Kenya)", + "kan": "Kannada", + "kau": "Kanuri", + "kaa": "Kara-Kalpak", + "krc": "Karachay-Balkar", + "krl": "Karelian", + "kas": "Kashmir", + "csb": "Kashubian", + "kaw": "Kawi", + "kaz": "Kazakh", + "kha": "Khasi", + "kho": "Khotanese", + "kik": "Kikuyu", + "kmb": "Kimbundu", + "kin": "Kinyarwanda", + "kir": "Kirghiz", + "tlh": "Klingon", + "kom": "Komi", + "kon": "Kongo", + "kok": "Konkani (macrolanguage)", + "kor": "Korea", + "kos": "Kosraean", + "kpe": "Kpelle", + "kua": "Kuanyama", + "kum": "Kumyk", + "kur": "Kurdish", + "kru": "Kurukh", + "kut": "Kutenai", + "lad": "Ladino", + "lah": "Lahnda", + "lam": "Lamba", + "lao": "Lao", + "lat": "Latin", + "lav": "Latvian", + "lez": "Lezghian", + "lim": "Limburgan", + "lin": "Lingala", + "lit": "Lithuania", + "jbo": "Lojban", + "loz": "Lozi", + "lub": "Luba-Katanga", + "lua": "Luba-Lulua", + "lui": "Luiseno", + "smj": "Lule Sami", + "lun": "Lunda", + "luo": "Luo (Kenya and Tanzania)", + "lus": "Lushai", + "ltz": "Luxembourgish", + "mkd": "Masedonian", + "mad": "Madurese", + "mag": "Magahi", + "mai": "Maithili", + "mak": "Makasar", + "mlg": "Malagasi", + "msa": "Malay (macrolanguage)", + "mal": "Malayalam", + "mlt": "Maltese", + "mnc": "Manchu", + "mdr": "Mandar", + "man": "Mandingo", + "mni": "Manipuri", + "glv": "Manx", + "mri": "Maori", + "arn": "Mapudungun", + "mar": "Marathi", + "chm": "Mari (Russia)", + "mah": "Marshallese", + "mwr": "Marwari", + "mas": "Masai", + "men": "Mende (Sierra Leone)", + "mic": "Mi'kmaq", + "min": "Minangkabau", + "mwl": "Mirandese", + "moh": "Mohawk", + "mdf": "Moksha", + "lol": "Mongo", + "mon": "Mongolian", + "mos": "Mossi", + "mul": "Multiple languages", + "nqo": "N'Ko", + "nau": "Nauru", + "nav": "Navajo", + "ndo": "Ndonga", + "nap": "Neapolitan", + "nia": "Nias", + "niu": "Niuean", + "zxx": "No linguistic content", + "nog": "Nogai", + "nor": "Norwegian", + "nob": "Norwegian Bokmål", + "nno": "Norwegian Nynorsk", + "nym": "Nyamwezi", + "nya": "Nyanja", + "nyn": "Nyankole", + "nyo": "Nyoro", + "nzi": "Nzima", + "oci": "Occitan (post 1500)", + "oji": "Ojibwa", + "orm": "Oromo", + "osa": "Osage", + "oss": "Ossetian", + "pal": "Pahlavi", + "pau": "Palauan", + "pli": "Pali", + "pam": "Pampanga", + "pag": "Pangasinan", + "pan": "Panjabi", + "pap": "Papiamento", + "fas": "Persian", + "phn": "Phoenician", + "pon": "Pohnpeian", + "pol": "Polandia", + "por": "Portugis", + "pus": "Pashto", + "que": "Quechua", + "raj": "Rajasthani", + "rap": "Rapanui", + "ron": "Rumania", + "roh": "Romansh", + "rom": "Romany", + "run": "Rundi", + "rus": "Rusia", + "smo": "Samoan", + "sad": "Sandawe", + "sag": "Sango", + "san": "Sanskrit", + "sat": "Santali", + "srd": "Sardinian", + "sas": "Sasak", + "sco": "Scots", + "sel": "Selkup", + "srp": "Serbia", + "srr": "Serer", + "shn": "Shan", + "sna": "Shona", + "scn": "Sicilian", + "sid": "Sidamo", + "bla": "Siksika", + "snd": "Sindhi", + "sin": "Sinhala", + "den": "Slave (Athapascan)", + "slk": "Slovakia", + "slv": "Slovenia", + "sog": "Sogdian", + "som": "Somali", + "snk": "Soninke", + "spa": "Spanyol", + "srn": "Sranan Tongo", + "suk": "Sukuma", + "sux": "Sumerian", + "sun": "Sundan", + "sus": "Susu", + "swa": "Swahili (macrolanguage)", + "ssw": "Swati", + "swe": "Swedia", + "syr": "Syriac", + "tgl": "Tagalog", + "tah": "Tahitian", + "tgk": "Tajik", + "tmh": "Tamashek", + "tam": "Tamil", + "tat": "Tatar", + "tel": "Telugu", + "ter": "Tereno", + "tet": "Tetum", + "tha": "Thailand", + "bod": "Tibet", + "tig": "Tigre", + "tir": "Tigrinya", + "tem": "Timne", + "tiv": "Tiv", + "tli": "Tlingit", + "tpi": "Tok Pisin", + "tkl": "Tokelau", + "tog": "Tonga (Nyasa)", + "ton": "Tonga (Tonga Islands)", + "tsi": "Tsimshian", + "tso": "Tsonga", + "tsn": "Tswana", + "tum": "Tumbuka", + "tur": "Turki", + "tuk": "Turkmen", + "tvl": "Tuvalu", + "tyv": "Tuvinian", + "twi": "Twi", + "udm": "Udmurt", + "uga": "Ugaritic", + "uig": "Uighur", + "ukr": "Ukrainian", + "umb": "Umbundu", + "mis": "Uncoded languages", + "und": "Undetermined", + "urd": "Urdu", + "uzb": "Uzbek", + "vai": "Vai", + "ven": "Venda", + "vie": "Vietnamese", + "vol": "Volapük", + "vot": "Votic", + "wln": "Wallon", + "war": "Waray (Philippines)", + "was": "Washo", + "cym": "Welsh", + "wal": "Wolaytta", + "wol": "Wolof", + "xho": "Xhosa", + "sah": "Yakut", + "yao": "Yao", + "yap": "Yapese", + "yid": "Yiddish", + "yor": "Yoruba", + "zap": "Zapotec", + "zza": "Zaza", + "zen": "Zenaga", + "zha": "Zhuang", + "zul": "Zulu", + "zun": "Zuni" + }, "it": { "aar": "Afar", "abk": "Abkhazian", @@ -5398,6 +5776,384 @@ LANGUAGE_NAMES = { "zxx": "Geen linguïstische inhoud", "zza": "Zaza" }, + "no": { + "abk": "Abkhazian", + "ace": "Achinese", + "ach": "Acoli", + "ada": "Adangme", + "ady": "Adyghe", + "aar": "Afar", + "afh": "Afrihili", + "afr": "Afrikansk", + "ain": "Ainu (Japan)", + "aka": "Akan", + "akk": "Akkadian", + "sqi": "Albansk", + "ale": "Aleut", + "amh": "Amharic", + "anp": "Angika", + "ara": "Arabisk", + "arg": "Aragonsk", + "arp": "Arapaho", + "arw": "Arawak", + "hye": "Armensk", + "asm": "assamisk", + "ast": "Asturian", + "ava": "Avaric", + "ave": "Avestisk", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Aserbadjansk", + "ban": "Balinese", + "bal": "Baluchi", + "bam": "Bambara", + "bas": "Basa (Cameroon)", + "bak": "Basjkirsk", + "eus": "Baskisk", + "bej": "Beja", + "bel": "Hviterussisk", + "bem": "Bemba (Zambia)", + "ben": "Bengali", + "bit": "Berinomo", + "bho": "Bhojpuri", + "bik": "Bikol", + "byn": "Bilin", + "bin": "Bini", + "bis": "Bislama", + "zbl": "Blissymbols", + "bos": "Bosnian", + "bra": "Braj", + "bre": "Breton", + "bug": "Buginese", + "bul": "Bulgarsk", + "bua": "Buriat", + "mya": "burmesisk", + "cad": "Caddo", + "cat": "Katalan", + "ceb": "Cebuano", + "chg": "Chagatai", + "cha": "chamorro", + "che": "Chechen", + "chr": "cherokee", + "chy": "Cheyenne", + "chb": "Chibcha", + "zho": "Kinesisk", + "chn": "Chinook jargon", + "chp": "Chipewyan", + "cho": "Choctaw", + "cht": "Cholón", + "chk": "Chuukese", + "chv": "tsjuvansk", + "cop": "Koptisk", + "cor": "Cornish", + "cos": "Corsican", + "cre": "Cree", + "mus": "Creek", + "hrv": "Kroatsisk", + "ces": "Tjekkisk", + "dak": "Dakota", + "dan": "Dansk", + "dar": "Dargwa", + "del": "Delaware", + "div": "Dhivehi", + "din": "Dinka", + "doi": "Dogri (macrolanguage)", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "Nederlandsk", + "dse": "Dutch Sign Language", + "dyu": "Dyula", + "dzo": "dzongkha", + "efi": "Efik", + "egy": "Egyptian (Ancient)", + "eka": "Ekajuk", + "elx": "Elamite", + "eng": "Engelsk", + "enu": "Enu", + "myv": "Erzya", + "epo": "Esperanto", + "est": "Estonsk", + "ewe": "ewe", + "ewo": "Ewondo", + "fan": "Fang (Equatorial Guinea)", + "fat": "Fanti", + "fao": "færøysk", + "fij": "fijiansk", + "fil": "Filipino", + "fin": "Finsk", + "fon": "Fon", + "fra": "Fransk", + "fur": "Friulian", + "ful": "fulani", + "gaa": "Ga", + "glg": "Galician", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (Central African Republic)", + "hmj": "Ge", + "gez": "Geez", + "kat": "Georgisk", + "deu": "Tysk", + "gil": "Gilbertese", + "gon": "Gondi", + "gor": "Gorontalo", + "got": "Gotisk", + "grb": "Grebo", + "grn": "Guarani", + "guj": "gujarati", + "gwi": "Gwichʼin", + "hai": "Haida", + "hau": "Hausa", + "haw": "hawaiisk", + "heb": "Hebraisk", + "her": "Herero", + "hil": "Hiligaynon", + "hin": "hindi", + "hmo": "Hiri Motu", + "hit": "Hittite", + "hmn": "Hmong", + "hun": "Ungarsk", + "hup": "Hupa", + "iba": "Iban", + "isl": "Islandsk", + "ido": "ido", + "ibo": "ibo", + "ilo": "Iloko", + "ind": "Indonesisk", + "inh": "Ingush", + "ina": "Interlingua (International Auxiliary Language Association)", + "ile": "interlingue", + "iku": "inuktitut", + "ipk": "unupiak", + "gle": "Irsk", + "ita": "Italiensk", + "jpn": "Japansk", + "jav": "Javanesisk", + "jrb": "Judeo-Arabic", + "jpr": "Judeo-Persian", + "kbd": "Kabardian", + "kab": "Kabyle", + "kac": "Kachin", + "kal": "Grønlandsk", + "xal": "Kalmyk", + "kam": "Kamba (Kenya)", + "kan": "kannada", + "kau": "Kanuri", + "kaa": "Kara-Kalpak", + "krc": "Karachay-Balkar", + "krl": "Karelisk", + "kas": "kasjmiri", + "csb": "Kashubian", + "kaw": "Kawi", + "kaz": "kasakhisk", + "kha": "Khasi", + "kho": "Khotanese", + "kik": "kikuyu", + "kmb": "Kimbundu", + "kin": "kinjarwanda", + "kir": "kirgisisk", + "tlh": "Klingon", + "kom": "komi", + "kon": "Kongo", + "kok": "Konkani (macrolanguage)", + "kor": "Koreansk", + "kos": "Kosraean", + "kpe": "Kpelle", + "kua": "kuanyama", + "kum": "Kumyk", + "kur": "Kurdisk", + "kru": "Kurukh", + "kut": "Kutenai", + "lad": "Ladino", + "lah": "Lahnda", + "lam": "Lamba", + "lao": "laotisk", + "lat": "Latin", + "lav": "Latvisk", + "lez": "Lezghian", + "lim": "Limburgan", + "lin": "lingala", + "lit": "Lituaisk", + "jbo": "Lojban", + "loz": "Lozi", + "lub": "luba-katanga", + "lua": "Luba-Lulua", + "lui": "Luiseno", + "smj": "Lulesamisk", + "lun": "Lunda", + "luo": "Luo (Kenya and Tanzania)", + "lus": "Lushai", + "ltz": "Luxemburgisk", + "mkd": "Makedonsk", + "mad": "Madurese", + "mag": "Magahi", + "mai": "Maithili", + "mak": "Makasar", + "mlg": "madagassisk", + "msa": "Malay (macrolanguage)", + "mal": "malayalam", + "mlt": "Maltisk", + "mnc": "Manchu", + "mdr": "Mandar", + "man": "Mandingo", + "mni": "Manipuri", + "glv": "manx", + "mri": "Maori", + "arn": "Mapudungun", + "mar": "Marathi", + "chm": "Mari (Russland)", + "mah": "Marshallese", + "mwr": "Marwari", + "mas": "Masai", + "men": "Mende (Sierra Leone)", + "mic": "Mi'kmaq", + "min": "Minangkabau", + "mwl": "Mirandese", + "moh": "Mohawk", + "mdf": "Moksha", + "lol": "Mongo", + "mon": "Mongolsk", + "mos": "Mossi", + "mul": "Flere språk", + "nqo": "N'Ko", + "nau": "nauru", + "nav": "Navajo", + "ndo": "Ndonga", + "nap": "Napolitansk", + "nia": "Nias", + "niu": "Niuean", + "zxx": "Inget språklig innhold", + "nog": "Nogai", + "nor": "Norsk", + "nob": "Norsk bokmål", + "nno": "Norsk nynorsk", + "nym": "Nyamwezi", + "nya": "Nyanja", + "nyn": "Nyankole", + "nyo": "Nyoro", + "nzi": "Nzima", + "oci": "Occitan (post 1500)", + "oji": "Ojibwa", + "orm": "oromo", + "osa": "Osage", + "oss": "Ossetian", + "pal": "Pahlavi", + "pau": "Palauan", + "pli": "Pali", + "pam": "Pampanga", + "pag": "Pangasinan", + "pan": "Panjabi", + "pap": "Papiamento", + "fas": "Persisk", + "phn": "Phoenician", + "pon": "Pohnpeian", + "pol": "Polsk", + "por": "Portugisisk", + "pus": "Pashto", + "que": "Quechua", + "raj": "Rajasthani", + "rap": "Rapanui", + "ron": "Rumensk", + "roh": "Retoromansk", + "rom": "Romany", + "run": "rundi", + "rus": "Russisk", + "smo": "samoansk", + "sad": "Sandawe", + "sag": "Sango", + "san": "sanskrit", + "sat": "Santali", + "srd": "Sardinsk", + "sas": "Sasak", + "sco": "Scots", + "sel": "Selkup", + "srp": "Serbisk", + "srr": "Serer", + "shn": "Shan", + "sna": "Shona", + "scn": "Siciliansk", + "sid": "sidamo", + "bla": "Siksika", + "snd": "sindhi", + "sin": "Sinhala", + "den": "Slave (Athapascan)", + "slk": "Slovakisk", + "slv": "Slovensk", + "sog": "Sogdian", + "som": "somalisk", + "snk": "Soninke", + "spa": "Spansk", + "srn": "Sranan Tongo", + "suk": "Sukuma", + "sux": "Sumerian", + "sun": "sundanesisk", + "sus": "Susu", + "swa": "Swahili (macrolanguage)", + "ssw": "swati", + "swe": "Svensk", + "syr": "Syriac", + "tgl": "tagalog", + "tah": "Tahitian", + "tgk": "Tajik", + "tmh": "Tamashek", + "tam": "Tamilsk", + "tat": "tatarisk", + "tel": "Telugu", + "ter": "Tereno", + "tet": "Tetum", + "tha": "Thai", + "bod": "tibetansk", + "tig": "Tigre", + "tir": "Tigrinya", + "tem": "Timne", + "tiv": "Tiv", + "tli": "Tlingit", + "tpi": "Tok Pisin", + "tkl": "Tokelau", + "tog": "Tonga (Nyasa)", + "ton": "tonga (Tonga-øyene)", + "tsi": "Tsimshian", + "tso": "tsonga", + "tsn": "tswana", + "tum": "Tumbuka", + "tur": "Tyrkisk", + "tuk": "turkmensk", + "tvl": "Tuvalu", + "tyv": "Tuvinian", + "twi": "twi", + "udm": "Udmurt", + "uga": "Ugaritic", + "uig": "uigurisk", + "ukr": "Ukrainsk", + "umb": "Umbundu", + "mis": "Uncoded languages", + "und": "Undetermined", + "urd": "urdu", + "uzb": "usbekisk", + "vai": "Vai", + "ven": "venda", + "vie": "Vietnamesisk", + "vol": "Volapük", + "vot": "Votic", + "wln": "Walloon", + "war": "Waray (Philippines)", + "was": "Washo", + "cym": "Walisisk", + "wal": "Wolaytta", + "wol": "wolof", + "xho": "Xhosa", + "sah": "Yakut", + "yao": "Yao", + "yap": "Yapese", + "yid": "jiddisk", + "yor": "joruba", + "zap": "Zapotec", + "zza": "Zaza", + "zen": "Zenaga", + "zha": "Zhuang", + "zul": "Zulu", + "zun": "Zuni" + }, "pl": { "aar": "afarski", "abk": "abchaski", @@ -5823,6 +6579,384 @@ LANGUAGE_NAMES = { "zxx": "brak kontekstu językowego", "zza": "zazaki" }, + "pt": { + "abk": "Abcázio", + "ace": "Achém", + "ach": "Acoli", + "ada": "Adangme", + "ady": "Adyghe", + "aar": "Afar", + "afh": "Afrihili", + "afr": "Africânder", + "ain": "Ainu (Japão)", + "aka": "Akan", + "akk": "Acadiano", + "sqi": "Albanês", + "ale": "Aleúte", + "amh": "Amárico", + "anp": "Angika", + "ara": "Arabic", + "arg": "Aragonese", + "arp": "Arapaho", + "arw": "Arawak", + "hye": "Armênio", + "asm": "Assamese", + "ast": "Asturian", + "ava": "Avaric", + "ave": "Avestan", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Azerbaijano", + "ban": "Balinês", + "bal": "Balúchi", + "bam": "Bambara", + "bas": "Basa (Cameroon)", + "bak": "Bashkir", + "eus": "Basque", + "bej": "Beja", + "bel": "Belarusian", + "bem": "Bemba (Zambia)", + "ben": "Bengali", + "bit": "Berinomo", + "bho": "Bhojpuri", + "bik": "Bikol", + "byn": "Bilin", + "bin": "Bini", + "bis": "Bislama", + "zbl": "Blissymbols", + "bos": "Bosnian", + "bra": "Braj", + "bre": "Bretão", + "bug": "Buginese", + "bul": "Búlgaro", + "bua": "Buriat", + "mya": "Birmanês", + "cad": "Caddo", + "cat": "Catalão", + "ceb": "Cebuano", + "chg": "Chagatai", + "cha": "Chamorro", + "che": "Chechen", + "chr": "Cheroqui", + "chy": "Cheyenne", + "chb": "Chibcha", + "zho": "Chinês", + "chn": "Chinook jargon", + "chp": "Chipewyan", + "cho": "Choctaw", + "cht": "Cholón", + "chk": "Chuukese", + "chv": "Chuvash", + "cop": "Coptic", + "cor": "Cornish", + "cos": "Corsican", + "cre": "Cree", + "mus": "Creek", + "hrv": "Croata", + "ces": "Czech", + "dak": "Dacota", + "dan": "Danish", + "dar": "Dargwa", + "del": "Delaware", + "div": "Dhivehi", + "din": "Dinka", + "doi": "Dogri (macrolanguage)", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "Holandês", + "dse": "Língua gestual holandesa", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efik", + "egy": "Egyptian (Ancient)", + "eka": "Ekajuk", + "elx": "Elamite", + "eng": "Inglês", + "enu": "Enu", + "myv": "Erzya", + "epo": "Esperanto", + "est": "Estónio", + "ewe": "Ewe", + "ewo": "Ewondo", + "fan": "Fang (Equatorial Guinea)", + "fat": "Fanti", + "fao": "Faroese", + "fij": "Fijian", + "fil": "Filipino", + "fin": "Finlandês", + "fon": "Fon", + "fra": "Francês", + "fur": "Friuliano", + "ful": "Fulah", + "gaa": "Ga", + "glg": "Galician", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (Central African Republic)", + "hmj": "Ge", + "gez": "Geez", + "kat": "Georgiano", + "deu": "Alemão", + "gil": "Gilbertês", + "gon": "Gondi", + "gor": "Gorontalo", + "got": "Gótico", + "grb": "Grebo", + "grn": "Guarani", + "guj": "Guzerate", + "gwi": "Gwichʼin", + "hai": "Haida", + "hau": "Hauçá", + "haw": "Havaiano", + "heb": "Hebraico", + "her": "Herero", + "hil": "Hiligaynon", + "hin": "Hindi", + "hmo": "Hiri Motu", + "hit": "Hitita", + "hmn": "Hmong", + "hun": "Húngaro", + "hup": "Hupa", + "iba": "Iban", + "isl": "Islandês", + "ido": "Ido", + "ibo": "Igbo", + "ilo": "Ilocano", + "ind": "Indonésio", + "inh": "Ingush", + "ina": "Interlingua (International Auxiliary Language Association)", + "ile": "Interlingue", + "iku": "Inuktitut", + "ipk": "Inupiaq", + "gle": "Irlandês", + "ita": "Italiano", + "jpn": "Japanese", + "jav": "Javanês", + "jrb": "Judeo-Arabic", + "jpr": "Judeo-Persian", + "kbd": "Kabardian", + "kab": "Kabyle", + "kac": "Kachin", + "kal": "Kalaallisut", + "xal": "Kalmyk", + "kam": "Kamba (Quênia)", + "kan": "Canarês", + "kau": "Kanuri", + "kaa": "Kara-Kalpak", + "krc": "Karachay-Balkar", + "krl": "Karelian", + "kas": "Kashmiri", + "csb": "Kashubian", + "kaw": "Kawi", + "kaz": "Cazaque", + "kha": "Khasi", + "kho": "Khotanese", + "kik": "Quicuio", + "kmb": "Quimbundo", + "kin": "Kinyarwanda", + "kir": "Quirguiz", + "tlh": "Klingon", + "kom": "Komi", + "kon": "Quicongo", + "kok": "Konkani (macrolanguage)", + "kor": "Coreano", + "kos": "Kosraean", + "kpe": "Kpelle", + "kua": "Kuanyama", + "kum": "Kumyk", + "kur": "Kurdish", + "kru": "Kurukh", + "kut": "Kutenai", + "lad": "Ladino", + "lah": "Lahnda", + "lam": "Lamba", + "lao": "Laosiano", + "lat": "Latin", + "lav": "Letão", + "lez": "Lezghian", + "lim": "Limburgan", + "lin": "Lingala", + "lit": "Lituano", + "jbo": "Lojban", + "loz": "Lozi", + "lub": "Luba-Catanga", + "lua": "Luba-Lulua", + "lui": "Luiseno", + "smj": "Lule Sami", + "lun": "Lunda", + "luo": "Luo (Kenya and Tanzania)", + "lus": "Lushai", + "ltz": "Luxembourgish", + "mkd": "Macedónio", + "mad": "Madurese", + "mag": "Magahi", + "mai": "Maithili", + "mak": "Makasar", + "mlg": "Malgaxe", + "msa": "Malay (macrolanguage)", + "mal": "Malayalam", + "mlt": "Maltese", + "mnc": "Manchu", + "mdr": "Mandar", + "man": "Mandinga", + "mni": "Manipuri", + "glv": "Manx", + "mri": "Maori", + "arn": "Mapudungun", + "mar": "Marata", + "chm": "Mari (Russia)", + "mah": "Marshallese", + "mwr": "Marwari", + "mas": "Masai", + "men": "Mende (Sierra Leone)", + "mic": "Mi'kmaq", + "min": "Minangkabau", + "mwl": "Mirandês", + "moh": "Mohawk", + "mdf": "Mocsa", + "lol": "Mongo", + "mon": "Mongolian", + "mos": "Mossi", + "mul": "Múltiplos idiomas", + "nqo": "N'Ko", + "nau": "Nauruano", + "nav": "Navajo", + "ndo": "Ndonga", + "nap": "Neapolitan", + "nia": "Nias", + "niu": "Niueano", + "zxx": "Sem conteúdo linguistico", + "nog": "Nogai", + "nor": "Norueguês", + "nob": "Norueguês, Dano", + "nno": "Norueguês, Novo", + "nym": "Nyamwezi", + "nya": "Nyanja", + "nyn": "Nyankole", + "nyo": "Nyoro", + "nzi": "Nzima", + "oci": "Occitan (post 1500)", + "oji": "Ojibwa", + "orm": "Oromo", + "osa": "Osage", + "oss": "Ossetian", + "pal": "Pálavi", + "pau": "Palauano", + "pli": "Pali", + "pam": "Pampanga", + "pag": "Pangasinense", + "pan": "Panjabi", + "pap": "Papiamento", + "fas": "Persian", + "phn": "Fenício", + "pon": "Pohnpeian", + "pol": "Polaco", + "por": "Português", + "pus": "Pushto", + "que": "Quíchua", + "raj": "Rajastani", + "rap": "Rapanui", + "ron": "Romeno", + "roh": "Romansh", + "rom": "Romany", + "run": "Rundi", + "rus": "Russo", + "smo": "Samoan", + "sad": "Sandawe", + "sag": "Sango", + "san": "Sanskrit", + "sat": "Santali", + "srd": "Sardinian", + "sas": "Sasak", + "sco": "Scots", + "sel": "Selkup", + "srp": "Sérvio", + "srr": "Serere", + "shn": "Shan", + "sna": "Shona", + "scn": "Sicilian", + "sid": "Sidamo", + "bla": "Siksika", + "snd": "Sindi", + "sin": "Cingalês", + "den": "Slave (Athapascan)", + "slk": "Eslovaco", + "slv": "Esloveno", + "sog": "Sogdian", + "som": "Somali", + "snk": "Soninke", + "spa": "Espanhol", + "srn": "Sranan Tongo", + "suk": "Sukuma", + "sux": "Sumerian", + "sun": "Sudanês", + "sus": "Sosso", + "swa": "Swahili (macrolanguage)", + "ssw": "Swati", + "swe": "Sueco", + "syr": "Siríaco", + "tgl": "Tagaloge", + "tah": "Tahitian", + "tgk": "Tajik", + "tmh": "Tamaxeque", + "tam": "Tamil", + "tat": "Tatar", + "tel": "Telugu", + "ter": "Tereno", + "tet": "Tétum", + "tha": "Tailandês", + "bod": "Tibetano", + "tig": "Tigre", + "tir": "Tigrinya", + "tem": "Timne", + "tiv": "Tiv", + "tli": "Tlingit", + "tpi": "Tok Pisin", + "tkl": "Toquelauano", + "tog": "Toganês (Nyasa)", + "ton": "Tonga (ilhas tonga)", + "tsi": "Tsimshian", + "tso": "Tsonga", + "tsn": "Tswana", + "tum": "Tumbuka", + "tur": "Turco", + "tuk": "Turcomano", + "tvl": "Tuvaluano", + "tyv": "Tuvinian", + "twi": "Twi", + "udm": "Udmurt", + "uga": "Ugarítico", + "uig": "Uighur", + "ukr": "Ucraniano", + "umb": "Umbundu", + "mis": "Idiomas sem código", + "und": "Não identificável", + "urd": "Urdu", + "uzb": "Usbeque", + "vai": "Vai", + "ven": "Venda", + "vie": "Vietnamita", + "vol": "Volapük", + "vot": "Votic", + "wln": "Walloon", + "war": "Waray (Philippines)", + "was": "Washo", + "cym": "Galês", + "wal": "Wolaytta", + "wol": "Uolofe", + "xho": "Xosa", + "sah": "Iacuto", + "yao": "Iao", + "yap": "Yapese", + "yid": "Ídiche", + "yor": "Iorubá", + "zap": "Zapoteca", + "zza": "Zaza", + "zen": "Zenaga", + "zha": "Zhuang", + "zul": "Zulu", + "zun": "Zuni" + }, "pt_BR": { "abk": "Abcázio", "ace": "Achém", @@ -6626,6 +7760,384 @@ LANGUAGE_NAMES = { "zxx": "Нет языкового содержимого", "zza": "Зазаки" }, + "sk": { + "abk": "Abkhazian", + "ace": "Achinese", + "ach": "Acoli", + "ada": "Adangme", + "ady": "Adyghe", + "aar": "Afar", + "afh": "Afrihili", + "afr": "Afrikánsky", + "ain": "Ainu (Japan)", + "aka": "Akan", + "akk": "Akkadian", + "sqi": "Albanian", + "ale": "Aleut", + "amh": "Amharic", + "anp": "Angika", + "ara": "Arabská", + "arg": "Aragonese", + "arp": "Arapaho", + "arw": "Arawak", + "hye": "Arménčina", + "asm": "Assamese", + "ast": "Asturian", + "ava": "Avaric", + "ave": "Avestan", + "awa": "Awadhi", + "aym": "Aymara", + "aze": "Ázerbajdžánsky", + "ban": "Balinese", + "bal": "Baluchi", + "bam": "Bambara", + "bas": "Basa (Cameroon)", + "bak": "Bashkir", + "eus": "Baskitský", + "bej": "Beja", + "bel": "Belarusian", + "bem": "Bemba (Zambia)", + "ben": "Bengali", + "bit": "Berinomo", + "bho": "Bhojpuri", + "bik": "Bikol", + "byn": "Bilin", + "bin": "Bini", + "bis": "Bislama", + "zbl": "Blissymbols", + "bos": "Bosnian", + "bra": "Braj", + "bre": "Bretónsky", + "bug": "Buginese", + "bul": "Bulharský", + "bua": "Buriat", + "mya": "Burmese", + "cad": "Caddo", + "cat": "Katalánsky", + "ceb": "Cebuano", + "chg": "Chagatai", + "cha": "Chamorro", + "che": "Chechen", + "chr": "Cherokee", + "chy": "Cheyenne", + "chb": "Chibcha", + "zho": "Čínsky", + "chn": "Chinook jargon", + "chp": "Chipewyan", + "cho": "Choctaw", + "cht": "Cholón", + "chk": "Chuukese", + "chv": "Chuvash", + "cop": "Coptic", + "cor": "Cornish", + "cos": "Corsican", + "cre": "Cree", + "mus": "Creek", + "hrv": "Chorvátsky", + "ces": "Český", + "dak": "Dakota", + "dan": "Dánsky", + "dar": "Dargwa", + "del": "Delaware", + "div": "Dhivehi", + "din": "Dinka", + "doi": "Dogri (macrolanguage)", + "dgr": "Dogrib", + "dua": "Duala", + "nld": "Holandský", + "dse": "Dutch Sign Language", + "dyu": "Dyula", + "dzo": "Dzongkha", + "efi": "Efik", + "egy": "Egyptian (Ancient)", + "eka": "Ekajuk", + "elx": "Elamite", + "eng": "Angličtina", + "enu": "Enu", + "myv": "Erzya", + "epo": "Esperanto", + "est": "Estónsky", + "ewe": "Ewe", + "ewo": "Ewondo", + "fan": "Fang (Equatorial Guinea)", + "fat": "Fanti", + "fao": "Faroese", + "fij": "Fijian", + "fil": "Filipino", + "fin": "Fínsky", + "fon": "Fon", + "fra": "Francúzsky", + "fur": "Friulian", + "ful": "Fulah", + "gaa": "Ga", + "glg": "Galician", + "lug": "Ganda", + "gay": "Gayo", + "gba": "Gbaya (Central African Republic)", + "hmj": "Ge", + "gez": "Geez", + "kat": "Georgian", + "deu": "Nemecký", + "gil": "Gilbertese", + "gon": "Gondi", + "gor": "Gorontalo", + "got": "Gothic", + "grb": "Grebo", + "grn": "Guarani", + "guj": "Gujarati", + "gwi": "Gwichʼin", + "hai": "Haida", + "hau": "Hausa", + "haw": "Hawaiian", + "heb": "Hebrejský", + "her": "Herero", + "hil": "Hiligaynon", + "hin": "Hindi", + "hmo": "Hiri Motu", + "hit": "Hittite", + "hmn": "Hmong", + "hun": "Maďarský", + "hup": "Hupa", + "iba": "Iban", + "isl": "Islandský", + "ido": "Ido", + "ibo": "Igbo", + "ilo": "Iloko", + "ind": "Indonézsky", + "inh": "Ingush", + "ina": "Interlingua (International Auxiliary Language Association)", + "ile": "Interlingue", + "iku": "Inuktitut", + "ipk": "Inupiaq", + "gle": "Írsky", + "ita": "Taliansky", + "jpn": "Japonský", + "jav": "Javanese", + "jrb": "Judeo-Arabic", + "jpr": "Judeo-Persian", + "kbd": "Kabardian", + "kab": "Kabyle", + "kac": "Kachin", + "kal": "Kalaallisut", + "xal": "Kalmyk", + "kam": "Kamba (Kenya)", + "kan": "Kannada", + "kau": "Kanuri", + "kaa": "Kara-Kalpak", + "krc": "Karachay-Balkar", + "krl": "Karelian", + "kas": "Kashmiri", + "csb": "Kashubian", + "kaw": "Kawi", + "kaz": "Kazakh", + "kha": "Khasi", + "kho": "Khotanese", + "kik": "Kikuyu", + "kmb": "Kimbundu", + "kin": "Kinyarwanda", + "kir": "Kirghiz", + "tlh": "Klingon", + "kom": "Komi", + "kon": "Kongo", + "kok": "Konkani (macrolanguage)", + "kor": "Kórejský", + "kos": "Kosraean", + "kpe": "Kpelle", + "kua": "Kuanyama", + "kum": "Kumyk", + "kur": "Kurdský", + "kru": "Kurukh", + "kut": "Kutenai", + "lad": "Ladino", + "lah": "Lahnda", + "lam": "Lamba", + "lao": "Lao", + "lat": "Latin", + "lav": "Latvian", + "lez": "Lezghian", + "lim": "Limburgan", + "lin": "Lingala", + "lit": "Lotyšský", + "jbo": "Lojban", + "loz": "Lozi", + "lub": "Luba-Katanga", + "lua": "Luba-Lulua", + "lui": "Luiseno", + "smj": "Lule Sami", + "lun": "Lunda", + "luo": "Luo (Kenya and Tanzania)", + "lus": "Lushai", + "ltz": "Luxembourgish", + "mkd": "Macedónsky", + "mad": "Madurese", + "mag": "Magahi", + "mai": "Maithili", + "mak": "Makasar", + "mlg": "Malagasy", + "msa": "Malay (macrolanguage)", + "mal": "Malayalam", + "mlt": "Maltézsky", + "mnc": "Manchu", + "mdr": "Mandar", + "man": "Mandingo", + "mni": "Manipuri", + "glv": "Manx", + "mri": "Maori", + "arn": "Mapudungun", + "mar": "Marathi", + "chm": "Mari (Russia)", + "mah": "Marshallese", + "mwr": "Marwari", + "mas": "Masai", + "men": "Mende (Sierra Leone)", + "mic": "Mi'kmaq", + "min": "Minangkabau", + "mwl": "Mirandese", + "moh": "Mohawk", + "mdf": "Moksha", + "lol": "Mongo", + "mon": "Mongolian", + "mos": "Mossi", + "mul": "Multiple languages", + "nqo": "N'Ko", + "nau": "Nauru", + "nav": "Navajo", + "ndo": "Ndonga", + "nap": "Neapolitan", + "nia": "Nias", + "niu": "Niuean", + "zxx": "No linguistic content", + "nog": "Nogai", + "nor": "Norwegian", + "nob": "Norwegian Bokmål", + "nno": "Norwegian Nynorsk", + "nym": "Nyamwezi", + "nya": "Nyanja", + "nyn": "Nyankole", + "nyo": "Nyoro", + "nzi": "Nzima", + "oci": "Occitan (post 1500)", + "oji": "Ojibwa", + "orm": "Oromo", + "osa": "Osage", + "oss": "Ossetian", + "pal": "Pahlavi", + "pau": "Palauan", + "pli": "Pali", + "pam": "Pampanga", + "pag": "Pangasinan", + "pan": "Panjabi", + "pap": "Papiamento", + "fas": "Persian", + "phn": "Phoenician", + "pon": "Pohnpeian", + "pol": "Poľský", + "por": "Portugalský", + "pus": "Pashto", + "que": "Quechua", + "raj": "Rajasthani", + "rap": "Rapanui", + "ron": "Rumunský", + "roh": "Romansh", + "rom": "Romany", + "run": "Rundi", + "rus": "Ruský", + "smo": "Samoan", + "sad": "Sandawe", + "sag": "Sango", + "san": "Sanskrit", + "sat": "Santali", + "srd": "Sardinian", + "sas": "Sasak", + "sco": "Scots", + "sel": "Selkup", + "srp": "Srbský", + "srr": "Serer", + "shn": "Shan", + "sna": "Shona", + "scn": "Sicilian", + "sid": "Sidamo", + "bla": "Siksika", + "snd": "Sindhi", + "sin": "Sinhala", + "den": "Slave (Athapascan)", + "slk": "Slovenský", + "slv": "Slovinský", + "sog": "Sogdian", + "som": "Somali", + "snk": "Soninke", + "spa": "Španielsky", + "srn": "Sranan Tongo", + "suk": "Sukuma", + "sux": "Sumerian", + "sun": "Sundanese", + "sus": "Susu", + "swa": "Swahili (macrolanguage)", + "ssw": "Swati", + "swe": "Švédsky", + "syr": "Syriac", + "tgl": "Tagalog", + "tah": "Tahitian", + "tgk": "Tajik", + "tmh": "Tamashek", + "tam": "Tamilský", + "tat": "Tatar", + "tel": "Telugu", + "ter": "Tereno", + "tet": "Tetum", + "tha": "Thajský", + "bod": "Tibetan", + "tig": "Tigre", + "tir": "Tigrinya", + "tem": "Timne", + "tiv": "Tiv", + "tli": "Tlingit", + "tpi": "Tok Pisin", + "tkl": "Tokelau", + "tog": "Tonga (Nyasa)", + "ton": "Tonga (Tonga Islands)", + "tsi": "Tsimshian", + "tso": "Tsonga", + "tsn": "Tswana", + "tum": "Tumbuka", + "tur": "Turecký", + "tuk": "Turkmen", + "tvl": "Tuvalu", + "tyv": "Tuvinian", + "twi": "Twi", + "udm": "Udmurt", + "uga": "Ugaritic", + "uig": "Uighur", + "ukr": "Ukrainian", + "umb": "Umbundu", + "mis": "Uncoded languages", + "und": "Undetermined", + "urd": "Urdu", + "uzb": "Uzbek", + "vai": "Vai", + "ven": "Venda", + "vie": "Vietnamský", + "vol": "Volapük", + "vot": "Votic", + "wln": "Vallónsky", + "war": "Waray (Philippines)", + "was": "Washo", + "cym": "Welšský", + "wal": "Wolaytta", + "wol": "Wolof", + "xho": "Xhosa", + "sah": "Yakut", + "yao": "Yao", + "yap": "Yapese", + "yid": "Yiddish", + "yor": "Yoruba", + "zap": "Zapotec", + "zza": "Zaza", + "zen": "Zenaga", + "zha": "Zhuang", + "zul": "Zulu", + "zun": "Zuni" + }, "sv": { "aar": "Afar", "abk": "Abchaziska", diff --git a/cps/kobo.py b/cps/kobo.py index 8ab1e47b..76530797 100644 --- a/cps/kobo.py +++ b/cps/kobo.py @@ -21,6 +21,7 @@ import base64 import datetime import os import uuid +import zipfile from time import gmtime, strftime import json from urllib.parse import unquote @@ -46,7 +47,8 @@ import requests from . import config, logger, kobo_auth, db, calibre_db, helper, shelf as shelf_lib, ub, csrf, kobo_sync_status from . import isoLanguages -from .constants import sqlalchemy_version2, COVER_THUMBNAIL_SMALL +from .epub import get_epub_layout +from .constants import COVER_THUMBNAIL_SMALL #, sqlalchemy_version2 from .helper import get_download_link from .services import SyncToken as SyncToken from .web import download_required @@ -54,7 +56,7 @@ from .kobo_auth import requires_kobo_auth, get_auth_token KOBO_FORMATS = {"KEPUB": ["KEPUB"], "EPUB": ["EPUB3", "EPUB"]} KOBO_STOREAPI_URL = "https://storeapi.kobo.com" -KOBO_IMAGEHOST_URL = "https://kbimages1-a.akamaihd.net" +KOBO_IMAGEHOST_URL = "https://cdn.kobo.com/book-images" SYNC_ITEM_LIMIT = 100 @@ -140,6 +142,7 @@ def HandleSyncRequest(): sync_token = SyncToken.SyncToken.from_headers(request.headers) log.info("Kobo library sync request received.") log.debug("SyncToken: {}".format(sync_token)) + log.debug("Download link format {}".format(get_download_url_for_book('[bookid]','[bookformat]'))) if not current_app.wsgi_app.is_proxied: log.debug('Kobo: Received unproxied request, changed request port to external server port') @@ -163,16 +166,10 @@ def HandleSyncRequest(): only_kobo_shelves = current_user.kobo_only_shelves_sync if only_kobo_shelves: - if sqlalchemy_version2: - changed_entries = select(db.Books, - ub.ArchivedBook.last_modified, - ub.BookShelf.date_added, - ub.ArchivedBook.is_archived) - else: - changed_entries = calibre_db.session.query(db.Books, - ub.ArchivedBook.last_modified, - ub.BookShelf.date_added, - ub.ArchivedBook.is_archived) + changed_entries = calibre_db.session.query(db.Books, + ub.ArchivedBook.last_modified, + ub.BookShelf.date_added, + ub.ArchivedBook.is_archived) changed_entries = (changed_entries .join(db.Data).outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id, ub.ArchivedBook.user_id == current_user.id)) @@ -189,12 +186,9 @@ def HandleSyncRequest(): .filter(ub.Shelf.kobo_sync) .distinct()) else: - if sqlalchemy_version2: - changed_entries = select(db.Books, ub.ArchivedBook.last_modified, ub.ArchivedBook.is_archived) - else: - changed_entries = calibre_db.session.query(db.Books, - ub.ArchivedBook.last_modified, - ub.ArchivedBook.is_archived) + changed_entries = calibre_db.session.query(db.Books, + ub.ArchivedBook.last_modified, + ub.ArchivedBook.is_archived) changed_entries = (changed_entries .join(db.Data).outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id, ub.ArchivedBook.user_id == current_user.id)) @@ -206,10 +200,7 @@ def HandleSyncRequest(): .order_by(db.Books.id)) reading_states_in_new_entitlements = [] - if sqlalchemy_version2: - books = calibre_db.session.execute(changed_entries.limit(SYNC_ITEM_LIMIT)) - else: - books = changed_entries.limit(SYNC_ITEM_LIMIT) + books = changed_entries.limit(SYNC_ITEM_LIMIT) log.debug("Books to Sync: {}".format(len(books.all()))) for book in books: formats = [data.format for data in book.Books.data] @@ -227,7 +218,7 @@ def HandleSyncRequest(): new_reading_state_last_modified = max(new_reading_state_last_modified, kobo_reading_state.last_modified) reading_states_in_new_entitlements.append(book.Books.id) - ts_created = book.Books.timestamp + ts_created = book.Books.timestamp.replace(tzinfo=None) try: ts_created = max(ts_created, book.date_added) @@ -240,7 +231,7 @@ def HandleSyncRequest(): sync_results.append({"ChangedEntitlement": entitlement}) new_books_last_modified = max( - book.Books.last_modified, new_books_last_modified + book.Books.last_modified.replace(tzinfo=None), new_books_last_modified ) try: new_books_last_modified = max( @@ -252,27 +243,16 @@ def HandleSyncRequest(): new_books_last_created = max(ts_created, new_books_last_created) kobo_sync_status.add_synced_books(book.Books.id) - if sqlalchemy_version2: - max_change = calibre_db.session.execute(changed_entries - .filter(ub.ArchivedBook.is_archived) - .filter(ub.ArchivedBook.user_id == current_user.id) - .order_by(func.datetime(ub.ArchivedBook.last_modified).desc()))\ - .columns(db.Books).first() - else: - max_change = changed_entries.from_self().filter(ub.ArchivedBook.is_archived)\ - .filter(ub.ArchivedBook.user_id == current_user.id) \ - .order_by(func.datetime(ub.ArchivedBook.last_modified).desc()).first() + max_change = changed_entries.filter(ub.ArchivedBook.is_archived)\ + .filter(ub.ArchivedBook.user_id == current_user.id) \ + .order_by(func.datetime(ub.ArchivedBook.last_modified).desc()).first() max_change = max_change.last_modified if max_change else new_archived_last_modified new_archived_last_modified = max(new_archived_last_modified, max_change) # no. of books returned - if sqlalchemy_version2: - entries = calibre_db.session.execute(changed_entries).all() - book_count = len(entries) - else: - book_count = changed_entries.count() + book_count = changed_entries.count() # last entry: cont_sync = bool(book_count) log.debug("Remaining books to Sync: {}".format(book_count)) @@ -335,7 +315,7 @@ def generate_sync_response(sync_token, sync_results, set_cont=False): extra_headers["x-kobo-recent-reads"] = store_response.headers.get("x-kobo-recent-reads") except Exception as ex: - log.error("Failed to receive or parse response from Kobo's sync endpoint: {}".format(ex)) + log.error_or_exception("Failed to receive or parse response from Kobo's sync endpoint: {}".format(ex)) if set_cont: extra_headers["x-kobo-sync"] = "continue" sync_token.to_headers(extra_headers) @@ -356,7 +336,7 @@ def HandleMetadataRequest(book_uuid): log.info("Kobo library metadata request received for book %s" % book_uuid) book = calibre_db.get_book_by_uuid(book_uuid) if not book or not book.data: - log.info(u"Book %s not found in database", book_uuid) + log.info("Book %s not found in database", book_uuid) return redirect_or_proxy_request() metadata = get_metadata(book) @@ -365,7 +345,7 @@ def HandleMetadataRequest(book_uuid): return response -def get_download_url_for_book(book, book_format): +def get_download_url_for_book(book_id, book_format): if not current_app.wsgi_app.is_proxied: if ':' in request.host and not request.host.endswith(']'): host = "".join(request.host.split(':')[:-1]) @@ -377,13 +357,13 @@ def get_download_url_for_book(book, book_format): url_base=host, url_port=config.config_external_port, auth_token=get_auth_token(), - book_id=book.id, + book_id=book_id, book_format=book_format.lower() ) return url_for( "kobo.download_book", auth_token=kobo_auth.get_auth_token(), - book_id=book.id, + book_id=book_id, book_format=book_format.lower(), _external=True, ) @@ -459,16 +439,21 @@ def get_metadata(book): continue for kobo_format in KOBO_FORMATS[book_data.format]: # log.debug('Id: %s, Format: %s' % (book.id, kobo_format)) - download_urls.append( - { - "Format": kobo_format, - "Size": book_data.uncompressed_size, - "Url": get_download_url_for_book(book, book_data.format), - # The Kobo forma accepts platforms: (Generic, Android) - "Platform": "Generic", - # "DrmType": "None", # Not required - } - ) + try: + if get_epub_layout(book, book_data) == 'pre-paginated': + kobo_format = 'EPUB3FL' + download_urls.append( + { + "Format": kobo_format, + "Size": book_data.uncompressed_size, + "Url": get_download_url_for_book(book.id, book_data.format), + # The Kobo forma accepts platforms: (Generic, Android) + "Platform": "Generic", + # "DrmType": "None", # Not required + } + ) + except (zipfile.BadZipfile, FileNotFoundError) as e: + log.error(e) book_uuid = book.uuid metadata = { @@ -515,7 +500,7 @@ def get_metadata(book): @requires_kobo_auth # Creates a Shelf with the given items, and returns the shelf's uuid. def HandleTagCreate(): - # catch delete requests, otherwise the are handled in the book delete handler + # catch delete requests, otherwise they are handled in the book delete handler if request.method == "DELETE": abort(405) name, items = None, None @@ -709,20 +694,12 @@ def sync_shelves(sync_token, sync_results, only_kobo_shelves=False): }) extra_filters.append(ub.Shelf.kobo_sync) - if sqlalchemy_version2: - shelflist = ub.session.execute(select(ub.Shelf).outerjoin(ub.BookShelf).filter( - or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified, - func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified), - ub.Shelf.user_id == current_user.id, - *extra_filters - ).distinct().order_by(func.datetime(ub.Shelf.last_modified).asc())).columns(ub.Shelf) - else: - shelflist = ub.session.query(ub.Shelf).outerjoin(ub.BookShelf).filter( - or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified, - func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified), - ub.Shelf.user_id == current_user.id, - *extra_filters - ).distinct().order_by(func.datetime(ub.Shelf.last_modified).asc()) + shelflist = ub.session.query(ub.Shelf).outerjoin(ub.BookShelf).filter( + or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified, + func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified), + ub.Shelf.user_id == current_user.id, + *extra_filters + ).distinct().order_by(func.datetime(ub.Shelf.last_modified).asc()) for shelf in shelflist: if not shelf_lib.check_shelf_view_permissions(shelf): @@ -759,7 +736,7 @@ def create_kobo_tag(shelf): for book_shelf in shelf.books: book = calibre_db.get_book(book_shelf.book_id) if not book: - log.info(u"Book (id: %s) in BookShelf (id: %s) not found in book database", book_shelf.book_id, shelf.id) + log.info("Book (id: %s) in BookShelf (id: %s) not found in book database", book_shelf.book_id, shelf.id) continue tag["Items"].append( { @@ -776,7 +753,7 @@ def create_kobo_tag(shelf): def HandleStateRequest(book_uuid): book = calibre_db.get_book_by_uuid(book_uuid) if not book or not book.data: - log.info(u"Book %s not found in database", book_uuid) + log.info("Book %s not found in database", book_uuid) return redirect_or_proxy_request() kobo_reading_state = get_or_create_reading_state(book.id) @@ -923,20 +900,26 @@ def get_current_bookmark_response(current_bookmark): @kobo.route("//////image.jpg") @requires_kobo_auth def HandleCoverImageRequest(book_uuid, width, height, Quality, isGreyscale): - book_cover = helper.get_book_cover_with_uuid(book_uuid, resolution=COVER_THUMBNAIL_SMALL) - if not book_cover: - if config.config_kobo_proxy: - log.debug("Cover for unknown book: %s proxied to kobo" % book_uuid) - return redirect(KOBO_IMAGEHOST_URL + - "/{book_uuid}/{width}/{height}/false/image.jpg".format(book_uuid=book_uuid, - width=width, - height=height), 307) - else: - log.debug("Cover for unknown book: %s requested" % book_uuid) - # additional proxy request make no sense, -> direct return - return make_response(jsonify({})) - log.debug("Cover request received for book %s" % book_uuid) - return book_cover + try: + resolution = None if int(height) > 1000 else COVER_THUMBNAIL_SMALL + except ValueError: + log.error("Requested height %s of book %s is invalid" % (book_uuid, height)) + resolution = COVER_THUMBNAIL_SMALL + book_cover = helper.get_book_cover_with_uuid(book_uuid, resolution=resolution) + if book_cover: + log.debug("Serving local cover image of book %s" % book_uuid) + return book_cover + + if not config.config_kobo_proxy: + log.debug("Returning 404 for cover image of unknown book %s" % book_uuid) + # additional proxy request make no sense, -> direct return + return abort(404) + + log.debug("Redirecting request for cover image of unknown book %s to Kobo" % book_uuid) + return redirect(KOBO_IMAGEHOST_URL + + "/{book_uuid}/{width}/{height}/false/image.jpg".format(book_uuid=book_uuid, + width=width, + height=height), 307) @kobo.route("") @@ -951,7 +934,7 @@ def HandleBookDeletionRequest(book_uuid): log.info("Kobo book delete request received for book %s" % book_uuid) book = calibre_db.get_book_by_uuid(book_uuid) if not book: - log.info(u"Book %s not found in database", book_uuid) + log.info("Book %s not found in database", book_uuid) return redirect_or_proxy_request() book_id = book.id @@ -976,6 +959,7 @@ def HandleUnimplementedRequest(dummy=None): @kobo.route("/v1/user/wishlist", methods=["GET", "POST"]) @kobo.route("/v1/user/recommendations", methods=["GET", "POST"]) @kobo.route("/v1/analytics/", methods=["GET", "POST"]) +@kobo.route("/v1/assets", methods=["GET"]) def HandleUserRequest(dummy=None): log.debug("Unimplemented User Request received: %s (request is forwarded to kobo if configured)", request.base_url) return redirect_or_proxy_request() @@ -1034,7 +1018,7 @@ def make_calibre_web_auth_response(): "RefreshToken": RefreshToken, "TokenType": "Bearer", "TrackingId": str(uuid.uuid4()), - "UserKey": content['UserKey'], + "UserKey": content.get('UserKey',""), } ) ) diff --git a/cps/kobo_auth.py b/cps/kobo_auth.py index ea9b71b1..3736e4e1 100644 --- a/cps/kobo_auth.py +++ b/cps/kobo_auth.py @@ -64,11 +64,12 @@ from datetime import datetime from os import urandom from functools import wraps -from flask import g, Blueprint, url_for, abort, request +from flask import g, Blueprint, abort, request from flask_login import login_user, current_user, login_required from flask_babel import gettext as _ +from flask_limiter import RateLimitExceeded -from . import logger, config, calibre_db, db, helper, ub, lm +from . import logger, config, calibre_db, db, helper, ub, lm, limiter from .render_template import render_title_template log = logger.create() @@ -112,7 +113,7 @@ def generate_auth_token(user_id): return render_title_template( "generate_kobo_auth_url.html", - title=_(u"Kobo Setup"), + title=_("Kobo Setup"), auth_token=auth_token.auth_token, warning = warning ) @@ -151,6 +152,10 @@ def requires_kobo_auth(f): def inner(*args, **kwargs): auth_token = get_auth_token() if auth_token is not None: + try: + limiter.check() + except RateLimitExceeded: + return abort(429) user = ( ub.session.query(ub.User) .join(ub.RemoteAuthToken) @@ -159,7 +164,8 @@ def requires_kobo_auth(f): ) if user is not None: login_user(user) + [limiter.limiter.storage.clear(k.key) for k in limiter.current_limits] return f(*args, **kwargs) - log.debug("Received Kobo request without a recognizable auth token.") - return abort(401) + log.debug("Received Kobo request without a recognizable auth token.") + return abort(401) return inner diff --git a/cps/logger.py b/cps/logger.py index 13535efb..74f7fb39 100644 --- a/cps/logger.py +++ b/cps/logger.py @@ -150,7 +150,7 @@ def setup(log_file, log_level=None): else: try: file_handler = RotatingFileHandler(log_file, maxBytes=100000, backupCount=2, encoding='utf-8') - except IOError: + except (IOError, PermissionError): if log_file == DEFAULT_LOG_FILE: raise file_handler = RotatingFileHandler(DEFAULT_LOG_FILE, maxBytes=100000, backupCount=2, encoding='utf-8') @@ -177,7 +177,7 @@ def create_access_log(log_file, log_name, formatter): access_log.setLevel(logging.INFO) try: file_handler = RotatingFileHandler(log_file, maxBytes=50000, backupCount=2, encoding='utf-8') - except IOError: + except (IOError, PermissionError): if log_file == DEFAULT_ACCESS_LOG: raise file_handler = RotatingFileHandler(DEFAULT_ACCESS_LOG, maxBytes=50000, backupCount=2, encoding='utf-8') diff --git a/cps/main.py b/cps/main.py index d3591c06..286b2b27 100644 --- a/cps/main.py +++ b/cps/main.py @@ -18,9 +18,14 @@ import sys -from . import create_app +from . import create_app, limiter from .jinjia import jinjia from .remotelogin import remotelogin +from flask import request + + +def request_username(): + return request.authorization.username def main(): app = create_app() @@ -39,6 +44,7 @@ def main(): try: from .kobo import kobo, get_kobo_activated from .kobo_auth import kobo_auth + from flask_limiter.util import get_remote_address kobo_available = get_kobo_activated() except (ImportError, AttributeError): # Catch also error for not installed flask-WTF (missing csrf decorator) kobo_available = False @@ -56,6 +62,7 @@ def main(): app.register_blueprint(tasks) app.register_blueprint(web) app.register_blueprint(opds) + limiter.limit("3/minute",key_func=request_username)(opds) app.register_blueprint(jinjia) app.register_blueprint(about) app.register_blueprint(shelf) @@ -67,6 +74,7 @@ def main(): if kobo_available: app.register_blueprint(kobo) app.register_blueprint(kobo_auth) + limiter.limit("3/minute", key_func=get_remote_address)(kobo) if oauth_available: app.register_blueprint(oauth) success = web_server.start() diff --git a/cps/metadata_provider/amazon.py b/cps/metadata_provider/amazon.py index da3aed79..30291a3f 100644 --- a/cps/metadata_provider/amazon.py +++ b/cps/metadata_provider/amazon.py @@ -63,11 +63,11 @@ class Amazon(Metadata): r.raise_for_status() except Exception as ex: log.warning(ex) - return + return None long_soup = BS(r.text, "lxml") #~4sec :/ soup2 = long_soup.find("div", attrs={"cel_widget_id": "dpx-books-ppd_csm_instrumentation_wrapper"}) if soup2 is None: - return + return None try: match = MetaRecord( title = "", @@ -98,7 +98,7 @@ class Amazon(Metadata): try: match.authors = [next( filter(lambda i: i != " " and i != "\n" and not i.startswith("{"), - x.findAll(text=True))).strip() + x.findAll(string=True))).strip() for x in soup2.findAll("span", attrs={"class": "author"})] except (AttributeError, TypeError, StopIteration): match.authors = "" @@ -115,7 +115,7 @@ class Amazon(Metadata): return match, index except Exception as e: log.error_or_exception(e) - return + return None val = list() if self.active: @@ -127,10 +127,10 @@ class Amazon(Metadata): results.raise_for_status() except requests.exceptions.HTTPError as e: log.error_or_exception(e) - return None + return [] except Exception as e: log.warning(e) - return None + return [] soup = BS(results.text, 'html.parser') links_list = [next(filter(lambda i: "digital-text" in i["href"], x.findAll("a")))["href"] for x in soup.findAll("div", attrs={"data-component-type": "s-search-result"})] diff --git a/cps/metadata_provider/douban.py b/cps/metadata_provider/douban.py index ee21f587..39c71cc7 100644 --- a/cps/metadata_provider/douban.py +++ b/cps/metadata_provider/douban.py @@ -43,7 +43,8 @@ class Douban(Metadata): __id__ = "douban" DESCRIPTION = "豆瓣" META_URL = "https://book.douban.com/" - SEARCH_URL = "https://www.douban.com/j/search" + SEARCH_JSON_URL = "https://www.douban.com/j/search" + SEARCH_URL = "https://www.douban.com/search" ID_PATTERN = re.compile(r"sid: (?P\d+),") AUTHORS_PATTERN = re.compile(r"作者|译者") @@ -52,6 +53,7 @@ class Douban(Metadata): PUBLISHED_DATE_PATTERN = re.compile(r"出版年") SERIES_PATTERN = re.compile(r"丛书") IDENTIFIERS_PATTERN = re.compile(r"ISBN|统一书号") + CRITERIA_PATTERN = re.compile("criteria = '(.+)'") TITTLE_XPATH = "//span[@property='v:itemreviewed']" COVER_XPATH = "//a[@class='nbg']" @@ -63,56 +65,90 @@ class Douban(Metadata): session = requests.Session() session.headers = { 'user-agent': - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.56', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.56', } - def search( - self, query: str, generic_cover: str = "", locale: str = "en" - ) -> Optional[List[MetaRecord]]: + def search(self, + query: str, + generic_cover: str = "", + locale: str = "en") -> List[MetaRecord]: + val = [] if self.active: - log.debug(f"starting search {query} on douban") + log.debug(f"start searching {query} on douban") if title_tokens := list( - self.get_title_tokens(query, strip_joiners=False) - ): + self.get_title_tokens(query, strip_joiners=False)): query = "+".join(title_tokens) - try: - r = self.session.get( - self.SEARCH_URL, params={"cat": 1001, "q": query} - ) - r.raise_for_status() + book_id_list = self._get_book_id_list_from_html(query) - except Exception as e: - log.warning(e) - return None - - results = r.json() - if results["total"] == 0: + if not book_id_list: + log.debug("No search results in Douban") return [] - book_id_list = [ - self.ID_PATTERN.search(item).group("id") - for item in results["items"][:10] if self.ID_PATTERN.search(item) - ] - - with futures.ThreadPoolExecutor(max_workers=5) as executor: + with futures.ThreadPoolExecutor( + max_workers=5, thread_name_prefix='douban') as executor: fut = [ - executor.submit(self._parse_single_book, book_id, generic_cover) - for book_id in book_id_list + executor.submit(self._parse_single_book, book_id, + generic_cover) for book_id in book_id_list ] - + val = [ - future.result() - for future in futures.as_completed(fut) if future.result() + future.result() for future in futures.as_completed(fut) + if future.result() ] return val - def _parse_single_book( - self, id: str, generic_cover: str = "" - ) -> Optional[MetaRecord]: + def _get_book_id_list_from_html(self, query: str) -> List[str]: + try: + r = self.session.get(self.SEARCH_URL, + params={ + "cat": 1001, + "q": query + }) + r.raise_for_status() + + except Exception as e: + log.warning(e) + return [] + + html = etree.HTML(r.content.decode("utf8")) + result_list = html.xpath(self.COVER_XPATH) + + return [ + self.ID_PATTERN.search(item.get("onclick")).group("id") + for item in result_list[:10] + if self.ID_PATTERN.search(item.get("onclick")) + ] + + def _get_book_id_list_from_json(self, query: str) -> List[str]: + try: + r = self.session.get(self.SEARCH_JSON_URL, + params={ + "cat": 1001, + "q": query + }) + r.raise_for_status() + + except Exception as e: + log.warning(e) + return [] + + results = r.json() + if results["total"] == 0: + return [] + + return [ + self.ID_PATTERN.search(item).group("id") + for item in results["items"][:10] if self.ID_PATTERN.search(item) + ] + + def _parse_single_book(self, + id: str, + generic_cover: str = "") -> Optional[MetaRecord]: url = f"https://book.douban.com/subject/{id}/" + log.debug(f"start parsing {url}") try: r = self.session.get(url) @@ -133,10 +169,12 @@ class Douban(Metadata): ), ) - html = etree.HTML(r.content.decode("utf8")) + decode_content = r.content.decode("utf8") + html = etree.HTML(decode_content) match.title = html.xpath(self.TITTLE_XPATH)[0].text - match.cover = html.xpath(self.COVER_XPATH)[0].attrib["href"] or generic_cover + match.cover = html.xpath( + self.COVER_XPATH)[0].attrib["href"] or generic_cover try: rating_num = float(html.xpath(self.RATING_XPATH)[0].text.strip()) except Exception: @@ -146,35 +184,39 @@ class Douban(Metadata): tag_elements = html.xpath(self.TAGS_XPATH) if len(tag_elements): match.tags = [tag_element.text for tag_element in tag_elements] + else: + match.tags = self._get_tags(decode_content) description_element = html.xpath(self.DESCRIPTION_XPATH) if len(description_element): - match.description = html2text(etree.tostring( - description_element[-1], encoding="utf8").decode("utf8")) + match.description = html2text( + etree.tostring(description_element[-1]).decode("utf8")) info = html.xpath(self.INFO_XPATH) for element in info: text = element.text if self.AUTHORS_PATTERN.search(text): - next = element.getnext() - while next is not None and next.tag != "br": - match.authors.append(next.text) - next = next.getnext() + next_element = element.getnext() + while next_element is not None and next_element.tag != "br": + match.authors.append(next_element.text) + next_element = next_element.getnext() elif self.PUBLISHER_PATTERN.search(text): - match.publisher = element.tail.strip() + if publisher := element.tail.strip(): + match.publisher = publisher + else: + match.publisher = element.getnext().text elif self.SUBTITLE_PATTERN.search(text): - match.title = f'{match.title}:' + element.tail.strip() + match.title = f'{match.title}:{element.tail.strip()}' elif self.PUBLISHED_DATE_PATTERN.search(text): match.publishedDate = self._clean_date(element.tail.strip()) - elif self.SUBTITLE_PATTERN.search(text): + elif self.SERIES_PATTERN.search(text): match.series = element.getnext().text elif i_type := self.IDENTIFIERS_PATTERN.search(text): match.identifiers[i_type.group()] = element.tail.strip() return match - def _clean_date(self, date: str) -> str: """ Clean up the date string to be in the format YYYY-MM-DD @@ -194,13 +236,24 @@ class Douban(Metadata): if date[i].isdigit(): digit.append(date[i]) elif digit: - ls.append("".join(digit) if len(digit)==2 else f"0{digit[0]}") + ls.append("".join(digit) if len(digit) == + 2 else f"0{digit[0]}") digit = [] if digit: - ls.append("".join(digit) if len(digit)==2 else f"0{digit[0]}") + ls.append("".join(digit) if len(digit) == + 2 else f"0{digit[0]}") moon = ls[0] - if len(ls)>1: - day = ls[1] + if len(ls) > 1: + day = ls[1] return f"{year}-{moon}-{day}" + + def _get_tags(self, text: str) -> List[str]: + tags = [] + if criteria := self.CRITERIA_PATTERN.search(text): + tags.extend( + item.replace('7:', '') for item in criteria.group().split('|') + if item.startswith('7:')) + + return tags diff --git a/cps/metadata_provider/google.py b/cps/metadata_provider/google.py index 98fadd37..ba7e10af 100644 --- a/cps/metadata_provider/google.py +++ b/cps/metadata_provider/google.py @@ -19,6 +19,7 @@ # Google Books api document: https://developers.google.com/books/docs/v1/using from typing import Dict, List, Optional from urllib.parse import quote +from datetime import datetime import requests @@ -81,7 +82,11 @@ class Google(Metadata): match.description = result["volumeInfo"].get("description", "") match.languages = self._parse_languages(result=result, locale=locale) match.publisher = result["volumeInfo"].get("publisher", "") - match.publishedDate = result["volumeInfo"].get("publishedDate", "") + try: + datetime.strptime(result["volumeInfo"].get("publishedDate", ""), "%Y-%m-%d") + match.publishedDate = result["volumeInfo"].get("publishedDate", "") + except ValueError: + match.publishedDate = "" match.rating = result["volumeInfo"].get("averageRating", 0) match.series, match.series_index = "", 1 match.tags = result["volumeInfo"].get("categories", []) @@ -103,6 +108,13 @@ class Google(Metadata): def _parse_cover(result: Dict, generic_cover: str) -> str: if result["volumeInfo"].get("imageLinks"): cover_url = result["volumeInfo"]["imageLinks"]["thumbnail"] + + # strip curl in cover + cover_url = cover_url.replace("&edge=curl", "") + + # request 800x900 cover image (higher resolution) + cover_url += "&fife=w800-h900" + return cover_url.replace("http://", "https://") return generic_cover diff --git a/cps/metadata_provider/lubimyczytac.py b/cps/metadata_provider/lubimyczytac.py index e4abe9db..4644cad9 100644 --- a/cps/metadata_provider/lubimyczytac.py +++ b/cps/metadata_provider/lubimyczytac.py @@ -102,7 +102,7 @@ class LubimyCzytac(Metadata): PUBLISH_DATE = "//dt[contains(@title,'Data pierwszego wydania" FIRST_PUBLISH_DATE = f"{DETAILS}{PUBLISH_DATE} oryginalnego')]{SIBLINGS}[1]/text()" FIRST_PUBLISH_DATE_PL = f"{DETAILS}{PUBLISH_DATE} polskiego')]{SIBLINGS}[1]/text()" - TAGS = "//nav[@aria-label='breadcrumb']//a[contains(@href,'/ksiazki/k/')]/text()" + TAGS = "//nav[@aria-label='breadcrumbs']//a[contains(@href,'/ksiazki/k/')]/span/text()" RATING = "//meta[@property='books:rating:value']/@content" COVER = "//meta[@property='og:image']/@content" diff --git a/cps/oauth_bb.py b/cps/oauth_bb.py index d9a60c0e..ec400f71 100644 --- a/cps/oauth_bb.py +++ b/cps/oauth_bb.py @@ -74,7 +74,7 @@ def register_user_with_oauth(user=None): if len(all_oauth.keys()) == 0: return if user is None: - flash(_(u"Register with %(provider)s", provider=", ".join(list(all_oauth.values()))), category="success") + flash(_("Register with %(provider)s", provider=", ".join(list(all_oauth.values()))), category="success") else: for oauth_key in all_oauth.keys(): # Find this OAuth token in the database, or create it @@ -134,8 +134,8 @@ def bind_oauth_or_register(provider_id, provider_user_id, redirect_url, provider # already bind with user, just login if oauth_entry.user: login_user(oauth_entry.user) - log.debug(u"You are now logged in as: '%s'", oauth_entry.user.name) - flash(_(u"you are now logged in as: '%(nickname)s'", nickname= oauth_entry.user.name), + log.debug("You are now logged in as: '%s'", oauth_entry.user.name) + flash(_("Success! You are now logged in as: %(nickname)s", nickname= oauth_entry.user.name), category="success") return redirect(url_for('web.index')) else: @@ -145,21 +145,21 @@ def bind_oauth_or_register(provider_id, provider_user_id, redirect_url, provider try: ub.session.add(oauth_entry) ub.session.commit() - flash(_(u"Link to %(oauth)s Succeeded", oauth=provider_name), category="success") + flash(_("Link to %(oauth)s Succeeded", oauth=provider_name), category="success") log.info("Link to {} Succeeded".format(provider_name)) return redirect(url_for('web.profile')) except Exception as ex: log.error_or_exception(ex) ub.session.rollback() else: - flash(_(u"Login failed, No User Linked With OAuth Account"), category="error") + flash(_("Login failed, No User Linked With OAuth Account"), category="error") log.info('Login failed, No User Linked With OAuth Account') return redirect(url_for('web.login')) # return redirect(url_for('web.login')) # if config.config_public_reg: # return redirect(url_for('web.register')) # else: - # flash(_(u"Public registration is not enabled"), category="error") + # flash(_("Public registration is not enabled"), category="error") # return redirect(url_for(redirect_url)) except (NoResultFound, AttributeError): return redirect(url_for(redirect_url)) @@ -194,15 +194,15 @@ def unlink_oauth(provider): ub.session.delete(oauth_entry) ub.session.commit() logout_oauth_user() - flash(_(u"Unlink to %(oauth)s Succeeded", oauth=oauth_check[provider]), category="success") + flash(_("Unlink to %(oauth)s Succeeded", oauth=oauth_check[provider]), category="success") log.info("Unlink to {} Succeeded".format(oauth_check[provider])) except Exception as ex: log.error_or_exception(ex) ub.session.rollback() - flash(_(u"Unlink to %(oauth)s Failed", oauth=oauth_check[provider]), category="error") + flash(_("Unlink to %(oauth)s Failed", oauth=oauth_check[provider]), category="error") except NoResultFound: log.warning("oauth %s for user %d not found", provider, current_user.id) - flash(_(u"Not Linked to %(oauth)s", oauth=provider), category="error") + flash(_("Not Linked to %(oauth)s", oauth=provider), category="error") return redirect(url_for('web.profile')) def generate_oauth_blueprints(): @@ -258,13 +258,13 @@ if ub.oauth_support: @oauth_authorized.connect_via(oauthblueprints[0]['blueprint']) def github_logged_in(blueprint, token): if not token: - flash(_(u"Failed to log in with GitHub."), category="error") + flash(_("Failed to log in with GitHub."), category="error") log.error("Failed to log in with GitHub") return False resp = blueprint.session.get("/user") if not resp.ok: - flash(_(u"Failed to fetch user info from GitHub."), category="error") + flash(_("Failed to fetch user info from GitHub."), category="error") log.error("Failed to fetch user info from GitHub") return False @@ -276,13 +276,13 @@ if ub.oauth_support: @oauth_authorized.connect_via(oauthblueprints[1]['blueprint']) def google_logged_in(blueprint, token): if not token: - flash(_(u"Failed to log in with Google."), category="error") + flash(_("Failed to log in with Google."), category="error") log.error("Failed to log in with Google") return False resp = blueprint.session.get("/oauth2/v2/userinfo") if not resp.ok: - flash(_(u"Failed to fetch user info from Google."), category="error") + flash(_("Failed to fetch user info from Google."), category="error") log.error("Failed to fetch user info from Google") return False @@ -295,8 +295,8 @@ if ub.oauth_support: @oauth_error.connect_via(oauthblueprints[0]['blueprint']) def github_error(blueprint, error, error_description=None, error_uri=None): msg = ( - u"OAuth error from {name}! " - u"error={error} description={description} uri={uri}" + "OAuth error from {name}! " + "error={error} description={description} uri={uri}" ).format( name=blueprint.name, error=error, @@ -308,8 +308,8 @@ if ub.oauth_support: @oauth_error.connect_via(oauthblueprints[1]['blueprint']) def google_error(blueprint, error, error_description=None, error_uri=None): msg = ( - u"OAuth error from {name}! " - u"error={error} description={description} uri={uri}" + "OAuth error from {name}! " + "error={error} description={description} uri={uri}" ).format( name=blueprint.name, error=error, @@ -329,10 +329,10 @@ def github_login(): if account_info.ok: account_info_json = account_info.json() return bind_oauth_or_register(oauthblueprints[0]['id'], account_info_json['id'], 'github.login', 'github') - flash(_(u"GitHub Oauth error, please retry later."), category="error") + flash(_("GitHub Oauth error, please retry later."), category="error") log.error("GitHub Oauth error, please retry later") except (InvalidGrantError, TokenExpiredError) as e: - flash(_(u"GitHub Oauth error: {}").format(e), category="error") + flash(_("GitHub Oauth error: {}").format(e), category="error") log.error(e) return redirect(url_for('web.login')) @@ -353,10 +353,10 @@ def google_login(): if resp.ok: account_info_json = resp.json() return bind_oauth_or_register(oauthblueprints[1]['id'], account_info_json['id'], 'google.login', 'google') - flash(_(u"Google Oauth error, please retry later."), category="error") + flash(_("Google Oauth error, please retry later."), category="error") log.error("Google Oauth error, please retry later") except (InvalidGrantError, TokenExpiredError) as e: - flash(_(u"Google Oauth error: {}").format(e), category="error") + flash(_("Google Oauth error: {}").format(e), category="error") log.error(e) return redirect(url_for('web.login')) diff --git a/cps/opds.py b/cps/opds.py index 60dbd551..4067712f 100644 --- a/cps/opds.py +++ b/cps/opds.py @@ -21,41 +21,28 @@ # along with this program. If not, see . import datetime +import json from urllib.parse import unquote_plus -from functools import wraps -from flask import Blueprint, request, render_template, Response, g, make_response, abort +from flask import Blueprint, request, render_template, make_response, abort, Response from flask_login import current_user from flask_babel import get_locale +from flask_babel import gettext as _ from sqlalchemy.sql.expression import func, text, or_, and_, true from sqlalchemy.exc import InvalidRequestError, OperationalError -from werkzeug.security import check_password_hash -from . import constants, logger, config, db, calibre_db, ub, services, isoLanguages +from . import logger, config, db, calibre_db, ub, isoLanguages +from .usermanagement import requires_basic_auth_if_no_ano from .helper import get_download_link, get_book_cover from .pagination import Pagination from .web import render_read_books -from .usermanagement import load_user_from_request -from flask_babel import gettext as _ + opds = Blueprint('opds', __name__) log = logger.create() -def requires_basic_auth_if_no_ano(f): - @wraps(f) - def decorated(*args, **kwargs): - auth = request.authorization - if config.config_anonbrowse != 1: - if not auth or auth.type != 'basic' or not check_auth(auth.username, auth.password): - return authenticate() - return f(*args, **kwargs) - if config.config_login_type == constants.LOGIN_LDAP and services.ldap and config.config_anonbrowse != 1: - return services.ldap.basic_auth_required(f) - return decorated - - @opds.route("/opds/") @opds.route("/opds") @requires_basic_auth_if_no_ano @@ -69,7 +56,7 @@ def feed_osd(): return render_xml_template('osd.xml', lang='en-EN') -@opds.route("/opds/search", defaults={'query': ""}) +# @opds.route("/opds/search", defaults={'query': ""}) @opds.route("/opds/search/") @requires_basic_auth_if_no_ano def feed_cc_search(query): @@ -328,7 +315,7 @@ def feed_format(book_id): @requires_basic_auth_if_no_ano def feed_languagesindex(): off = request.args.get("offset") or 0 - if current_user.filter_language() == u"all": + if current_user.filter_language() == "all": languages = calibre_db.speaking_language() else: languages = calibre_db.session.query(db.Languages).filter( @@ -355,7 +342,8 @@ def feed_languages(book_id): @requires_basic_auth_if_no_ano def feed_shelfindex(): off = request.args.get("offset") or 0 - shelf = g.shelves_access + shelf = ub.session.query(ub.Shelf).filter( + or_(ub.Shelf.is_public == 1, ub.Shelf.user_id == current_user.id)).order_by(ub.Shelf.name).all() number = len(shelf) pagination = Pagination((int(off) / (int(config.config_books_per_page)) + 1), config.config_books_per_page, number) @@ -402,11 +390,7 @@ def feed_shelf(book_id): @opds.route("/opds/download///") @requires_basic_auth_if_no_ano def opds_download_link(book_id, book_format): - # I gave up with this: With enabled ldap login, the user doesn't get logged in, therefore it's always guest - # workaround, loading the user from the request and checking its download rights here - # in case of anonymous browsing user is None - user = load_user_from_request(request) or current_user - if not user.role_download(): + if not current_user.role_download(): return abort(403) if "Kobo" in request.headers.get('User-Agent'): client = "kobo" @@ -429,6 +413,17 @@ def get_metadata_calibre_companion(uuid, library): return "" +@opds.route("/opds/stats") +@requires_basic_auth_if_no_ano +def get_database_stats(): + stat = dict() + stat['books'] = calibre_db.session.query(db.Books).count() + stat['authors'] = calibre_db.session.query(db.Authors).count() + stat['categories'] = calibre_db.session.query(db.Tags).count() + stat['series'] = calibre_db.session.query(db.Series).count() + return Response(json.dumps(stat), mimetype="application/json") + + @opds.route("/opds/thumb_240_240/") @opds.route("/opds/cover_240_240/") @opds.route("/opds/cover_90_90/") @@ -478,27 +473,6 @@ def feed_search(term): return render_xml_template('feed.xml', searchterm="") -def check_auth(username, password): - try: - username = username.encode('windows-1252') - except UnicodeEncodeError: - username = username.encode('utf-8') - user = ub.session.query(ub.User).filter(func.lower(ub.User.name) == - username.decode('utf-8').lower()).first() - if bool(user and check_password_hash(str(user.password), password)): - return True - else: - ip_address = request.headers.get('X-Forwarded-For', request.remote_addr) - log.warning('OPDS Login failed for user "%s" IP-address: %s', username.decode('utf-8'), ip_address) - return False - - -def authenticate(): - return Response( - 'Could not verify your access level for that URL.\n' - 'You have to login with proper credentials', 401, - {'WWW-Authenticate': 'Basic realm="Login Required"'}) - def render_xml_template(*args, **kwargs): # ToDo: return time in current timezone similar to %z diff --git a/cps/remotelogin.py b/cps/remotelogin.py index 037979ea..ee434670 100644 --- a/cps/remotelogin.py +++ b/cps/remotelogin.py @@ -58,8 +58,8 @@ def remote_login(): ub.session.add(auth_token) ub.session_commit() verify_url = url_for('remotelogin.verify_token', token=auth_token.auth_token, _external=true) - log.debug(u"Remot Login request with token: %s", auth_token.auth_token) - return render_title_template('remote_login.html', title=_(u"Login"), token=auth_token.auth_token, + log.debug("Remot Login request with token: %s", auth_token.auth_token) + return render_title_template('remote_login.html', title=_("Login"), token=auth_token.auth_token, verify_url=verify_url, page="remotelogin") @@ -71,8 +71,8 @@ def verify_token(token): # Token not found if auth_token is None: - flash(_(u"Token not found"), category="error") - log.error(u"Remote Login token not found") + flash(_("Token not found"), category="error") + log.error("Remote Login token not found") return redirect(url_for('web.index')) # Token expired @@ -80,8 +80,8 @@ def verify_token(token): ub.session.delete(auth_token) ub.session_commit() - flash(_(u"Token has expired"), category="error") - log.error(u"Remote Login token expired") + flash(_("Token has expired"), category="error") + log.error("Remote Login token expired") return redirect(url_for('web.index')) # Update token with user information @@ -89,8 +89,8 @@ def verify_token(token): auth_token.verified = True ub.session_commit() - flash(_(u"Success! Please return to your device"), category="success") - log.debug(u"Remote Login token for userid %s verified", auth_token.user_id) + flash(_("Success! Please return to your device"), category="success") + log.debug("Remote Login token for userid %s verified", auth_token.user_id) return redirect(url_for('web.index')) @@ -105,7 +105,7 @@ def token_verified(): # Token not found if auth_token is None: data['status'] = 'error' - data['message'] = _(u"Token not found") + data['message'] = _("Token not found") # Token expired elif datetime.now() > auth_token.expiration: @@ -113,7 +113,7 @@ def token_verified(): ub.session_commit() data['status'] = 'error' - data['message'] = _(u"Token has expired") + data['message'] = _("Token has expired") elif not auth_token.verified: data['status'] = 'not_verified' @@ -126,8 +126,8 @@ def token_verified(): ub.session_commit("User {} logged in via remotelogin, token deleted".format(user.name)) data['status'] = 'success' - log.debug(u"Remote Login for userid %s succeeded", user.id) - flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.name), category="success") + log.debug("Remote Login for userid %s succeeded", user.id) + flash(_("Success! You are now logged in as: %(nickname)s", nickname=user.name), category="success") response = make_response(json.dumps(data, ensure_ascii=False)) response.headers["Content-Type"] = "application/json; charset=utf-8" diff --git a/cps/render_template.py b/cps/render_template.py index 04a50bbb..68b46459 100644 --- a/cps/render_template.py +++ b/cps/render_template.py @@ -20,11 +20,13 @@ from flask import render_template, g, abort, request from flask_babel import gettext as _ from werkzeug.local import LocalProxy from flask_login import current_user +from sqlalchemy.sql.expression import or_ -from . import config, constants, logger +from . import config, constants, logger, ub from .ub import User + log = logger.create() def get_sidebar_config(kwargs=None): @@ -45,12 +47,12 @@ def get_sidebar_config(kwargs=None): "show_text": _('Show Hot Books'), "config_show": True}) if current_user.role_admin(): sidebar.append({"glyph": "glyphicon-download", "text": _('Downloaded Books'), "link": 'web.download_list', - "id": "download", "visibility": constants.SIDEBAR_DOWNLOAD, 'public': (not g.user.is_anonymous), + "id": "download", "visibility": constants.SIDEBAR_DOWNLOAD, 'public': (not current_user.is_anonymous), "page": "download", "show_text": _('Show Downloaded Books'), "config_show": content}) else: sidebar.append({"glyph": "glyphicon-download", "text": _('Downloaded Books'), "link": 'web.books_list', - "id": "download", "visibility": constants.SIDEBAR_DOWNLOAD, 'public': (not g.user.is_anonymous), + "id": "download", "visibility": constants.SIDEBAR_DOWNLOAD, 'public': (not current_user.is_anonymous), "page": "download", "show_text": _('Show Downloaded Books'), "config_show": content}) sidebar.append( @@ -58,47 +60,50 @@ def get_sidebar_config(kwargs=None): "visibility": constants.SIDEBAR_BEST_RATED, 'public': True, "page": "rated", "show_text": _('Show Top Rated Books'), "config_show": True}) sidebar.append({"glyph": "glyphicon-eye-open", "text": _('Read Books'), "link": 'web.books_list', "id": "read", - "visibility": constants.SIDEBAR_READ_AND_UNREAD, 'public': (not g.user.is_anonymous), - "page": "read", "show_text": _('Show read and unread'), "config_show": content}) + "visibility": constants.SIDEBAR_READ_AND_UNREAD, 'public': (not current_user.is_anonymous), + "page": "read", "show_text": _('Show Read and Unread'), "config_show": content}) sidebar.append( {"glyph": "glyphicon-eye-close", "text": _('Unread Books'), "link": 'web.books_list', "id": "unread", - "visibility": constants.SIDEBAR_READ_AND_UNREAD, 'public': (not g.user.is_anonymous), "page": "unread", + "visibility": constants.SIDEBAR_READ_AND_UNREAD, 'public': (not current_user.is_anonymous), "page": "unread", "show_text": _('Show unread'), "config_show": False}) sidebar.append({"glyph": "glyphicon-random", "text": _('Discover'), "link": 'web.books_list', "id": "rand", "visibility": constants.SIDEBAR_RANDOM, 'public': True, "page": "discover", "show_text": _('Show Random Books'), "config_show": True}) sidebar.append({"glyph": "glyphicon-inbox", "text": _('Categories'), "link": 'web.category_list', "id": "cat", "visibility": constants.SIDEBAR_CATEGORY, 'public': True, "page": "category", - "show_text": _('Show category selection'), "config_show": True}) + "show_text": _('Show Category Section'), "config_show": True}) sidebar.append({"glyph": "glyphicon-bookmark", "text": _('Series'), "link": 'web.series_list', "id": "serie", "visibility": constants.SIDEBAR_SERIES, 'public': True, "page": "series", - "show_text": _('Show series selection'), "config_show": True}) + "show_text": _('Show Series Section'), "config_show": True}) sidebar.append({"glyph": "glyphicon-user", "text": _('Authors'), "link": 'web.author_list', "id": "author", "visibility": constants.SIDEBAR_AUTHOR, 'public': True, "page": "author", - "show_text": _('Show author selection'), "config_show": True}) + "show_text": _('Show Author Section'), "config_show": True}) sidebar.append( {"glyph": "glyphicon-text-size", "text": _('Publishers'), "link": 'web.publisher_list', "id": "publisher", "visibility": constants.SIDEBAR_PUBLISHER, 'public': True, "page": "publisher", - "show_text": _('Show publisher selection'), "config_show":True}) + "show_text": _('Show Publisher Section'), "config_show":True}) sidebar.append({"glyph": "glyphicon-flag", "text": _('Languages'), "link": 'web.language_overview', "id": "lang", - "visibility": constants.SIDEBAR_LANGUAGE, 'public': (g.user.filter_language() == 'all'), + "visibility": constants.SIDEBAR_LANGUAGE, 'public': (current_user.filter_language() == 'all'), "page": "language", - "show_text": _('Show language selection'), "config_show": True}) + "show_text": _('Show Language Section'), "config_show": True}) sidebar.append({"glyph": "glyphicon-star-empty", "text": _('Ratings'), "link": 'web.ratings_list', "id": "rate", "visibility": constants.SIDEBAR_RATING, 'public': True, - "page": "rating", "show_text": _('Show ratings selection'), "config_show": True}) + "page": "rating", "show_text": _('Show Ratings Section'), "config_show": True}) sidebar.append({"glyph": "glyphicon-file", "text": _('File formats'), "link": 'web.formats_list', "id": "format", "visibility": constants.SIDEBAR_FORMAT, 'public': True, - "page": "format", "show_text": _('Show file formats selection'), "config_show": True}) + "page": "format", "show_text": _('Show File Formats Section'), "config_show": True}) sidebar.append( {"glyph": "glyphicon-trash", "text": _('Archived Books'), "link": 'web.books_list', "id": "archived", - "visibility": constants.SIDEBAR_ARCHIVED, 'public': (not g.user.is_anonymous), "page": "archived", - "show_text": _('Show archived books'), "config_show": content}) + "visibility": constants.SIDEBAR_ARCHIVED, 'public': (not current_user.is_anonymous), "page": "archived", + "show_text": _('Show Archived Books'), "config_show": content}) if not simple: sidebar.append( {"glyph": "glyphicon-th-list", "text": _('Books List'), "link": 'web.books_table', "id": "list", - "visibility": constants.SIDEBAR_LIST, 'public': (not g.user.is_anonymous), "page": "list", + "visibility": constants.SIDEBAR_LIST, 'public': (not current_user.is_anonymous), "page": "list", "show_text": _('Show Books List'), "config_show": content}) + g.shelves_access = ub.session.query(ub.Shelf).filter( + or_(ub.Shelf.is_public == 1, ub.Shelf.user_id == current_user.id)).order_by(ub.Shelf.name).all() + return sidebar, simple diff --git a/cps/schedule.py b/cps/schedule.py index 5f3326ef..05367e99 100644 --- a/cps/schedule.py +++ b/cps/schedule.py @@ -19,7 +19,7 @@ import datetime from . import config, constants -from .services.background_scheduler import BackgroundScheduler, use_APScheduler +from .services.background_scheduler import BackgroundScheduler, CronTrigger, use_APScheduler from .tasks.database import TaskReconnectDatabase from .tasks.thumbnail import TaskGenerateCoverThumbnails, TaskGenerateSeriesThumbnails, TaskClearCoverThumbnailCache from .services.worker import WorkerThread @@ -27,13 +27,12 @@ from .tasks.metadata_backup import TaskBackupMetadata def get_scheduled_tasks(reconnect=True): tasks = list() - # config.schedule_reconnect or - # Reconnect Calibre database (metadata.db) + # Reconnect Calibre database (metadata.db) based on config.schedule_reconnect if reconnect: tasks.append([lambda: TaskReconnectDatabase(), 'reconnect', False]) - # ToDo make configurable. Generate metadata.opf file for each changed book - if False: + # Generate metadata.opf file for each changed book + if config.schedule_metadata_backup: tasks.append([lambda: TaskBackupMetadata("en"), 'backup metadata', False]) # Generate all missing book cover thumbnails @@ -66,10 +65,10 @@ def register_scheduled_tasks(reconnect=True): duration = config.schedule_duration # Register scheduled tasks - scheduler.schedule_tasks(tasks=get_scheduled_tasks(reconnect), trigger='cron', hour=start) + scheduler.schedule_tasks(tasks=get_scheduled_tasks(reconnect), trigger=CronTrigger(hour=start)) end_time = calclulate_end_time(start, duration) - scheduler.schedule(func=end_scheduled_tasks, trigger='cron', name="end scheduled task", hour=end_time.hour, - minute=end_time.minute) + scheduler.schedule(func=end_scheduled_tasks, trigger=CronTrigger(hour=end_time.hour, minute=end_time.minute), + name="end scheduled task") # Kick-off tasks, if they should currently be running if should_task_be_running(start, duration): diff --git a/cps/search.py b/cps/search.py index 17d54b4e..f214b3a8 100644 --- a/cps/search.py +++ b/cps/search.py @@ -45,7 +45,7 @@ def simple_search(): return render_title_template('search.html', searchterm="", result_count=0, - title=_(u"Search"), + title=_("Search"), page="search") @@ -185,18 +185,18 @@ def extend_search_term(searchterm, searchterm.extend((author_name.replace('|', ','), book_title, publisher)) if pub_start: try: - searchterm.extend([_(u"Published after ") + + searchterm.extend([_("Published after ") + format_date(datetime.strptime(pub_start, "%Y-%m-%d"), format='medium')]) except ValueError: - pub_start = u"" + pub_start = "" if pub_end: try: - searchterm.extend([_(u"Published before ") + + searchterm.extend([_("Published before ") + format_date(datetime.strptime(pub_end, "%Y-%m-%d"), format='medium')]) except ValueError: - pub_end = u"" + pub_end = "" elements = {'tag': db.Tags, 'serie':db.Series, 'shelf':ub.Shelf} for key, db_element in elements.items(): tag_names = calibre_db.session.query(db_element).filter(db_element.id.in_(tags['include_' + key])).all() @@ -214,11 +214,11 @@ def extend_search_term(searchterm, language_names = calibre_db.speaking_language(language_names) searchterm.extend(language.name for language in language_names) if rating_high: - searchterm.extend([_(u"Rating <= %(rating)s", rating=rating_high)]) + searchterm.extend([_("Rating <= %(rating)s", rating=rating_high)]) if rating_low: - searchterm.extend([_(u"Rating >= %(rating)s", rating=rating_low)]) - if read_status: - searchterm.extend([_(u"Read Status = %(status)s", status=read_status)]) + searchterm.extend([_("Rating >= %(rating)s", rating=rating_low)]) + if read_status != "Any": + searchterm.extend([_("Read Status = '%(status)s'", status=read_status)]) searchterm.extend(ext for ext in tags['include_extension']) searchterm.extend(ext for ext in tags['exclude_extension']) # handle custom columns @@ -267,23 +267,23 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): column_start = term.get('custom_column_' + str(c.id) + '_start') column_end = term.get('custom_column_' + str(c.id) + '_end') if column_start: - search_term.extend([u"{} >= {}".format(c.name, + search_term.extend(["{} >= {}".format(c.name, format_date(datetime.strptime(column_start, "%Y-%m-%d").date(), format='medium') )]) cc_present = True if column_end: - search_term.extend([u"{} <= {}".format(c.name, + search_term.extend(["{} <= {}".format(c.name, format_date(datetime.strptime(column_end, "%Y-%m-%d").date(), format='medium') )]) cc_present = True 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([("{}: {}".format(c.name, term.get('custom_column_' + str(c.id))))]) cc_present = True 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 != "Any": search_term, pub_start, pub_end = extend_search_term(search_term, author_name, book_title, @@ -302,7 +302,8 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): q = q.filter(func.datetime(db.Books.pubdate) > func.datetime(pub_start)) if pub_end: q = q.filter(func.datetime(db.Books.pubdate) < func.datetime(pub_end)) - q = q.filter(adv_search_read_status(read_status)) + if read_status != "Any": + q = q.filter(adv_search_read_status(read_status)) if publisher: q = q.filter(db.Books.publishers.any(func.lower(db.Publishers.name).ilike("%" + publisher + "%"))) q = adv_search_tag(q, tags['include_tag'], tags['exclude_tag']) @@ -339,7 +340,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None): pagination=pagination, entries=entries, result_count=result_count, - title=_(u"Advanced Search"), page="advsearch", + title=_("Advanced Search"), page="advsearch", order=order[1]) @@ -366,22 +367,28 @@ def render_prepare_search_form(cc): .filter(calibre_db.common_filters()) \ .group_by(db.Data.format)\ .order_by(db.Data.format).all() - if current_user.filter_language() == u"all": + if current_user.filter_language() == "all": languages = calibre_db.speaking_language() else: languages = None return render_title_template('search_form.html', tags=tags, languages=languages, extensions=extensions, - series=series,shelves=shelves, title=_(u"Advanced Search"), cc=cc, page="advsearch") + series=series,shelves=shelves, title=_("Advanced Search"), cc=cc, page="advsearch") def render_search_results(term, offset=None, order=None, limit=None): - join = db.books_series_link, db.Books.id == db.books_series_link.c.book, db.Series - entries, result_count, pagination = calibre_db.get_search_results(term, - config, - offset, - order, - limit, - *join) + if term: + join = db.books_series_link, db.Books.id == db.books_series_link.c.book, db.Series + entries, result_count, pagination = calibre_db.get_search_results(term, + config, + offset, + order, + limit, + *join) + else: + entries = list() + order = [None, None] + pagination = result_count = None + return render_title_template('search.html', searchterm=term, pagination=pagination, @@ -389,7 +396,7 @@ def render_search_results(term, offset=None, order=None, limit=None): adv_searchterm=term, entries=entries, result_count=result_count, - title=_(u"Search"), + title=_("Search"), page="search", order=order[1]) diff --git a/cps/server.py b/cps/server.py index fb70a723..0b6d2fb3 100644 --- a/cps/server.py +++ b/cps/server.py @@ -21,12 +21,12 @@ import os import errno import signal import socket -import subprocess # nosec try: from gevent.pywsgi import WSGIServer from .gevent_wsgi import MyWSGIHandler from gevent.pool import Pool + from gevent.socket import socket as GeventSocket from gevent import __version__ as _version from greenlet import GreenletExit import ssl @@ -36,6 +36,7 @@ except ImportError: from .tornado_wsgi import MyWSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop + from tornado.netutil import bind_unix_socket from tornado import version as _version VERSION = 'Tornado ' + _version _GEVENT = False @@ -95,7 +96,12 @@ class WebServer(object): log.warning('Cert path: %s', certfile_path) log.warning('Key path: %s', keyfile_path) - def _make_gevent_unix_socket(self, socket_file): + def _make_gevent_socket_activated(self): + # Reuse an already open socket on fd=SD_LISTEN_FDS_START + SD_LISTEN_FDS_START = 3 + return GeventSocket(fileno=SD_LISTEN_FDS_START) + + def _prepare_unix_socket(self, socket_file): # the socket file must not exist prior to bind() if os.path.exists(socket_file): # avoid nuking regular files and symbolic links (could be a mistype or security issue) @@ -103,35 +109,41 @@ class WebServer(object): raise OSError(errno.EEXIST, os.strerror(errno.EEXIST), socket_file) os.remove(socket_file) - unix_sock = WSGIServer.get_listener(socket_file, family=socket.AF_UNIX) self.unix_socket_file = socket_file - # ensure current user and group have r/w permissions, no permissions for other users - # this way the socket can be shared in a semi-secure manner - # between the user running calibre-web and the user running the fronting webserver - os.chmod(socket_file, 0o660) - - return unix_sock - - def _make_gevent_socket(self): + def _make_gevent_listener(self): if os.name != 'nt': + socket_activated = os.environ.get("LISTEN_FDS") + if socket_activated: + sock = self._make_gevent_socket_activated() + sock_info = sock.getsockname() + return sock, "systemd-socket:" + _readable_listen_address(sock_info[0], sock_info[1]) unix_socket_file = os.environ.get("CALIBRE_UNIX_SOCKET") if unix_socket_file: - return self._make_gevent_unix_socket(unix_socket_file), "unix:" + unix_socket_file + self._prepare_unix_socket(unix_socket_file) + unix_sock = WSGIServer.get_listener(unix_socket_file, family=socket.AF_UNIX) + # ensure current user and group have r/w permissions, no permissions for other users + # this way the socket can be shared in a semi-secure manner + # between the user running calibre-web and the user running the fronting webserver + os.chmod(unix_socket_file, 0o660) + + return unix_sock, "unix:" + unix_socket_file if self.listen_address: - return (self.listen_address, self.listen_port), None + return ((self.listen_address, self.listen_port), + _readable_listen_address(self.listen_address, self.listen_port)) if os.name == 'nt': self.listen_address = '0.0.0.0' - return (self.listen_address, self.listen_port), None + return ((self.listen_address, self.listen_port), + _readable_listen_address(self.listen_address, self.listen_port)) try: address = ('::', self.listen_port) sock = WSGIServer.get_listener(address, family=socket.AF_INET6) except socket.error as ex: log.error('%s', ex) - log.warning('Unable to listen on "", trying on IPv4 only...') + log.warning('Unable to listen on {}, trying on IPv4 only...'.format(address)) address = ('', self.listen_port) sock = WSGIServer.get_listener(address, family=socket.AF_INET) @@ -152,7 +164,7 @@ class WebServer(object): # The value of __package__ indicates how Python was called. It may # not exist if a setuptools script is installed as an egg. It may be # set incorrectly for entry points created with pip on Windows. - if getattr(__main__, "__package__", None) is None or ( + if getattr(__main__, "__package__", "") in ["", None] or ( os.name == "nt" and __main__.__package__ == "" and not os.path.exists(py_script) @@ -193,15 +205,15 @@ class WebServer(object): rv.extend(("-m", py_module.lstrip("."))) rv.extend(args) + if os.name == 'nt': + rv = ['"{}"'.format(a) for a in rv] return rv def _start_gevent(self): ssl_args = self.ssl_args or {} try: - sock, output = self._make_gevent_socket() - if output is None: - output = _readable_listen_address(self.listen_address, self.listen_port) + sock, output = self._make_gevent_listener() log.info('Starting Gevent server on %s', output) self.wsgiserver = WSGIServer(sock, self.app, log=self.access_logger, handler_class=MyWSGIHandler, error_log=log, @@ -226,17 +238,42 @@ class WebServer(object): if os.name == 'nt' and sys.version_info > (3, 7): import asyncio asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) - log.info('Starting Tornado server on %s', _readable_listen_address(self.listen_address, self.listen_port)) + try: + # Max Buffersize set to 200MB + http_server = HTTPServer(MyWSGIContainer(self.app), + max_buffer_size=209700000, + ssl_options=self.ssl_args) - # Max Buffersize set to 200MB - http_server = HTTPServer(MyWSGIContainer(self.app), - max_buffer_size=209700000, - ssl_options=self.ssl_args) - http_server.listen(self.listen_port, self.listen_address) - self.wsgiserver = IOLoop.current() - self.wsgiserver.start() - # wait for stop signal - self.wsgiserver.close(True) + unix_socket_file = os.environ.get("CALIBRE_UNIX_SOCKET") + if os.environ.get("LISTEN_FDS") and os.name != 'nt': + SD_LISTEN_FDS_START = 3 + sock = socket.socket(fileno=SD_LISTEN_FDS_START) + http_server.add_socket(sock) + sock.setblocking(0) + socket_name =sock.getsockname() + output = "systemd-socket:" + _readable_listen_address(socket_name[0], socket_name[1]) + elif unix_socket_file and os.name != 'nt': + self._prepare_unix_socket(unix_socket_file) + output = "unix:" + unix_socket_file + unix_socket = bind_unix_socket(self.unix_socket_file) + http_server.add_socket(unix_socket) + # ensure current user and group have r/w permissions, no permissions for other users + # this way the socket can be shared in a semi-secure manner + # between the user running calibre-web and the user running the fronting webserver + os.chmod(self.unix_socket_file, 0o660) + else: + output = _readable_listen_address(self.listen_address, self.listen_port) + http_server.listen(self.listen_port, self.listen_address) + log.info('Starting Tornado server on %s', output) + + self.wsgiserver = IOLoop.current() + self.wsgiserver.start() + # wait for stop signal + self.wsgiserver.close(True) + finally: + if self.unix_socket_file: + os.remove(self.unix_socket_file) + self.unix_socket_file = None def start(self): try: @@ -262,9 +299,16 @@ class WebServer(object): log.info("Performing restart of Calibre-Web") args = self._get_args_for_reloading() - subprocess.call(args, close_fds=True) # nosec + os.execv(args[0].lstrip('"').rstrip('"'), args) return True + @staticmethod + def shutdown_scheduler(): + from .services.background_scheduler import BackgroundScheduler + scheduler = BackgroundScheduler() + if scheduler: + scheduler.scheduler.shutdown() + def _killServer(self, __, ___): self.stop() @@ -273,9 +317,13 @@ class WebServer(object): updater_thread.stop() log.info("webserver stop (restart=%s)", restart) + self.shutdown_scheduler() self.restart = restart if self.wsgiserver: if _GEVENT: self.wsgiserver.close() else: - self.wsgiserver.add_callback_from_signal(self.wsgiserver.stop) + if restart: + self.wsgiserver.call_later(1.0, self.wsgiserver.stop) + else: + self.wsgiserver.add_callback_from_signal(self.wsgiserver.stop) diff --git a/cps/services/SyncToken.py b/cps/services/SyncToken.py index a53d7a99..bf31a7bc 100644 --- a/cps/services/SyncToken.py +++ b/cps/services/SyncToken.py @@ -19,11 +19,9 @@ import sys from base64 import b64decode, b64encode -from jsonschema import validate, exceptions, __version__ +from jsonschema import validate, exceptions from datetime import datetime -from urllib.parse import unquote - from flask import json from .. import logger diff --git a/cps/services/background_scheduler.py b/cps/services/background_scheduler.py index 27285fd9..72991559 100644 --- a/cps/services/background_scheduler.py +++ b/cps/services/background_scheduler.py @@ -23,6 +23,8 @@ from .worker import WorkerThread try: from apscheduler.schedulers.background import BackgroundScheduler as BScheduler + from apscheduler.triggers.cron import CronTrigger + from apscheduler.triggers.date import DateTrigger use_APScheduler = True except (ImportError, RuntimeError) as e: use_APScheduler = False @@ -43,35 +45,33 @@ class BackgroundScheduler: cls.scheduler = BScheduler() cls.scheduler.start() - atexit.register(lambda: cls.scheduler.shutdown()) - return cls._instance - def schedule(self, func, trigger, name=None, **trigger_args): + def schedule(self, func, trigger, name=None): if use_APScheduler: - return self.scheduler.add_job(func=func, trigger=trigger, name=name, **trigger_args) + return self.scheduler.add_job(func=func, trigger=trigger, name=name) # Expects a lambda expression for the task - def schedule_task(self, task, user=None, name=None, hidden=False, trigger='cron', **trigger_args): + def schedule_task(self, task, user=None, name=None, hidden=False, trigger=None): if use_APScheduler: def scheduled_task(): worker_task = task() worker_task.scheduled = True WorkerThread.add(user, worker_task, hidden=hidden) - return self.schedule(func=scheduled_task, trigger=trigger, name=name, **trigger_args) + return self.schedule(func=scheduled_task, trigger=trigger, name=name) # Expects a list of lambda expressions for the tasks - def schedule_tasks(self, tasks, user=None, trigger='cron', **trigger_args): + def schedule_tasks(self, tasks, user=None, trigger=None): if use_APScheduler: for task in tasks: - self.schedule_task(task[0], user=user, trigger=trigger, name=task[1], hidden=task[2], **trigger_args) + self.schedule_task(task[0], user=user, trigger=trigger, name=task[1], hidden=task[2]) # Expects a lambda expression for the task def schedule_task_immediately(self, task, user=None, name=None, hidden=False): if use_APScheduler: def immediate_task(): WorkerThread.add(user, task(), hidden) - return self.schedule(func=immediate_task, trigger='date', name=name) + return self.schedule(func=immediate_task, trigger=DateTrigger(), name=name) # Expects a list of lambda expressions for the tasks def schedule_tasks_immediately(self, tasks, user=None): diff --git a/cps/services/simpleldap.py b/cps/services/simpleldap.py index 1ca7e5bf..dc915ceb 100644 --- a/cps/services/simpleldap.py +++ b/cps/services/simpleldap.py @@ -20,6 +20,7 @@ import base64 from flask_simpleldap import LDAP, LDAPException from flask_simpleldap import ldap as pyLDAP +from flask import current_app from .. import constants, logger try: @@ -28,8 +29,47 @@ except ImportError: pass log = logger.create() -_ldap = LDAP() +class LDAPLogger(object): + + def write(self, message): + try: + log.debug(message.strip("\n").replace("\n", "")) + except Exception: + log.debug("Logging Error") + + +class mySimpleLDap(LDAP): + + @staticmethod + def init_app(app): + super(mySimpleLDap, mySimpleLDap).init_app(app) + app.config.setdefault('LDAP_LOGLEVEL', 0) + + @property + def initialize(self): + """Initialize a connection to the LDAP server. + + :return: LDAP connection object. + """ + try: + log_level = 2 if current_app.config['LDAP_LOGLEVEL'] == logger.logging.DEBUG else 0 + conn = pyLDAP.initialize('{0}://{1}:{2}'.format( + current_app.config['LDAP_SCHEMA'], + current_app.config['LDAP_HOST'], + current_app.config['LDAP_PORT']), trace_level=log_level, trace_file=LDAPLogger()) + conn.set_option(pyLDAP.OPT_NETWORK_TIMEOUT, + current_app.config['LDAP_TIMEOUT']) + conn = self._set_custom_options(conn) + conn.protocol_version = pyLDAP.VERSION3 + if current_app.config['LDAP_USE_TLS']: + conn.start_tls_s() + return conn + except pyLDAP.LDAPError as e: + raise LDAPException(self.error(e.args)) + + +_ldap = mySimpleLDap() def init_app(app, config): if config.config_login_type != constants.LOGIN_LDAP: @@ -44,15 +84,15 @@ def init_app(app, config): app.config['LDAP_SCHEMA'] = 'ldap' if config.config_ldap_authentication > constants.LDAP_AUTH_ANONYMOUS: if config.config_ldap_authentication > constants.LDAP_AUTH_UNAUTHENTICATE: - if config.config_ldap_serv_password is None: - config.config_ldap_serv_password = '' - app.config['LDAP_PASSWORD'] = base64.b64decode(config.config_ldap_serv_password) + if config.config_ldap_serv_password_e is None: + config.config_ldap_serv_password_e = '' + app.config['LDAP_PASSWORD'] = config.config_ldap_serv_password_e else: - app.config['LDAP_PASSWORD'] = base64.b64decode("") + app.config['LDAP_PASSWORD'] = "" app.config['LDAP_USERNAME'] = config.config_ldap_serv_username else: app.config['LDAP_USERNAME'] = "" - app.config['LDAP_PASSWORD'] = base64.b64decode("") + app.config['LDAP_PASSWORD'] = "" if bool(config.config_ldap_cert_path): app.config['LDAP_CUSTOM_OPTIONS'].update({ pyLDAP.OPT_X_TLS_REQUIRE_CERT: pyLDAP.OPT_X_TLS_DEMAND, @@ -70,7 +110,7 @@ def init_app(app, config): app.config['LDAP_OPENLDAP'] = bool(config.config_ldap_openldap) app.config['LDAP_GROUP_OBJECT_FILTER'] = config.config_ldap_group_object_filter app.config['LDAP_GROUP_MEMBERS_FIELD'] = config.config_ldap_group_members_field - + app.config['LDAP_LOGLEVEL'] = config.config_log_level try: _ldap.init_app(app) except ValueError: diff --git a/cps/shelf.py b/cps/shelf.py index 9ddc0d1a..5d05cfe2 100644 --- a/cps/shelf.py +++ b/cps/shelf.py @@ -46,13 +46,13 @@ def add_to_shelf(shelf_id, book_id): if shelf is None: log.error("Invalid shelf specified: %s", shelf_id) if not xhr: - flash(_(u"Invalid shelf specified"), category="error") + flash(_("Invalid shelf specified"), category="error") return redirect(url_for('web.index')) return "Invalid shelf specified", 400 if not check_shelf_edit_permissions(shelf): if not xhr: - flash(_(u"Sorry you are not allowed to add a book to that shelf"), category="error") + flash(_("Sorry you are not allowed to add a book to that shelf"), category="error") return redirect(url_for('web.index')) return "Sorry you are not allowed to add a book to the that shelf", 403 @@ -61,7 +61,7 @@ def add_to_shelf(shelf_id, book_id): if book_in_shelf: log.error("Book %s is already part of %s", book_id, shelf) if not xhr: - flash(_(u"Book is already part of the shelf: %(shelfname)s", shelfname=shelf.name), category="error") + flash(_("Book is already part of the shelf: %(shelfname)s", shelfname=shelf.name), category="error") return redirect(url_for('web.index')) return "Book is already part of the shelf: %s" % shelf.name, 400 @@ -79,14 +79,14 @@ def add_to_shelf(shelf_id, book_id): except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") if "HTTP_REFERER" in request.environ: return redirect(request.environ["HTTP_REFERER"]) else: return redirect(url_for('web.index')) if not xhr: log.debug("Book has been added to shelf: {}".format(shelf.name)) - flash(_(u"Book has been added to shelf: %(sname)s", sname=shelf.name), category="success") + flash(_("Book has been added to shelf: %(sname)s", sname=shelf.name), category="success") if "HTTP_REFERER" in request.environ: return redirect(request.environ["HTTP_REFERER"]) else: @@ -100,12 +100,12 @@ def search_to_shelf(shelf_id): shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first() if shelf is None: log.error("Invalid shelf specified: {}".format(shelf_id)) - flash(_(u"Invalid shelf specified"), category="error") + flash(_("Invalid shelf specified"), category="error") return redirect(url_for('web.index')) if not check_shelf_edit_permissions(shelf): log.warning("You are not allowed to add a book to the shelf".format(shelf.name)) - flash(_(u"You are not allowed to add a book to the shelf"), category="error") + flash(_("You are not allowed to add a book to the shelf"), category="error") return redirect(url_for('web.index')) if current_user.id in ub.searched_ids and ub.searched_ids[current_user.id]: @@ -123,7 +123,7 @@ def search_to_shelf(shelf_id): if not books_for_shelf: log.error("Books are already part of {}".format(shelf.name)) - flash(_(u"Books are already part of the shelf: %(name)s", name=shelf.name), category="error") + flash(_("Books are already part of the shelf: %(name)s", name=shelf.name), category="error") return redirect(url_for('web.index')) maxOrder = ub.session.query(func.max(ub.BookShelf.order)).filter(ub.BookShelf.shelf == shelf_id).first()[0] or 0 @@ -135,14 +135,14 @@ def search_to_shelf(shelf_id): try: ub.session.merge(shelf) ub.session.commit() - flash(_(u"Books have been added to shelf: %(sname)s", sname=shelf.name), category="success") + flash(_("Books have been added to shelf: %(sname)s", sname=shelf.name), category="success") except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") else: log.error("Could not add books to shelf: {}".format(shelf.name)) - flash(_(u"Could not add books to shelf: %(sname)s", sname=shelf.name), category="error") + flash(_("Could not add books to shelf: %(sname)s", sname=shelf.name), category="error") return redirect(url_for('web.index')) @@ -182,13 +182,13 @@ def remove_from_shelf(shelf_id, book_id): except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") if "HTTP_REFERER" in request.environ: return redirect(request.environ["HTTP_REFERER"]) else: return redirect(url_for('web.index')) if not xhr: - flash(_(u"Book has been removed from shelf: %(sname)s", sname=shelf.name), category="success") + flash(_("Book has been removed from shelf: %(sname)s", sname=shelf.name), category="success") if "HTTP_REFERER" in request.environ: return redirect(request.environ["HTTP_REFERER"]) else: @@ -197,7 +197,7 @@ def remove_from_shelf(shelf_id, book_id): else: if not xhr: log.warning("You are not allowed to remove a book from shelf: {}".format(shelf.name)) - flash(_(u"Sorry you are not allowed to remove a book from this shelf"), + flash(_("Sorry you are not allowed to remove a book from this shelf"), category="error") return redirect(url_for('web.index')) return "Sorry you are not allowed to remove a book from this shelf", 403 @@ -207,7 +207,7 @@ def remove_from_shelf(shelf_id, book_id): @login_required def create_shelf(): shelf = ub.Shelf() - return create_edit_shelf(shelf, page_title=_(u"Create a Shelf"), page="shelfcreate") + return create_edit_shelf(shelf, page_title=_("Create a Shelf"), page="shelfcreate") @shelf.route("/shelf/edit/", methods=["GET", "POST"]) @@ -215,9 +215,9 @@ def create_shelf(): def edit_shelf(shelf_id): shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first() if not check_shelf_edit_permissions(shelf): - flash(_(u"Sorry you are not allowed to edit this shelf"), category="error") + flash(_("Sorry you are not allowed to edit this shelf"), category="error") return redirect(url_for('web.index')) - return create_edit_shelf(shelf, page_title=_(u"Edit a shelf"), page="shelfedit", shelf_id=shelf_id) + return create_edit_shelf(shelf, page_title=_("Edit a shelf"), page="shelfedit", shelf_id=shelf_id) @shelf.route("/shelf/delete/", methods=["POST"]) @@ -232,7 +232,7 @@ def delete_shelf(shelf_id): except InvalidRequestError as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") return redirect(url_for('web.index')) @@ -269,7 +269,7 @@ def order_shelf(shelf_id): except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") result = list() if shelf: @@ -278,7 +278,7 @@ def order_shelf(shelf_id): .add_columns(calibre_db.common_filters().label("visible")) \ .filter(ub.BookShelf.shelf == shelf_id).order_by(ub.BookShelf.order.asc()).all() return render_title_template('shelf_order.html', entries=result, - title=_(u"Change order of Shelf: '%(name)s'", name=shelf.name), + title=_("Change order of Shelf: '%(name)s'", name=shelf.name), shelf=shelf, page="shelforder") else: abort(404) @@ -295,11 +295,14 @@ def check_shelf_edit_permissions(cur_shelf): def check_shelf_view_permissions(cur_shelf): - if cur_shelf.is_public: - return True - if current_user.is_anonymous or cur_shelf.user_id != current_user.id: - log.error("User is unauthorized to view non-public shelf: {}".format(cur_shelf.name)) - return False + try: + if cur_shelf.is_public: + return True + if current_user.is_anonymous or cur_shelf.user_id != current_user.id: + log.error("User is unauthorized to view non-public shelf: {}".format(cur_shelf.name)) + return False + except Exception as e: + log.error(e) return True @@ -310,7 +313,7 @@ def create_edit_shelf(shelf, page_title, page, shelf_id=False): if request.method == "POST": to_save = request.form.to_dict() if not current_user.role_edit_shelfs() and to_save.get("is_public") == "on": - flash(_(u"Sorry you are not allowed to create a public shelf"), category="error") + flash(_("Sorry you are not allowed to create a public shelf"), category="error") return redirect(url_for('web.index')) is_public = 1 if to_save.get("is_public") == "on" else 0 if config.config_kobo_sync: @@ -327,24 +330,24 @@ def create_edit_shelf(shelf, page_title, page, shelf_id=False): shelf.user_id = int(current_user.id) ub.session.add(shelf) shelf_action = "created" - flash_text = _(u"Shelf %(title)s created", title=shelf_title) + flash_text = _("Shelf %(title)s created", title=shelf_title) else: shelf_action = "changed" - flash_text = _(u"Shelf %(title)s changed", title=shelf_title) + flash_text = _("Shelf %(title)s changed", title=shelf_title) try: ub.session.commit() - log.info(u"Shelf {} {}".format(shelf_title, shelf_action)) + log.info("Shelf {} {}".format(shelf_title, shelf_action)) flash(flash_text, category="success") return redirect(url_for('shelf.show_shelf', shelf_id=shelf.id)) except (OperationalError, InvalidRequestError) as ex: ub.session.rollback() log.error_or_exception(ex) log.error_or_exception("Settings Database error: {}".format(ex)) - flash(_(u"Database error: %(error)s.", error=ex.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=ex.orig), category="error") except Exception as ex: ub.session.rollback() log.error_or_exception(ex) - flash(_(u"There was an error"), category="error") + flash(_("There was an error"), category="error") return render_title_template('shelf_edit.html', shelf=shelf, title=page_title, @@ -366,7 +369,7 @@ def check_shelf_is_unique(title, is_public, shelf_id=False): if not is_shelf_name_unique: log.error("A public shelf with the name '{}' already exists.".format(title)) - flash(_(u"A public shelf with the name '%(title)s' already exists.", title=title), + flash(_("A public shelf with the name '%(title)s' already exists.", title=title), category="error") else: is_shelf_name_unique = ub.session.query(ub.Shelf) \ @@ -377,7 +380,7 @@ def check_shelf_is_unique(title, is_public, shelf_id=False): if not is_shelf_name_unique: log.error("A private shelf with the name '{}' already exists.".format(title)) - flash(_(u"A private shelf with the name '%(title)s' already exists.", title=title), + flash(_("A private shelf with the name '%(title)s' already exists.", title=title), category="error") return is_shelf_name_unique @@ -454,14 +457,14 @@ def render_show_shelf(shelf_type, shelf_id, page_no, sort_param): except (OperationalError, InvalidRequestError) as e: ub.session.rollback() log.error_or_exception("Settings Database error: {}".format(e)) - flash(_(u"Database error: %(error)s.", error=e.orig), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e.orig), category="error") return render_title_template(page, entries=result, pagination=pagination, - title=_(u"Shelf: '%(name)s'", name=shelf.name), + title=_("Shelf: '%(name)s'", name=shelf.name), shelf=shelf, page="shelf") else: - flash(_(u"Error opening shelf. Shelf does not exist or is not accessible"), category="error") + flash(_("Error opening shelf. Shelf does not exist or is not accessible"), category="error") return redirect(url_for("web.index")) diff --git a/cps/static/css/caliBlur.css b/cps/static/css/caliBlur.css index b2b35423..3647b871 100644 --- a/cps/static/css/caliBlur.css +++ b/cps/static/css/caliBlur.css @@ -3290,10 +3290,13 @@ div.btn-group[role=group][aria-label="Download, send to Kindle, reading"] .dropd -ms-transform-origin: center top; transform-origin: center top; border: 0; - left: 0 !important; overflow-y: auto; } +.dropdown-menu:not(.datepicker-dropdown):not(.profileDropli) { + left: 0 !important; +} #add-to-shelves { + min-height: 48px; max-height: calc(100% - 120px); overflow-y: auto; } @@ -4423,38 +4426,6 @@ body.advanced_search > div.container-fluid > div.row-fluid > div.col-sm-10 > div left: 49px; margin-top: 5px } - - body:not(.blur) > .navbar > .container-fluid > .navbar-header:after, body:not(.blur) > .navbar > .container-fluid > .navbar-header:before { - color: hsla(0, 0%, 100%, .7); - cursor: pointer; - display: block; - font-family: plex-icons-new, serif; - font-size: 20px; - font-stretch: 100%; - font-style: normal; - font-variant-caps: normal; - font-variant-east-asian: normal; - font-variant-numeric: normal; - font-weight: 400; - height: 60px; - letter-spacing: normal; - line-height: 60px; - position: absolute - } - - body:not(.blur) > .navbar > .container-fluid > .navbar-header:before { - content: "\EA30"; - -webkit-font-variant-ligatures: normal; - font-variant-ligatures: normal; - left: 20px - } - - body:not(.blur) > .navbar > .container-fluid > .navbar-header:after { - content: "\EA2F"; - -webkit-font-variant-ligatures: normal; - font-variant-ligatures: normal; - left: 60px - } } body.admin > div.container-fluid > div > div.col-sm-10 > div.container-fluid > div.row:first-of-type > div.col > h2:before, body.admin > div.container-fluid > div > div.col-sm-10 > div.discover > h2:first-of-type:before, body.edituser.admin > div.container-fluid > div.row-fluid > div.col-sm-10 > div.discover > h1:before, body.newuser.admin > div.container-fluid > div.row-fluid > div.col-sm-10 > div.discover > h1:before { @@ -4842,8 +4813,14 @@ body.advsearch:not(.blur) > div.container-fluid > div.row-fluid > div.col-sm-10 z-index: 999999999999999999999999999999999999 } -.search #shelf-actions, body.login .home-btn { - display: none +body.search #shelf-actions button#add-to-shelf { + height: 40px; +} +@media screen and (max-width: 767px) { + body.search .discover, body.advsearch .discover { + display: flex; + flex-direction: column; + } } body.read:not(.blur) a[href*=readbooks] { @@ -5164,7 +5141,7 @@ body.login > div.navbar.navbar-default.navbar-static-top > div > div.navbar-head right: 5px } -#shelf-actions > .btn-group.open, .downloadBtn.open, .profileDrop[aria-expanded=true] { +body:not(.search) #shelf-actions > .btn-group.open, .downloadBtn.open, .profileDrop[aria-expanded=true] { pointer-events: none } @@ -5181,7 +5158,7 @@ body.login > div.navbar.navbar-default.navbar-static-top > div > div.navbar-head color: var(--color-primary) } -#shelf-actions, #shelf-actions > .btn-group, #shelf-actions > .btn-group > .empty-ul { +body:not(.search) #shelf-actions, body:not(.search) #shelf-actions > .btn-group, body:not(.search) #shelf-actions > .btn-group > .empty-ul { pointer-events: none } @@ -7309,6 +7286,11 @@ body.edituser.admin > div.container-fluid > div.row-fluid > div.col-sm-10 > div. float: right } + body.blur #main-nav + #scnd-nav .create-shelf, body.blur #main-nav + .col-sm-2 #scnd-nav .create-shelf { + float: none; + margin: 5px 0 10px -10px; + } + #main-nav + #scnd-nav .nav-head.hidden-xs { display: list-item !important; width: 225px diff --git a/cps/static/css/caliBlur_override.css b/cps/static/css/caliBlur_override.css index 4c8b6cb0..29fd7e29 100644 --- a/cps/static/css/caliBlur_override.css +++ b/cps/static/css/caliBlur_override.css @@ -22,3 +22,7 @@ body.serieslist.grid-view div.container-fluid > div > div.col-sm-10::before { padding: 0 0; line-height: 15px; } + +input.datepicker {color: transparent} +input.datepicker:focus {color: transparent} +input.datepicker:focus + input {color: #555} diff --git a/cps/static/css/kthoom.css b/cps/static/css/kthoom.css index 9565cd30..2c733e52 100644 --- a/cps/static/css/kthoom.css +++ b/cps/static/css/kthoom.css @@ -149,6 +149,20 @@ body { word-wrap: break-word; } +#mainContent > canvas { + display: block; + margin-left: auto; + margin-right: auto; +} + +.long-strip > .mainImage { + margin-bottom: 4px; +} + +.long-strip > .mainImage:last-child { + margin-bottom: 0px !important; +} + #titlebar { min-height: 25px; height: auto; diff --git a/cps/static/css/reader.css b/cps/static/css/reader.css new file mode 100644 index 00000000..ec8054ca --- /dev/null +++ b/cps/static/css/reader.css @@ -0,0 +1,29 @@ +.fontSizeWrapper { + position: relative; +} +.slider { + position: absolute; + top: 50%; + transform: translate(0,-50%); + width: 90%; + height: 60px; + background: transparent; + border-radius: 20px; + display: flex; + align-items: center; + box-shadow: 0px 15px 40px #7E6D5766; +} +.slider label { + font-size: 20px; + font-weight: 400; + font-family: Open Sans; + padding-right: 10px; + color: white; +} +.slider input[type="range"] { + width: 80%; + height: 5px; + background: black; + border: none; + outline: none; +} diff --git a/cps/static/css/style.css b/cps/static/css/style.css index 6e6b0eae..0bab5b53 100644 --- a/cps/static/css/style.css +++ b/cps/static/css/style.css @@ -140,6 +140,7 @@ table .bg-dark-danger a { color: #fff; } .container-fluid .book { margin-top: 20px; + max-width: 180px; display: flex; flex-direction: column; } @@ -433,3 +434,7 @@ div.log { #detailcover:-moz-full-screen { cursor:zoom-out; border: 0; } #detailcover:-ms-fullscreen { cursor:zoom-out; border: 0; } #detailcover:fullscreen { cursor:zoom-out; border: 0; } + +.error-list { + margin-top: 5px; + } diff --git a/cps/static/js/caliBlur.js b/cps/static/js/caliBlur.js index 0f179645..909a3d22 100755 --- a/cps/static/js/caliBlur.js +++ b/cps/static/js/caliBlur.js @@ -16,7 +16,6 @@ */ // Move advanced search to side-menu $("a[href*='advanced']").parent().insertAfter("#nav_new"); -$("body").addClass("blur"); $("body.stat").addClass("stats"); $("body.config").addClass("admin"); $("body.uiconfig").addClass("admin"); @@ -29,8 +28,8 @@ $("body > div.container-fluid > div > div.col-sm-10 > div.filterheader").attr("s // Back button curHref = window.location.href.split("/"); prevHref = document.referrer.split("/"); -$(".navbar-form.navbar-left") - .before('
'); +$(".plexBack a").attr('href', encodeURI(document.referrer)); + if (history.length === 1 || curHref[0] + curHref[1] + @@ -44,14 +43,9 @@ if (history.length === 1 || //Weird missing a after pressing back from edit. setTimeout(function () { - if ($(".plexBack a").length < 1) { - $(".plexBack").append(''); - } + $(".plexBack a").attr('href', encodeURI(document.referrer)); }, 10); -// Home button -$(".plexBack").before('
'); -$("a.navbar-brand").clone().appendTo(".home-btn").empty().removeClass("navbar-brand"); ///////////////////////////////// // Start of Book Details Work // /////////////////////////////// @@ -320,19 +314,11 @@ $(document).mouseup(function (e) { }); }); -// Split path name to array and remove blanks -url = window.location.pathname - // Move create shelf $("#nav_createshelf").prependTo(".your-shelves"); -// Create drop-down for profile and move elements to it -$("#main-nav") - .prepend(''); -$("#top_user").parent().addClass("dropdown").appendTo(".profileDropli"); -$("#nav_about").addClass("dropdown").appendTo(".profileDropli"); -$("#register").parent().addClass("dropdown").appendTo(".profileDropli"); -$("#logout").parent().addClass("dropdown").appendTo(".profileDropli"); +// Move About link it the profile dropdown +$(".profileDropli #top_user").parent().after($("#nav_about").addClass("dropdown")) // Remove the modals except from some areas where they are needed bodyClass = $("body").attr("class").split(" "); @@ -371,31 +357,6 @@ $(document).on("click", ".dropdown-toggle", function () { }); }); -// Fade out content on page unload -// delegate all clicks on "a" tag (links) -/*$(document).on("click", "a:not(.btn-toolbar a, a[href*='shelf/remove'], .identifiers a, .bookinfo , .btn-group > a, #add-to-shelves a, #book-list a, .stat.blur a )", function () { - - // get the href attribute - var newUrl = $(this).attr("href"); - - // veryfy if the new url exists or is a hash - if (!newUrl || newUrl[0] === "#") { - // set that hash - location.hash = newUrl; - return; - } - - now, fadeout the html (whole page) - $( '.blur-wrapper' ).fadeOut(250); - $(".row-fluid .col-sm-10").fadeOut(500,function () { - // when the animation is complete, set the new location - location = newUrl; - }); - - // prevent the default browser behavior. - return false; -});*/ - // Collapse long text into read-more $("div.comments").readmore({ collapsedHeight: 134, @@ -408,6 +369,13 @@ $("div.comments").readmore({ // End of Global Work // /////////////////////////////// +// Search Results +if($("body.search").length > 0) { + $('div[aria-label="Add to shelves"]').click(function () { + $("#add-to-shelves").toggle(); + }); +} + // Advanced Search Results if($("body.advsearch").length > 0) { $("#loader + .container-fluid") @@ -458,6 +426,8 @@ if ($("body.author").length > 0) { } } +// Split path name to array and remove blanks +url = window.location.pathname // Ereader Page - add class to iframe body on ereader page after it loads. backurl = "../../book/" + url[2] $("body.epub #title-controls") @@ -540,6 +510,7 @@ if ($("body.shelf").length > 0) { // Rest of Tooltips $(".home-btn > a").attr({ "data-toggle": "tooltip", + "href": $(".navbar-brand")[0].href, "title": $(document.body).attr("data-text"), // Home "data-placement": "bottom" }) @@ -666,7 +637,7 @@ $("#sendbtn").attr({ $("#sendbtn2").attr({ "data-toggle-two": "tooltip", - "title": $("#sendbtn2").text(), // "Send to E-Reader", + "title": $("#sendbtn2").text(), // "Send to eReader", "data-placement": "bottom", "data-viewport": ".btn-toolbar" }) diff --git a/cps/static/js/compress/jszip.js b/cps/static/js/compress/jszip.js deleted file mode 100644 index 1546d7fc..00000000 --- a/cps/static/js/compress/jszip.js +++ /dev/null @@ -1,9155 +0,0 @@ -/*! - -JSZip - A Javascript class for generating and reading zip files - - -(c) 2009-2014 Stuart Knightley -Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. - -JSZip uses the library pako released under the MIT license : -https://github.com/nodeca/pako/blob/master/LICENSE -*/ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.JSZip=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); - enc4 = chr3 & 63; - - if (isNaN(chr2)) { - enc3 = enc4 = 64; - } - else if (isNaN(chr3)) { - enc4 = 64; - } - - output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4); - - } - - return output; -}; - -// public method for decoding -exports.decode = function(input, utf8) { - var output = ""; - var chr1, chr2, chr3; - var enc1, enc2, enc3, enc4; - var i = 0; - - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); - - while (i < input.length) { - - enc1 = _keyStr.indexOf(input.charAt(i++)); - enc2 = _keyStr.indexOf(input.charAt(i++)); - enc3 = _keyStr.indexOf(input.charAt(i++)); - enc4 = _keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - - output = output + String.fromCharCode(chr1); - - if (enc3 != 64) { - output = output + String.fromCharCode(chr2); - } - if (enc4 != 64) { - output = output + String.fromCharCode(chr3); - } - - } - - return output; - -}; - -},{}],2:[function(_dereq_,module,exports){ -'use strict'; -function CompressedObject() { - this.compressedSize = 0; - this.uncompressedSize = 0; - this.crc32 = 0; - this.compressionMethod = null; - this.compressedContent = null; -} - -CompressedObject.prototype = { - /** - * Return the decompressed content in an unspecified format. - * The format will depend on the decompressor. - * @return {Object} the decompressed content. - */ - getContent: function() { - return null; // see implementation - }, - /** - * Return the compressed content in an unspecified format. - * The format will depend on the compressed conten source. - * @return {Object} the compressed content. - */ - getCompressedContent: function() { - return null; // see implementation - } -}; -module.exports = CompressedObject; - -},{}],3:[function(_dereq_,module,exports){ -'use strict'; -exports.STORE = { - magic: "\x00\x00", - compress: function(content, compressionOptions) { - return content; // no compression - }, - uncompress: function(content) { - return content; // no compression - }, - compressInputType: null, - uncompressInputType: null -}; -exports.DEFLATE = _dereq_('./flate'); - -},{"./flate":8}],4:[function(_dereq_,module,exports){ -'use strict'; - -var utils = _dereq_('./utils'); - -var table = [ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -]; - -/** - * - * Javascript crc32 - * http://www.webtoolkit.info/ - * - */ -module.exports = function crc32(input, crc) { - if (typeof input === "undefined" || !input.length) { - return 0; - } - - var isArray = utils.getTypeOf(input) !== "string"; - - if (typeof(crc) == "undefined") { - crc = 0; - } - var x = 0; - var y = 0; - var b = 0; - - crc = crc ^ (-1); - for (var i = 0, iTop = input.length; i < iTop; i++) { - b = isArray ? input[i] : input.charCodeAt(i); - y = (crc ^ b) & 0xFF; - x = table[y]; - crc = (crc >>> 8) ^ x; - } - - return crc ^ (-1); -}; -// vim: set shiftwidth=4 softtabstop=4: - -},{"./utils":21}],5:[function(_dereq_,module,exports){ -'use strict'; -var utils = _dereq_('./utils'); - -function DataReader(data) { - this.data = null; // type : see implementation - this.length = 0; - this.index = 0; -} -DataReader.prototype = { - /** - * Check that the offset will not go too far. - * @param {string} offset the additional offset to check. - * @throws {Error} an Error if the offset is out of bounds. - */ - checkOffset: function(offset) { - this.checkIndex(this.index + offset); - }, - /** - * Check that the specifed index will not be too far. - * @param {string} newIndex the index to check. - * @throws {Error} an Error if the index is out of bounds. - */ - checkIndex: function(newIndex) { - if (this.length < newIndex || newIndex < 0) { - throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); - } - }, - /** - * Change the index. - * @param {number} newIndex The new index. - * @throws {Error} if the new index is out of the data. - */ - setIndex: function(newIndex) { - this.checkIndex(newIndex); - this.index = newIndex; - }, - /** - * Skip the next n bytes. - * @param {number} n the number of bytes to skip. - * @throws {Error} if the new index is out of the data. - */ - skip: function(n) { - this.setIndex(this.index + n); - }, - /** - * Get the byte at the specified index. - * @param {number} i the index to use. - * @return {number} a byte. - */ - byteAt: function(i) { - // see implementations - }, - /** - * Get the next number with a given byte size. - * @param {number} size the number of bytes to read. - * @return {number} the corresponding number. - */ - readInt: function(size) { - var result = 0, - i; - this.checkOffset(size); - for (i = this.index + size - 1; i >= this.index; i--) { - result = (result << 8) + this.byteAt(i); - } - this.index += size; - return result; - }, - /** - * Get the next string with a given byte size. - * @param {number} size the number of bytes to read. - * @return {string} the corresponding string. - */ - readString: function(size) { - return utils.transformTo("string", this.readData(size)); - }, - /** - * Get raw data without conversion, bytes. - * @param {number} size the number of bytes to read. - * @return {Object} the raw data, implementation specific. - */ - readData: function(size) { - // see implementations - }, - /** - * Find the last occurence of a zip signature (4 bytes). - * @param {string} sig the signature to find. - * @return {number} the index of the last occurence, -1 if not found. - */ - lastIndexOfSignature: function(sig) { - // see implementations - }, - /** - * Get the next date. - * @return {Date} the date. - */ - readDate: function() { - var dostime = this.readInt(4); - return new Date( - ((dostime >> 25) & 0x7f) + 1980, // year - ((dostime >> 21) & 0x0f) - 1, // month - (dostime >> 16) & 0x1f, // day - (dostime >> 11) & 0x1f, // hour - (dostime >> 5) & 0x3f, // minute - (dostime & 0x1f) << 1); // second - } -}; -module.exports = DataReader; - -},{"./utils":21}],6:[function(_dereq_,module,exports){ -'use strict'; -exports.base64 = false; -exports.binary = false; -exports.dir = false; -exports.createFolders = false; -exports.date = null; -exports.compression = null; -exports.compressionOptions = null; -exports.comment = null; -exports.unixPermissions = null; -exports.dosPermissions = null; - -},{}],7:[function(_dereq_,module,exports){ -'use strict'; -var utils = _dereq_('./utils'); - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.string2binary = function(str) { - return utils.string2binary(str); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.string2Uint8Array = function(str) { - return utils.transformTo("uint8array", str); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.uint8Array2String = function(array) { - return utils.transformTo("string", array); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.string2Blob = function(str) { - var buffer = utils.transformTo("arraybuffer", str); - return utils.arrayBuffer2Blob(buffer); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.arrayBuffer2Blob = function(buffer) { - return utils.arrayBuffer2Blob(buffer); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.transformTo = function(outputType, input) { - return utils.transformTo(outputType, input); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.getTypeOf = function(input) { - return utils.getTypeOf(input); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.checkSupport = function(type) { - return utils.checkSupport(type); -}; - -/** - * @deprecated - * This value will be removed in a future version without replacement. - */ -exports.MAX_VALUE_16BITS = utils.MAX_VALUE_16BITS; - -/** - * @deprecated - * This value will be removed in a future version without replacement. - */ -exports.MAX_VALUE_32BITS = utils.MAX_VALUE_32BITS; - - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.pretty = function(str) { - return utils.pretty(str); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.findCompression = function(compressionMethod) { - return utils.findCompression(compressionMethod); -}; - -/** - * @deprecated - * This function will be removed in a future version without replacement. - */ -exports.isRegExp = function (object) { - return utils.isRegExp(object); -}; - - -},{"./utils":21}],8:[function(_dereq_,module,exports){ -'use strict'; -var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); - -var pako = _dereq_("pako"); -exports.uncompressInputType = USE_TYPEDARRAY ? "uint8array" : "array"; -exports.compressInputType = USE_TYPEDARRAY ? "uint8array" : "array"; - -exports.magic = "\x08\x00"; -exports.compress = function(input, compressionOptions) { - return pako.deflateRaw(input, { - level : compressionOptions.level || -1 // default compression - }); -}; -exports.uncompress = function(input) { - return pako.inflateRaw(input); -}; - -},{"pako":24}],9:[function(_dereq_,module,exports){ -'use strict'; - -var base64 = _dereq_('./base64'); - -/** -Usage: - zip = new JSZip(); - zip.file("hello.txt", "Hello, World!").file("tempfile", "nothing"); - zip.folder("images").file("smile.gif", base64Data, {base64: true}); - zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")}); - zip.remove("tempfile"); - - base64zip = zip.generate(); - -**/ - -/** - * Representation a of zip file in js - * @constructor - * @param {String=|ArrayBuffer=|Uint8Array=} data the data to load, if any (optional). - * @param {Object=} options the options for creating this objects (optional). - */ -function JSZip(data, options) { - // if this constructor is used without `new`, it adds `new` before itself: - if(!(this instanceof JSZip)) return new JSZip(data, options); - - // object containing the files : - // { - // "folder/" : {...}, - // "folder/data.txt" : {...} - // } - this.files = {}; - - this.comment = null; - - // Where we are in the hierarchy - this.root = ""; - if (data) { - this.load(data, options); - } - this.clone = function() { - var newObj = new JSZip(); - for (var i in this) { - if (typeof this[i] !== "function") { - newObj[i] = this[i]; - } - } - return newObj; - }; -} -JSZip.prototype = _dereq_('./object'); -JSZip.prototype.load = _dereq_('./load'); -JSZip.support = _dereq_('./support'); -JSZip.defaults = _dereq_('./defaults'); - -/** - * @deprecated - * This namespace will be removed in a future version without replacement. - */ -JSZip.utils = _dereq_('./deprecatedPublicUtils'); - -JSZip.base64 = { - /** - * @deprecated - * This method will be removed in a future version without replacement. - */ - encode : function(input) { - return base64.encode(input); - }, - /** - * @deprecated - * This method will be removed in a future version without replacement. - */ - decode : function(input) { - return base64.decode(input); - } -}; -JSZip.compressions = _dereq_('./compressions'); -module.exports = JSZip; - -},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(_dereq_,module,exports){ -'use strict'; -var base64 = _dereq_('./base64'); -var ZipEntries = _dereq_('./zipEntries'); -module.exports = function(data, options) { - var files, zipEntries, i, input; - options = options || {}; - if (options.base64) { - data = base64.decode(data); - } - - zipEntries = new ZipEntries(data, options); - files = zipEntries.files; - for (i = 0; i < files.length; i++) { - input = files[i]; - this.file(input.fileName, input.decompressed, { - binary: true, - optimizedBinaryString: true, - date: input.date, - dir: input.dir, - comment : input.fileComment.length ? input.fileComment : null, - unixPermissions : input.unixPermissions, - dosPermissions : input.dosPermissions, - createFolders: options.createFolders - }); - } - if (zipEntries.zipComment.length) { - this.comment = zipEntries.zipComment; - } - - return this; -}; - -},{"./base64":1,"./zipEntries":22}],11:[function(_dereq_,module,exports){ -(function (Buffer){ -'use strict'; -module.exports = function(data, encoding){ - return new Buffer(data, encoding); -}; -module.exports.test = function(b){ - return Buffer.isBuffer(b); -}; - -}).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined)) -},{}],12:[function(_dereq_,module,exports){ -'use strict'; -var Uint8ArrayReader = _dereq_('./uint8ArrayReader'); - -function NodeBufferReader(data) { - this.data = data; - this.length = this.data.length; - this.index = 0; -} -NodeBufferReader.prototype = new Uint8ArrayReader(); - -/** - * @see DataReader.readData - */ -NodeBufferReader.prototype.readData = function(size) { - this.checkOffset(size); - var result = this.data.slice(this.index, this.index + size); - this.index += size; - return result; -}; -module.exports = NodeBufferReader; - -},{"./uint8ArrayReader":18}],13:[function(_dereq_,module,exports){ -'use strict'; -var support = _dereq_('./support'); -var utils = _dereq_('./utils'); -var crc32 = _dereq_('./crc32'); -var signature = _dereq_('./signature'); -var defaults = _dereq_('./defaults'); -var base64 = _dereq_('./base64'); -var compressions = _dereq_('./compressions'); -var CompressedObject = _dereq_('./compressedObject'); -var nodeBuffer = _dereq_('./nodeBuffer'); -var utf8 = _dereq_('./utf8'); -var StringWriter = _dereq_('./stringWriter'); -var Uint8ArrayWriter = _dereq_('./uint8ArrayWriter'); - -/** - * Returns the raw data of a ZipObject, decompress the content if necessary. - * @param {ZipObject} file the file to use. - * @return {String|ArrayBuffer|Uint8Array|Buffer} the data. - */ -var getRawData = function(file) { - if (file._data instanceof CompressedObject) { - file._data = file._data.getContent(); - file.options.binary = true; - file.options.base64 = false; - - if (utils.getTypeOf(file._data) === "uint8array") { - var copy = file._data; - // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array. - // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file). - file._data = new Uint8Array(copy.length); - // with an empty Uint8Array, Opera fails with a "Offset larger than array size" - if (copy.length !== 0) { - file._data.set(copy, 0); - } - } - } - return file._data; -}; - -/** - * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it. - * @param {ZipObject} file the file to use. - * @return {String|ArrayBuffer|Uint8Array|Buffer} the data. - */ -var getBinaryData = function(file) { - var result = getRawData(file), - type = utils.getTypeOf(result); - if (type === "string") { - if (!file.options.binary) { - // unicode text ! - // unicode string => binary string is a painful process, check if we can avoid it. - if (support.nodebuffer) { - return nodeBuffer(result, "utf-8"); - } - } - return file.asBinary(); - } - return result; -}; - -/** - * Transform this._data into a string. - * @param {function} filter a function String -> String, applied if not null on the result. - * @return {String} the string representing this._data. - */ -var dataToString = function(asUTF8) { - var result = getRawData(this); - if (result === null || typeof result === "undefined") { - return ""; - } - // if the data is a base64 string, we decode it before checking the encoding ! - if (this.options.base64) { - result = base64.decode(result); - } - if (asUTF8 && this.options.binary) { - // JSZip.prototype.utf8decode supports arrays as input - // skip to array => string step, utf8decode will do it. - result = out.utf8decode(result); - } - else { - // no utf8 transformation, do the array => string step. - result = utils.transformTo("string", result); - } - - if (!asUTF8 && !this.options.binary) { - result = utils.transformTo("string", out.utf8encode(result)); - } - return result; -}; -/** - * A simple object representing a file in the zip file. - * @constructor - * @param {string} name the name of the file - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data - * @param {Object} options the options of the file - */ -var ZipObject = function(name, data, options) { - this.name = name; - this.dir = options.dir; - this.date = options.date; - this.comment = options.comment; - this.unixPermissions = options.unixPermissions; - this.dosPermissions = options.dosPermissions; - - this._data = data; - this.options = options; - - /* - * This object contains initial values for dir and date. - * With them, we can check if the user changed the deprecated metadata in - * `ZipObject#options` or not. - */ - this._initialMetadata = { - dir : options.dir, - date : options.date - }; -}; - -ZipObject.prototype = { - /** - * Return the content as UTF8 string. - * @return {string} the UTF8 string. - */ - asText: function() { - return dataToString.call(this, true); - }, - /** - * Returns the binary content. - * @return {string} the content as binary. - */ - asBinary: function() { - return dataToString.call(this, false); - }, - /** - * Returns the content as a nodejs Buffer. - * @return {Buffer} the content as a Buffer. - */ - asNodeBuffer: function() { - var result = getBinaryData(this); - return utils.transformTo("nodebuffer", result); - }, - /** - * Returns the content as an Uint8Array. - * @return {Uint8Array} the content as an Uint8Array. - */ - asUint8Array: function() { - var result = getBinaryData(this); - return utils.transformTo("uint8array", result); - }, - /** - * Returns the content as an ArrayBuffer. - * @return {ArrayBuffer} the content as an ArrayBufer. - */ - asArrayBuffer: function() { - return this.asUint8Array().buffer; - } -}; - -/** - * Transform an integer into a string in hexadecimal. - * @private - * @param {number} dec the number to convert. - * @param {number} bytes the number of bytes to generate. - * @returns {string} the result. - */ -var decToHex = function(dec, bytes) { - var hex = "", - i; - for (i = 0; i < bytes; i++) { - hex += String.fromCharCode(dec & 0xff); - dec = dec >>> 8; - } - return hex; -}; - -/** - * Merge the objects passed as parameters into a new one. - * @private - * @param {...Object} var_args All objects to merge. - * @return {Object} a new object with the data of the others. - */ -var extend = function() { - var result = {}, i, attr; - for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers - for (attr in arguments[i]) { - if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { - result[attr] = arguments[i][attr]; - } - } - } - return result; -}; - -/** - * Transforms the (incomplete) options from the user into the complete - * set of options to create a file. - * @private - * @param {Object} o the options from the user. - * @return {Object} the complete set of options. - */ -var prepareFileAttrs = function(o) { - o = o || {}; - if (o.base64 === true && (o.binary === null || o.binary === undefined)) { - o.binary = true; - } - o = extend(o, defaults); - o.date = o.date || new Date(); - if (o.compression !== null) o.compression = o.compression.toUpperCase(); - - return o; -}; - -/** - * Add a file in the current folder. - * @private - * @param {string} name the name of the file - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file - * @param {Object} o the options of the file - * @return {Object} the new file. - */ -var fileAdd = function(name, data, o) { - // be sure sub folders exist - var dataType = utils.getTypeOf(data), - parent; - - o = prepareFileAttrs(o); - - if (typeof o.unixPermissions === "string") { - o.unixPermissions = parseInt(o.unixPermissions, 8); - } - - // UNX_IFDIR 0040000 see zipinfo.c - if (o.unixPermissions && (o.unixPermissions & 0x4000)) { - o.dir = true; - } - // Bit 4 Directory - if (o.dosPermissions && (o.dosPermissions & 0x0010)) { - o.dir = true; - } - - if (o.dir) { - name = forceTrailingSlash(name); - } - - if (o.createFolders && (parent = parentFolder(name))) { - folderAdd.call(this, parent, true); - } - - if (o.dir || data === null || typeof data === "undefined") { - o.base64 = false; - o.binary = false; - data = null; - dataType = null; - } - else if (dataType === "string") { - if (o.binary && !o.base64) { - // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask - if (o.optimizedBinaryString !== true) { - // this is a string, not in a base64 format. - // Be sure that this is a correct "binary string" - data = utils.string2binary(data); - } - } - } - else { // arraybuffer, uint8array, ... - o.base64 = false; - o.binary = true; - - if (!dataType && !(data instanceof CompressedObject)) { - throw new Error("The data of '" + name + "' is in an unsupported format !"); - } - - // special case : it's way easier to work with Uint8Array than with ArrayBuffer - if (dataType === "arraybuffer") { - data = utils.transformTo("uint8array", data); - } - } - - var object = new ZipObject(name, data, o); - this.files[name] = object; - return object; -}; - -/** - * Find the parent folder of the path. - * @private - * @param {string} path the path to use - * @return {string} the parent folder, or "" - */ -var parentFolder = function (path) { - if (path.slice(-1) == '/') { - path = path.substring(0, path.length - 1); - } - var lastSlash = path.lastIndexOf('/'); - return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; -}; - - -/** - * Returns the path with a slash at the end. - * @private - * @param {String} path the path to check. - * @return {String} the path with a trailing slash. - */ -var forceTrailingSlash = function(path) { - // Check the name ends with a / - if (path.slice(-1) != "/") { - path += "/"; // IE doesn't like substr(-1) - } - return path; -}; -/** - * Add a (sub) folder in the current folder. - * @private - * @param {string} name the folder's name - * @param {boolean=} [createFolders] If true, automatically create sub - * folders. Defaults to false. - * @return {Object} the new folder. - */ -var folderAdd = function(name, createFolders) { - createFolders = (typeof createFolders !== 'undefined') ? createFolders : false; - - name = forceTrailingSlash(name); - - // Does this folder already exist? - if (!this.files[name]) { - fileAdd.call(this, name, null, { - dir: true, - createFolders: createFolders - }); - } - return this.files[name]; -}; - -/** - * Generate a JSZip.CompressedObject for a given zipOject. - * @param {ZipObject} file the object to read. - * @param {JSZip.compression} compression the compression to use. - * @param {Object} compressionOptions the options to use when compressing. - * @return {JSZip.CompressedObject} the compressed result. - */ -var generateCompressedObjectFrom = function(file, compression, compressionOptions) { - var result = new CompressedObject(), - content; - - // the data has not been decompressed, we might reuse things ! - if (file._data instanceof CompressedObject) { - result.uncompressedSize = file._data.uncompressedSize; - result.crc32 = file._data.crc32; - - if (result.uncompressedSize === 0 || file.dir) { - compression = compressions['STORE']; - result.compressedContent = ""; - result.crc32 = 0; - } - else if (file._data.compressionMethod === compression.magic) { - result.compressedContent = file._data.getCompressedContent(); - } - else { - content = file._data.getContent(); - // need to decompress / recompress - result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content), compressionOptions); - } - } - else { - // have uncompressed data - content = getBinaryData(file); - if (!content || content.length === 0 || file.dir) { - compression = compressions['STORE']; - content = ""; - } - result.uncompressedSize = content.length; - result.crc32 = crc32(content); - result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content), compressionOptions); - } - - result.compressedSize = result.compressedContent.length; - result.compressionMethod = compression.magic; - - return result; -}; - - - - -/** - * Generate the UNIX part of the external file attributes. - * @param {Object} unixPermissions the unix permissions or null. - * @param {Boolean} isDir true if the entry is a directory, false otherwise. - * @return {Number} a 32 bit integer. - * - * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : - * - * TTTTsstrwxrwxrwx0000000000ADVSHR - * ^^^^____________________________ file type, see zipinfo.c (UNX_*) - * ^^^_________________________ setuid, setgid, sticky - * ^^^^^^^^^________________ permissions - * ^^^^^^^^^^______ not used ? - * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only - */ -var generateUnixExternalFileAttr = function (unixPermissions, isDir) { - - var result = unixPermissions; - if (!unixPermissions) { - // I can't use octal values in strict mode, hence the hexa. - // 040775 => 0x41fd - // 0100664 => 0x81b4 - result = isDir ? 0x41fd : 0x81b4; - } - - return (result & 0xFFFF) << 16; -}; - -/** - * Generate the DOS part of the external file attributes. - * @param {Object} dosPermissions the dos permissions or null. - * @param {Boolean} isDir true if the entry is a directory, false otherwise. - * @return {Number} a 32 bit integer. - * - * Bit 0 Read-Only - * Bit 1 Hidden - * Bit 2 System - * Bit 3 Volume Label - * Bit 4 Directory - * Bit 5 Archive - */ -var generateDosExternalFileAttr = function (dosPermissions, isDir) { - - // the dir flag is already set for compatibility - - return (dosPermissions || 0) & 0x3F; -}; - -/** - * Generate the various parts used in the construction of the final zip file. - * @param {string} name the file name. - * @param {ZipObject} file the file content. - * @param {JSZip.CompressedObject} compressedObject the compressed object. - * @param {number} offset the current offset from the start of the zip file. - * @param {String} platform let's pretend we are this platform (change platform dependents fields) - * @return {object} the zip parts. - */ -var generateZipParts = function(name, file, compressedObject, offset, platform) { - var data = compressedObject.compressedContent, - utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), - comment = file.comment || "", - utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), - useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, - useUTF8ForComment = utfEncodedComment.length !== comment.length, - o = file.options, - dosTime, - dosDate, - extraFields = "", - unicodePathExtraField = "", - unicodeCommentExtraField = "", - dir, date; - - - // handle the deprecated options.dir - if (file._initialMetadata.dir !== file.dir) { - dir = file.dir; - } else { - dir = o.dir; - } - - // handle the deprecated options.date - if(file._initialMetadata.date !== file.date) { - date = file.date; - } else { - date = o.date; - } - - var extFileAttr = 0; - var versionMadeBy = 0; - if (dir) { - // dos or unix, we set the dos dir flag - extFileAttr |= 0x00010; - } - if(platform === "UNIX") { - versionMadeBy = 0x031E; // UNIX, version 3.0 - extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); - } else { // DOS or other, fallback to DOS - versionMadeBy = 0x0014; // DOS, version 2.0 - extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); - } - - // date - // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html - // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html - // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html - - dosTime = date.getHours(); - dosTime = dosTime << 6; - dosTime = dosTime | date.getMinutes(); - dosTime = dosTime << 5; - dosTime = dosTime | date.getSeconds() / 2; - - dosDate = date.getFullYear() - 1980; - dosDate = dosDate << 4; - dosDate = dosDate | (date.getMonth() + 1); - dosDate = dosDate << 5; - dosDate = dosDate | date.getDate(); - - if (useUTF8ForFileName) { - // set the unicode path extra field. unzip needs at least one extra - // field to correctly handle unicode path, so using the path is as good - // as any other information. This could improve the situation with - // other archive managers too. - // This field is usually used without the utf8 flag, with a non - // unicode path in the header (winrar, winzip). This helps (a bit) - // with the messy Windows' default compressed folders feature but - // breaks on p7zip which doesn't seek the unicode path extra field. - // So for now, UTF-8 everywhere ! - unicodePathExtraField = - // Version - decToHex(1, 1) + - // NameCRC32 - decToHex(crc32(utfEncodedFileName), 4) + - // UnicodeName - utfEncodedFileName; - - extraFields += - // Info-ZIP Unicode Path Extra Field - "\x75\x70" + - // size - decToHex(unicodePathExtraField.length, 2) + - // content - unicodePathExtraField; - } - - if(useUTF8ForComment) { - - unicodeCommentExtraField = - // Version - decToHex(1, 1) + - // CommentCRC32 - decToHex(this.crc32(utfEncodedComment), 4) + - // UnicodeName - utfEncodedComment; - - extraFields += - // Info-ZIP Unicode Path Extra Field - "\x75\x63" + - // size - decToHex(unicodeCommentExtraField.length, 2) + - // content - unicodeCommentExtraField; - } - - var header = ""; - - // version needed to extract - header += "\x0A\x00"; - // general purpose bit flag - // set bit 11 if utf8 - header += (useUTF8ForFileName || useUTF8ForComment) ? "\x00\x08" : "\x00\x00"; - // compression method - header += compressedObject.compressionMethod; - // last mod file time - header += decToHex(dosTime, 2); - // last mod file date - header += decToHex(dosDate, 2); - // crc-32 - header += decToHex(compressedObject.crc32, 4); - // compressed size - header += decToHex(compressedObject.compressedSize, 4); - // uncompressed size - header += decToHex(compressedObject.uncompressedSize, 4); - // file name length - header += decToHex(utfEncodedFileName.length, 2); - // extra field length - header += decToHex(extraFields.length, 2); - - - var fileRecord = signature.LOCAL_FILE_HEADER + header + utfEncodedFileName + extraFields; - - var dirRecord = signature.CENTRAL_FILE_HEADER + - // version made by (00: DOS) - decToHex(versionMadeBy, 2) + - // file header (common to file and central directory) - header + - // file comment length - decToHex(utfEncodedComment.length, 2) + - // disk number start - "\x00\x00" + - // internal file attributes TODO - "\x00\x00" + - // external file attributes - decToHex(extFileAttr, 4) + - // relative offset of local header - decToHex(offset, 4) + - // file name - utfEncodedFileName + - // extra field - extraFields + - // file comment - utfEncodedComment; - - return { - fileRecord: fileRecord, - dirRecord: dirRecord, - compressedObject: compressedObject - }; -}; - - -// return the actual prototype of JSZip -var out = { - /** - * Read an existing zip and merge the data in the current JSZip object. - * The implementation is in jszip-load.js, don't forget to include it. - * @param {String|ArrayBuffer|Uint8Array|Buffer} stream The stream to load - * @param {Object} options Options for loading the stream. - * options.base64 : is the stream in base64 ? default : false - * @return {JSZip} the current JSZip object - */ - load: function(stream, options) { - throw new Error("Load method is not defined. Is the file jszip-load.js included ?"); - }, - - /** - * Filter nested files/folders with the specified function. - * @param {Function} search the predicate to use : - * function (relativePath, file) {...} - * It takes 2 arguments : the relative path and the file. - * @return {Array} An array of matching elements. - */ - filter: function(search) { - var result = [], - filename, relativePath, file, fileClone; - for (filename in this.files) { - if (!this.files.hasOwnProperty(filename)) { - continue; - } - file = this.files[filename]; - // return a new object, don't let the user mess with our internal objects :) - fileClone = new ZipObject(file.name, file._data, extend(file.options)); - relativePath = filename.slice(this.root.length, filename.length); - if (filename.slice(0, this.root.length) === this.root && // the file is in the current root - search(relativePath, fileClone)) { // and the file matches the function - result.push(fileClone); - } - } - return result; - }, - - /** - * Add a file to the zip file, or search a file. - * @param {string|RegExp} name The name of the file to add (if data is defined), - * the name of the file to find (if no data) or a regex to match files. - * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded - * @param {Object} o File options - * @return {JSZip|Object|Array} this JSZip object (when adding a file), - * a file (when searching by string) or an array of files (when searching by regex). - */ - file: function(name, data, o) { - if (arguments.length === 1) { - if (utils.isRegExp(name)) { - var regexp = name; - return this.filter(function(relativePath, file) { - return !file.dir && regexp.test(relativePath); - }); - } - else { // text - return this.filter(function(relativePath, file) { - return !file.dir && relativePath === name; - })[0] || null; - } - } - else { // more than one argument : we have data ! - name = this.root + name; - fileAdd.call(this, name, data, o); - } - return this; - }, - - /** - * Add a directory to the zip file, or search. - * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. - * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. - */ - folder: function(arg) { - if (!arg) { - return this; - } - - if (utils.isRegExp(arg)) { - return this.filter(function(relativePath, file) { - return file.dir && arg.test(relativePath); - }); - } - - // else, name is a new folder - var name = this.root + arg; - var newFolder = folderAdd.call(this, name); - - // Allow chaining by returning a new object with this folder as the root - var ret = this.clone(); - ret.root = newFolder.name; - return ret; - }, - - /** - * Delete a file, or a directory and all sub-files, from the zip - * @param {string} name the name of the file to delete - * @return {JSZip} this JSZip object - */ - remove: function(name) { - name = this.root + name; - var file = this.files[name]; - if (!file) { - // Look for any folders - if (name.slice(-1) != "/") { - name += "/"; - } - file = this.files[name]; - } - - if (file && !file.dir) { - // file - delete this.files[name]; - } else { - // maybe a folder, delete recursively - var kids = this.filter(function(relativePath, file) { - return file.name.slice(0, name.length) === name; - }); - for (var i = 0; i < kids.length; i++) { - delete this.files[kids[i].name]; - } - } - - return this; - }, - - /** - * Generate the complete zip file - * @param {Object} options the options to generate the zip file : - * - base64, (deprecated, use type instead) true to generate base64. - * - compression, "STORE" by default. - * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. - * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file - */ - generate: function(options) { - options = extend(options || {}, { - base64: true, - compression: "STORE", - compressionOptions : null, - type: "base64", - platform: "DOS", - comment: null, - mimeType: 'application/zip' - }); - - utils.checkSupport(options.type); - - // accept nodejs `process.platform` - if( - options.platform === 'darwin' || - options.platform === 'freebsd' || - options.platform === 'linux' || - options.platform === 'sunos' - ) { - options.platform = "UNIX"; - } - if (options.platform === 'win32') { - options.platform = "DOS"; - } - - var zipData = [], - localDirLength = 0, - centralDirLength = 0, - writer, i, - utfEncodedComment = utils.transformTo("string", this.utf8encode(options.comment || this.comment || "")); - - // first, generate all the zip parts. - for (var name in this.files) { - if (!this.files.hasOwnProperty(name)) { - continue; - } - var file = this.files[name]; - - var compressionName = file.options.compression || options.compression.toUpperCase(); - var compression = compressions[compressionName]; - if (!compression) { - throw new Error(compressionName + " is not a valid compression method !"); - } - var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; - - var compressedObject = generateCompressedObjectFrom.call(this, file, compression, compressionOptions); - - var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength, options.platform); - localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize; - centralDirLength += zipPart.dirRecord.length; - zipData.push(zipPart); - } - - var dirEnd = ""; - - // end of central dir signature - dirEnd = signature.CENTRAL_DIRECTORY_END + - // number of this disk - "\x00\x00" + - // number of the disk with the start of the central directory - "\x00\x00" + - // total number of entries in the central directory on this disk - decToHex(zipData.length, 2) + - // total number of entries in the central directory - decToHex(zipData.length, 2) + - // size of the central directory 4 bytes - decToHex(centralDirLength, 4) + - // offset of start of central directory with respect to the starting disk number - decToHex(localDirLength, 4) + - // .ZIP file comment length - decToHex(utfEncodedComment.length, 2) + - // .ZIP file comment - utfEncodedComment; - - - // we have all the parts (and the total length) - // time to create a writer ! - var typeName = options.type.toLowerCase(); - if(typeName==="uint8array"||typeName==="arraybuffer"||typeName==="blob"||typeName==="nodebuffer") { - writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length); - }else{ - writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length); - } - - for (i = 0; i < zipData.length; i++) { - writer.append(zipData[i].fileRecord); - writer.append(zipData[i].compressedObject.compressedContent); - } - for (i = 0; i < zipData.length; i++) { - writer.append(zipData[i].dirRecord); - } - - writer.append(dirEnd); - - var zip = writer.finalize(); - - - - switch(options.type.toLowerCase()) { - // case "zip is an Uint8Array" - case "uint8array" : - case "arraybuffer" : - case "nodebuffer" : - return utils.transformTo(options.type.toLowerCase(), zip); - case "blob" : - return utils.arrayBuffer2Blob(utils.transformTo("arraybuffer", zip), options.mimeType); - // case "zip is a string" - case "base64" : - return (options.base64) ? base64.encode(zip) : zip; - default : // case "string" : - return zip; - } - - }, - - /** - * @deprecated - * This method will be removed in a future version without replacement. - */ - crc32: function (input, crc) { - return crc32(input, crc); - }, - - /** - * @deprecated - * This method will be removed in a future version without replacement. - */ - utf8encode: function (string) { - return utils.transformTo("string", utf8.utf8encode(string)); - }, - - /** - * @deprecated - * This method will be removed in a future version without replacement. - */ - utf8decode: function (input) { - return utf8.utf8decode(input); - } -}; -module.exports = out; - -},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(_dereq_,module,exports){ -'use strict'; -exports.LOCAL_FILE_HEADER = "PK\x03\x04"; -exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; -exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; -exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; -exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; -exports.DATA_DESCRIPTOR = "PK\x07\x08"; - -},{}],15:[function(_dereq_,module,exports){ -'use strict'; -var DataReader = _dereq_('./dataReader'); -var utils = _dereq_('./utils'); - -function StringReader(data, optimizedBinaryString) { - this.data = data; - if (!optimizedBinaryString) { - this.data = utils.string2binary(this.data); - } - this.length = this.data.length; - this.index = 0; -} -StringReader.prototype = new DataReader(); -/** - * @see DataReader.byteAt - */ -StringReader.prototype.byteAt = function(i) { - return this.data.charCodeAt(i); -}; -/** - * @see DataReader.lastIndexOfSignature - */ -StringReader.prototype.lastIndexOfSignature = function(sig) { - return this.data.lastIndexOf(sig); -}; -/** - * @see DataReader.readData - */ -StringReader.prototype.readData = function(size) { - this.checkOffset(size); - // this will work because the constructor applied the "& 0xff" mask. - var result = this.data.slice(this.index, this.index + size); - this.index += size; - return result; -}; -module.exports = StringReader; - -},{"./dataReader":5,"./utils":21}],16:[function(_dereq_,module,exports){ -'use strict'; - -var utils = _dereq_('./utils'); - -/** - * An object to write any content to a string. - * @constructor - */ -var StringWriter = function() { - this.data = []; -}; -StringWriter.prototype = { - /** - * Append any content to the current string. - * @param {Object} input the content to add. - */ - append: function(input) { - input = utils.transformTo("string", input); - this.data.push(input); - }, - /** - * Finalize the construction an return the result. - * @return {string} the generated string. - */ - finalize: function() { - return this.data.join(""); - } -}; - -module.exports = StringWriter; - -},{"./utils":21}],17:[function(_dereq_,module,exports){ -(function (Buffer){ -'use strict'; -exports.base64 = true; -exports.array = true; -exports.string = true; -exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; -// contains true if JSZip can read/generate nodejs Buffer, false otherwise. -// Browserify will provide a Buffer implementation for browsers, which is -// an augmented Uint8Array (i.e., can be used as either Buffer or U8). -exports.nodebuffer = typeof Buffer !== "undefined"; -// contains true if JSZip can read/generate Uint8Array, false otherwise. -exports.uint8array = typeof Uint8Array !== "undefined"; - -if (typeof ArrayBuffer === "undefined") { - exports.blob = false; -} -else { - var buffer = new ArrayBuffer(0); - try { - exports.blob = new Blob([buffer], { - type: "application/zip" - }).size === 0; - } - catch (e) { - try { - var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; - var builder = new Builder(); - builder.append(buffer); - exports.blob = builder.getBlob('application/zip').size === 0; - } - catch (e) { - exports.blob = false; - } - } -} - -}).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined)) -},{}],18:[function(_dereq_,module,exports){ -'use strict'; -var DataReader = _dereq_('./dataReader'); - -function Uint8ArrayReader(data) { - if (data) { - this.data = data; - this.length = this.data.length; - this.index = 0; - } -} -Uint8ArrayReader.prototype = new DataReader(); -/** - * @see DataReader.byteAt - */ -Uint8ArrayReader.prototype.byteAt = function(i) { - return this.data[i]; -}; -/** - * @see DataReader.lastIndexOfSignature - */ -Uint8ArrayReader.prototype.lastIndexOfSignature = function(sig) { - var sig0 = sig.charCodeAt(0), - sig1 = sig.charCodeAt(1), - sig2 = sig.charCodeAt(2), - sig3 = sig.charCodeAt(3); - for (var i = this.length - 4; i >= 0; --i) { - if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { - return i; - } - } - - return -1; -}; -/** - * @see DataReader.readData - */ -Uint8ArrayReader.prototype.readData = function(size) { - this.checkOffset(size); - if(size === 0) { - // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. - return new Uint8Array(0); - } - var result = this.data.subarray(this.index, this.index + size); - this.index += size; - return result; -}; -module.exports = Uint8ArrayReader; - -},{"./dataReader":5}],19:[function(_dereq_,module,exports){ -'use strict'; - -var utils = _dereq_('./utils'); - -/** - * An object to write any content to an Uint8Array. - * @constructor - * @param {number} length The length of the array. - */ -var Uint8ArrayWriter = function(length) { - this.data = new Uint8Array(length); - this.index = 0; -}; -Uint8ArrayWriter.prototype = { - /** - * Append any content to the current array. - * @param {Object} input the content to add. - */ - append: function(input) { - if (input.length !== 0) { - // with an empty Uint8Array, Opera fails with a "Offset larger than array size" - input = utils.transformTo("uint8array", input); - this.data.set(input, this.index); - this.index += input.length; - } - }, - /** - * Finalize the construction an return the result. - * @return {Uint8Array} the generated array. - */ - finalize: function() { - return this.data; - } -}; - -module.exports = Uint8ArrayWriter; - -},{"./utils":21}],20:[function(_dereq_,module,exports){ -'use strict'; - -var utils = _dereq_('./utils'); -var support = _dereq_('./support'); -var nodeBuffer = _dereq_('./nodeBuffer'); - -/** - * The following functions come from pako, from pako/lib/utils/strings - * released under the MIT license, see pako https://github.com/nodeca/pako/ - */ - -// Table with utf8 lengths (calculated by first byte of sequence) -// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, -// because max possible codepoint is 0x10ffff -var _utf8len = new Array(256); -for (var i=0; i<256; i++) { - _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); -} -_utf8len[254]=_utf8len[254]=1; // Invalid sequence start - -// convert string to array (typed, when possible) -var string2buf = function (str) { - var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { - c2 = str.charCodeAt(m_pos+1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - if (support.uint8array) { - buf = new Uint8Array(buf_len); - } else { - buf = new Array(buf_len); - } - - // convert - for (i=0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { - c2 = str.charCodeAt(m_pos+1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | (c >>> 6); - buf[i++] = 0x80 | (c & 0x3f); - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | (c >>> 12); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } else { - /* four bytes */ - buf[i++] = 0xf0 | (c >>> 18); - buf[i++] = 0x80 | (c >>> 12 & 0x3f); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } - } - - return buf; -}; - -// Calculate max possible position in utf8 buffer, -// that will not break sequence. If that's not possible -// - (very small limits) return max size as is. -// -// buf[] - utf8 bytes array -// max - length limit (mandatory); -var utf8border = function(buf, max) { - var pos; - - max = max || buf.length; - if (max > buf.length) { max = buf.length; } - - // go back from last position, until start of sequence found - pos = max-1; - while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } - - // Fuckup - very small and broken sequence, - // return max, because we should return something anyway. - if (pos < 0) { return max; } - - // If we came to start of buffer - that means vuffer is too small, - // return max too. - if (pos === 0) { return max; } - - return (pos + _utf8len[buf[pos]] > max) ? pos : max; -}; - -// convert array to string -var buf2string = function (buf) { - var str, i, out, c, c_len; - var len = buf.length; - - // Reserve max possible length (2 words per char) - // NB: by unknown reasons, Array is significantly faster for - // String.fromCharCode.apply than Uint16Array. - var utf16buf = new Array(len*2); - - for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } - - // apply mask on first byte - c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; - // join the rest - while (c_len > 1 && i < len) { - c = (c << 6) | (buf[i++] & 0x3f); - c_len--; - } - - // terminated by end of string? - if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } - - if (c < 0x10000) { - utf16buf[out++] = c; - } else { - c -= 0x10000; - utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); - utf16buf[out++] = 0xdc00 | (c & 0x3ff); - } - } - - // shrinkBuf(utf16buf, out) - if (utf16buf.length !== out) { - if(utf16buf.subarray) { - utf16buf = utf16buf.subarray(0, out); - } else { - utf16buf.length = out; - } - } - - // return String.fromCharCode.apply(null, utf16buf); - return utils.applyFromCharCode(utf16buf); -}; - - -// That's all for the pako functions. - - -/** - * Transform a javascript string into an array (typed if possible) of bytes, - * UTF-8 encoded. - * @param {String} str the string to encode - * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. - */ -exports.utf8encode = function utf8encode(str) { - if (support.nodebuffer) { - return nodeBuffer(str, "utf-8"); - } - - return string2buf(str); -}; - - -/** - * Transform a bytes array (or a representation) representing an UTF-8 encoded - * string into a javascript string. - * @param {Array|Uint8Array|Buffer} buf the data de decode - * @return {String} the decoded string. - */ -exports.utf8decode = function utf8decode(buf) { - if (support.nodebuffer) { - return utils.transformTo("nodebuffer", buf).toString("utf-8"); - } - - buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); - - // return buf2string(buf); - // Chrome prefers to work with "small" chunks of data - // for the method buf2string. - // Firefox and Chrome has their own shortcut, IE doesn't seem to really care. - var result = [], k = 0, len = buf.length, chunk = 65536; - while (k < len) { - var nextBoundary = utf8border(buf, Math.min(k + chunk, len)); - if (support.uint8array) { - result.push(buf2string(buf.subarray(k, nextBoundary))); - } else { - result.push(buf2string(buf.slice(k, nextBoundary))); - } - k = nextBoundary; - } - return result.join(""); - -}; -// vim: set shiftwidth=4 softtabstop=4: - -},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(_dereq_,module,exports){ -'use strict'; -var support = _dereq_('./support'); -var compressions = _dereq_('./compressions'); -var nodeBuffer = _dereq_('./nodeBuffer'); -/** - * Convert a string to a "binary string" : a string containing only char codes between 0 and 255. - * @param {string} str the string to transform. - * @return {String} the binary string. - */ -exports.string2binary = function(str) { - var result = ""; - for (var i = 0; i < str.length; i++) { - result += String.fromCharCode(str.charCodeAt(i) & 0xff); - } - return result; -}; -exports.arrayBuffer2Blob = function(buffer, mimeType) { - exports.checkSupport("blob"); - mimeType = mimeType || 'application/zip'; - - try { - // Blob constructor - return new Blob([buffer], { - type: mimeType - }); - } - catch (e) { - - try { - // deprecated, browser only, old way - var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; - var builder = new Builder(); - builder.append(buffer); - return builder.getBlob(mimeType); - } - catch (e) { - - // well, fuck ?! - throw new Error("Bug : can't construct the Blob."); - } - } - - -}; -/** - * The identity function. - * @param {Object} input the input. - * @return {Object} the same input. - */ -function identity(input) { - return input; -} - -/** - * Fill in an array with a string. - * @param {String} str the string to use. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). - * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. - */ -function stringToArrayLike(str, array) { - for (var i = 0; i < str.length; ++i) { - array[i] = str.charCodeAt(i) & 0xFF; - } - return array; -} - -/** - * Transform an array-like object to a string. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. - * @return {String} the result. - */ -function arrayLikeToString(array) { - // Performances notes : - // -------------------- - // String.fromCharCode.apply(null, array) is the fastest, see - // see http://jsperf.com/converting-a-uint8array-to-a-string/2 - // but the stack is limited (and we can get huge arrays !). - // - // result += String.fromCharCode(array[i]); generate too many strings ! - // - // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 - var chunk = 65536; - var result = [], - len = array.length, - type = exports.getTypeOf(array), - k = 0, - canUseApply = true; - try { - switch(type) { - case "uint8array": - String.fromCharCode.apply(null, new Uint8Array(0)); - break; - case "nodebuffer": - String.fromCharCode.apply(null, nodeBuffer(0)); - break; - } - } catch(e) { - canUseApply = false; - } - - // no apply : slow and painful algorithm - // default browser on android 4.* - if (!canUseApply) { - var resultStr = ""; - for(var i = 0; i < array.length;i++) { - resultStr += String.fromCharCode(array[i]); - } - return resultStr; - } - while (k < len && chunk > 1) { - try { - if (type === "array" || type === "nodebuffer") { - result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); - } - else { - result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); - } - k += chunk; - } - catch (e) { - chunk = Math.floor(chunk / 2); - } - } - return result.join(""); -} - -exports.applyFromCharCode = arrayLikeToString; - - -/** - * Copy the data from an array-like to an other array-like. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. - * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. - */ -function arrayLikeToArrayLike(arrayFrom, arrayTo) { - for (var i = 0; i < arrayFrom.length; i++) { - arrayTo[i] = arrayFrom[i]; - } - return arrayTo; -} - -// a matrix containing functions to transform everything into everything. -var transform = {}; - -// string to ? -transform["string"] = { - "string": identity, - "array": function(input) { - return stringToArrayLike(input, new Array(input.length)); - }, - "arraybuffer": function(input) { - return transform["string"]["uint8array"](input).buffer; - }, - "uint8array": function(input) { - return stringToArrayLike(input, new Uint8Array(input.length)); - }, - "nodebuffer": function(input) { - return stringToArrayLike(input, nodeBuffer(input.length)); - } -}; - -// array to ? -transform["array"] = { - "string": arrayLikeToString, - "array": identity, - "arraybuffer": function(input) { - return (new Uint8Array(input)).buffer; - }, - "uint8array": function(input) { - return new Uint8Array(input); - }, - "nodebuffer": function(input) { - return nodeBuffer(input); - } -}; - -// arraybuffer to ? -transform["arraybuffer"] = { - "string": function(input) { - return arrayLikeToString(new Uint8Array(input)); - }, - "array": function(input) { - return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); - }, - "arraybuffer": identity, - "uint8array": function(input) { - return new Uint8Array(input); - }, - "nodebuffer": function(input) { - return nodeBuffer(new Uint8Array(input)); - } -}; - -// uint8array to ? -transform["uint8array"] = { - "string": arrayLikeToString, - "array": function(input) { - return arrayLikeToArrayLike(input, new Array(input.length)); - }, - "arraybuffer": function(input) { - return input.buffer; - }, - "uint8array": identity, - "nodebuffer": function(input) { - return nodeBuffer(input); - } -}; - -// nodebuffer to ? -transform["nodebuffer"] = { - "string": arrayLikeToString, - "array": function(input) { - return arrayLikeToArrayLike(input, new Array(input.length)); - }, - "arraybuffer": function(input) { - return transform["nodebuffer"]["uint8array"](input).buffer; - }, - "uint8array": function(input) { - return arrayLikeToArrayLike(input, new Uint8Array(input.length)); - }, - "nodebuffer": identity -}; - -/** - * Transform an input into any type. - * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. - * If no output type is specified, the unmodified input will be returned. - * @param {String} outputType the output type. - * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. - * @throws {Error} an Error if the browser doesn't support the requested output type. - */ -exports.transformTo = function(outputType, input) { - if (!input) { - // undefined, null, etc - // an empty string won't harm. - input = ""; - } - if (!outputType) { - return input; - } - exports.checkSupport(outputType); - var inputType = exports.getTypeOf(input); - var result = transform[inputType][outputType](input); - return result; -}; - -/** - * Return the type of the input. - * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. - * @param {Object} input the input to identify. - * @return {String} the (lowercase) type of the input. - */ -exports.getTypeOf = function(input) { - if (typeof input === "string") { - return "string"; - } - if (Object.prototype.toString.call(input) === "[object Array]") { - return "array"; - } - if (support.nodebuffer && nodeBuffer.test(input)) { - return "nodebuffer"; - } - if (support.uint8array && input instanceof Uint8Array) { - return "uint8array"; - } - if (support.arraybuffer && input instanceof ArrayBuffer) { - return "arraybuffer"; - } -}; - -/** - * Throw an exception if the type is not supported. - * @param {String} type the type to check. - * @throws {Error} an Error if the browser doesn't support the requested type. - */ -exports.checkSupport = function(type) { - var supported = support[type.toLowerCase()]; - if (!supported) { - throw new Error(type + " is not supported by this browser"); - } -}; -exports.MAX_VALUE_16BITS = 65535; -exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 - -/** - * Prettify a string read as binary. - * @param {string} str the string to prettify. - * @return {string} a pretty string. - */ -exports.pretty = function(str) { - var res = '', - code, i; - for (i = 0; i < (str || "").length; i++) { - code = str.charCodeAt(i); - res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); - } - return res; -}; - -/** - * Find a compression registered in JSZip. - * @param {string} compressionMethod the method magic to find. - * @return {Object|null} the JSZip compression object, null if none found. - */ -exports.findCompression = function(compressionMethod) { - for (var method in compressions) { - if (!compressions.hasOwnProperty(method)) { - continue; - } - if (compressions[method].magic === compressionMethod) { - return compressions[method]; - } - } - return null; -}; -/** -* Cross-window, cross-Node-context regular expression detection -* @param {Object} object Anything -* @return {Boolean} true if the object is a regular expression, -* false otherwise -*/ -exports.isRegExp = function (object) { - return Object.prototype.toString.call(object) === "[object RegExp]"; -}; - - -},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(_dereq_,module,exports){ -'use strict'; -var StringReader = _dereq_('./stringReader'); -var NodeBufferReader = _dereq_('./nodeBufferReader'); -var Uint8ArrayReader = _dereq_('./uint8ArrayReader'); -var utils = _dereq_('./utils'); -var sig = _dereq_('./signature'); -var ZipEntry = _dereq_('./zipEntry'); -var support = _dereq_('./support'); -var jszipProto = _dereq_('./object'); -// class ZipEntries {{{ -/** - * All the entries in the zip file. - * @constructor - * @param {String|ArrayBuffer|Uint8Array} data the binary stream to load. - * @param {Object} loadOptions Options for loading the stream. - */ -function ZipEntries(data, loadOptions) { - this.files = []; - this.loadOptions = loadOptions; - if (data) { - this.load(data); - } -} -ZipEntries.prototype = { - /** - * Check that the reader is on the speficied signature. - * @param {string} expectedSignature the expected signature. - * @throws {Error} if it is an other signature. - */ - checkSignature: function(expectedSignature) { - var signature = this.reader.readString(4); - if (signature !== expectedSignature) { - throw new Error("Corrupted zip or bug : unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); - } - }, - /** - * Read the end of the central directory. - */ - readBlockEndOfCentral: function() { - this.diskNumber = this.reader.readInt(2); - this.diskWithCentralDirStart = this.reader.readInt(2); - this.centralDirRecordsOnThisDisk = this.reader.readInt(2); - this.centralDirRecords = this.reader.readInt(2); - this.centralDirSize = this.reader.readInt(4); - this.centralDirOffset = this.reader.readInt(4); - - this.zipCommentLength = this.reader.readInt(2); - // warning : the encoding depends of the system locale - // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. - // On a windows machine, this field is encoded with the localized windows code page. - this.zipComment = this.reader.readString(this.zipCommentLength); - // To get consistent behavior with the generation part, we will assume that - // this is utf8 encoded. - this.zipComment = jszipProto.utf8decode(this.zipComment); - }, - /** - * Read the end of the Zip 64 central directory. - * Not merged with the method readEndOfCentral : - * The end of central can coexist with its Zip64 brother, - * I don't want to read the wrong number of bytes ! - */ - readBlockZip64EndOfCentral: function() { - this.zip64EndOfCentralSize = this.reader.readInt(8); - this.versionMadeBy = this.reader.readString(2); - this.versionNeeded = this.reader.readInt(2); - this.diskNumber = this.reader.readInt(4); - this.diskWithCentralDirStart = this.reader.readInt(4); - this.centralDirRecordsOnThisDisk = this.reader.readInt(8); - this.centralDirRecords = this.reader.readInt(8); - this.centralDirSize = this.reader.readInt(8); - this.centralDirOffset = this.reader.readInt(8); - - this.zip64ExtensibleData = {}; - var extraDataSize = this.zip64EndOfCentralSize - 44, - index = 0, - extraFieldId, - extraFieldLength, - extraFieldValue; - while (index < extraDataSize) { - extraFieldId = this.reader.readInt(2); - extraFieldLength = this.reader.readInt(4); - extraFieldValue = this.reader.readString(extraFieldLength); - this.zip64ExtensibleData[extraFieldId] = { - id: extraFieldId, - length: extraFieldLength, - value: extraFieldValue - }; - } - }, - /** - * Read the end of the Zip 64 central directory locator. - */ - readBlockZip64EndOfCentralLocator: function() { - this.diskWithZip64CentralDirStart = this.reader.readInt(4); - this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); - this.disksCount = this.reader.readInt(4); - if (this.disksCount > 1) { - throw new Error("Multi-volumes zip are not supported"); - } - }, - /** - * Read the local files, based on the offset read in the central part. - */ - readLocalFiles: function() { - var i, file; - for (i = 0; i < this.files.length; i++) { - file = this.files[i]; - this.reader.setIndex(file.localHeaderOffset); - this.checkSignature(sig.LOCAL_FILE_HEADER); - file.readLocalPart(this.reader); - file.handleUTF8(); - file.processAttributes(); - } - }, - /** - * Read the central directory. - */ - readCentralDir: function() { - var file; - - this.reader.setIndex(this.centralDirOffset); - while (this.reader.readString(4) === sig.CENTRAL_FILE_HEADER) { - file = new ZipEntry({ - zip64: this.zip64 - }, this.loadOptions); - file.readCentralPart(this.reader); - this.files.push(file); - } - }, - /** - * Read the end of central directory. - */ - readEndOfCentral: function() { - var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); - if (offset === -1) { - // Check if the content is a truncated zip or complete garbage. - // A "LOCAL_FILE_HEADER" is not required at the beginning (auto - // extractible zip for example) but it can give a good hint. - // If an ajax request was used without responseType, we will also - // get unreadable data. - var isGarbage = true; - try { - this.reader.setIndex(0); - this.checkSignature(sig.LOCAL_FILE_HEADER); - isGarbage = false; - } catch (e) {} - - if (isGarbage) { - throw new Error("Can't find end of central directory : is this a zip file ? " + - "If it is, see http://stuk.github.io/jszip/documentation/howto/read_zip.html"); - } else { - throw new Error("Corrupted zip : can't find end of central directory"); - } - } - this.reader.setIndex(offset); - this.checkSignature(sig.CENTRAL_DIRECTORY_END); - this.readBlockEndOfCentral(); - - - /* extract from the zip spec : - 4) If one of the fields in the end of central directory - record is too small to hold required data, the field - should be set to -1 (0xFFFF or 0xFFFFFFFF) and the - ZIP64 format record should be created. - 5) The end of central directory record and the - Zip64 end of central directory locator record must - reside on the same disk when splitting or spanning - an archive. - */ - if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { - this.zip64 = true; - - /* - Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from - the zip file can fit into a 32bits integer. This cannot be solved : Javascript represents - all numbers as 64-bit double precision IEEE 754 floating point numbers. - So, we have 53bits for integers and bitwise operations treat everything as 32bits. - see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators - and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 - */ - - // should look for a zip64 EOCD locator - offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); - if (offset === -1) { - throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator"); - } - this.reader.setIndex(offset); - this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); - this.readBlockZip64EndOfCentralLocator(); - - // now the zip64 EOCD record - this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); - this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); - this.readBlockZip64EndOfCentral(); - } - }, - prepareReader: function(data) { - var type = utils.getTypeOf(data); - if (type === "string" && !support.uint8array) { - this.reader = new StringReader(data, this.loadOptions.optimizedBinaryString); - } - else if (type === "nodebuffer") { - this.reader = new NodeBufferReader(data); - } - else { - this.reader = new Uint8ArrayReader(utils.transformTo("uint8array", data)); - } - }, - /** - * Read a zip file and create ZipEntries. - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. - */ - load: function(data) { - this.prepareReader(data); - this.readEndOfCentral(); - this.readCentralDir(); - this.readLocalFiles(); - } -}; -// }}} end of ZipEntries -module.exports = ZipEntries; - -},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(_dereq_,module,exports){ -'use strict'; -var StringReader = _dereq_('./stringReader'); -var utils = _dereq_('./utils'); -var CompressedObject = _dereq_('./compressedObject'); -var jszipProto = _dereq_('./object'); - -var MADE_BY_DOS = 0x00; -var MADE_BY_UNIX = 0x03; - -// class ZipEntry {{{ -/** - * An entry in the zip file. - * @constructor - * @param {Object} options Options of the current file. - * @param {Object} loadOptions Options for loading the stream. - */ -function ZipEntry(options, loadOptions) { - this.options = options; - this.loadOptions = loadOptions; -} -ZipEntry.prototype = { - /** - * say if the file is encrypted. - * @return {boolean} true if the file is encrypted, false otherwise. - */ - isEncrypted: function() { - // bit 1 is set - return (this.bitFlag & 0x0001) === 0x0001; - }, - /** - * say if the file has utf-8 filename/comment. - * @return {boolean} true if the filename/comment is in utf-8, false otherwise. - */ - useUTF8: function() { - // bit 11 is set - return (this.bitFlag & 0x0800) === 0x0800; - }, - /** - * Prepare the function used to generate the compressed content from this ZipFile. - * @param {DataReader} reader the reader to use. - * @param {number} from the offset from where we should read the data. - * @param {number} length the length of the data to read. - * @return {Function} the callback to get the compressed content (the type depends of the DataReader class). - */ - prepareCompressedContent: function(reader, from, length) { - return function() { - var previousIndex = reader.index; - reader.setIndex(from); - var compressedFileData = reader.readData(length); - reader.setIndex(previousIndex); - - return compressedFileData; - }; - }, - /** - * Prepare the function used to generate the uncompressed content from this ZipFile. - * @param {DataReader} reader the reader to use. - * @param {number} from the offset from where we should read the data. - * @param {number} length the length of the data to read. - * @param {JSZip.compression} compression the compression used on this file. - * @param {number} uncompressedSize the uncompressed size to expect. - * @return {Function} the callback to get the uncompressed content (the type depends of the DataReader class). - */ - prepareContent: function(reader, from, length, compression, uncompressedSize) { - return function() { - - var compressedFileData = utils.transformTo(compression.uncompressInputType, this.getCompressedContent()); - var uncompressedFileData = compression.uncompress(compressedFileData); - - if (uncompressedFileData.length !== uncompressedSize) { - throw new Error("Bug : uncompressed data size mismatch"); - } - - return uncompressedFileData; - }; - }, - /** - * Read the local part of a zip file and add the info in this object. - * @param {DataReader} reader the reader to use. - */ - readLocalPart: function(reader) { - var compression, localExtraFieldsLength; - - // we already know everything from the central dir ! - // If the central dir data are false, we are doomed. - // On the bright side, the local part is scary : zip64, data descriptors, both, etc. - // The less data we get here, the more reliable this should be. - // Let's skip the whole header and dash to the data ! - reader.skip(22); - // in some zip created on windows, the filename stored in the central dir contains \ instead of /. - // Strangely, the filename here is OK. - // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes - // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... - // Search "unzip mismatching "local" filename continuing with "central" filename version" on - // the internet. - // - // I think I see the logic here : the central directory is used to display - // content and the local directory is used to extract the files. Mixing / and \ - // may be used to display \ to windows users and use / when extracting the files. - // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 - this.fileNameLength = reader.readInt(2); - localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir - this.fileName = reader.readString(this.fileNameLength); - reader.skip(localExtraFieldsLength); - - if (this.compressedSize == -1 || this.uncompressedSize == -1) { - throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize == -1 || uncompressedSize == -1)"); - } - - compression = utils.findCompression(this.compressionMethod); - if (compression === null) { // no compression found - throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + this.fileName + ")"); - } - this.decompressed = new CompressedObject(); - this.decompressed.compressedSize = this.compressedSize; - this.decompressed.uncompressedSize = this.uncompressedSize; - this.decompressed.crc32 = this.crc32; - this.decompressed.compressionMethod = this.compressionMethod; - this.decompressed.getCompressedContent = this.prepareCompressedContent(reader, reader.index, this.compressedSize, compression); - this.decompressed.getContent = this.prepareContent(reader, reader.index, this.compressedSize, compression, this.uncompressedSize); - - // we need to compute the crc32... - if (this.loadOptions.checkCRC32) { - this.decompressed = utils.transformTo("string", this.decompressed.getContent()); - if (jszipProto.crc32(this.decompressed) !== this.crc32) { - throw new Error("Corrupted zip : CRC32 mismatch"); - } - } - }, - - /** - * Read the central part of a zip file and add the info in this object. - * @param {DataReader} reader the reader to use. - */ - readCentralPart: function(reader) { - this.versionMadeBy = reader.readInt(2); - this.versionNeeded = reader.readInt(2); - this.bitFlag = reader.readInt(2); - this.compressionMethod = reader.readString(2); - this.date = reader.readDate(); - this.crc32 = reader.readInt(4); - this.compressedSize = reader.readInt(4); - this.uncompressedSize = reader.readInt(4); - this.fileNameLength = reader.readInt(2); - this.extraFieldsLength = reader.readInt(2); - this.fileCommentLength = reader.readInt(2); - this.diskNumberStart = reader.readInt(2); - this.internalFileAttributes = reader.readInt(2); - this.externalFileAttributes = reader.readInt(4); - this.localHeaderOffset = reader.readInt(4); - - if (this.isEncrypted()) { - throw new Error("Encrypted zip are not supported"); - } - - this.fileName = reader.readString(this.fileNameLength); - this.readExtraFields(reader); - this.parseZIP64ExtraField(reader); - this.fileComment = reader.readString(this.fileCommentLength); - }, - - /** - * Parse the external file attributes and get the unix/dos permissions. - */ - processAttributes: function () { - this.unixPermissions = null; - this.dosPermissions = null; - var madeBy = this.versionMadeBy >> 8; - - // Check if we have the DOS directory flag set. - // We look for it in the DOS and UNIX permissions - // but some unknown platform could set it as a compatibility flag. - this.dir = this.externalFileAttributes & 0x0010 ? true : false; - - if(madeBy === MADE_BY_DOS) { - // first 6 bits (0 to 5) - this.dosPermissions = this.externalFileAttributes & 0x3F; - } - - if(madeBy === MADE_BY_UNIX) { - this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; - // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); - } - - // fail safe : if the name ends with a / it probably means a folder - if (!this.dir && this.fileName.slice(-1) === '/') { - this.dir = true; - } - }, - - /** - * Parse the ZIP64 extra field and merge the info in the current ZipEntry. - * @param {DataReader} reader the reader to use. - */ - parseZIP64ExtraField: function(reader) { - - if (!this.extraFields[0x0001]) { - return; - } - - // should be something, preparing the extra reader - var extraReader = new StringReader(this.extraFields[0x0001].value); - - // I really hope that these 64bits integer can fit in 32 bits integer, because js - // won't let us have more. - if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { - this.uncompressedSize = extraReader.readInt(8); - } - if (this.compressedSize === utils.MAX_VALUE_32BITS) { - this.compressedSize = extraReader.readInt(8); - } - if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { - this.localHeaderOffset = extraReader.readInt(8); - } - if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { - this.diskNumberStart = extraReader.readInt(4); - } - }, - /** - * Read the central part of a zip file and add the info in this object. - * @param {DataReader} reader the reader to use. - */ - readExtraFields: function(reader) { - var start = reader.index, - extraFieldId, - extraFieldLength, - extraFieldValue; - - this.extraFields = this.extraFields || {}; - - while (reader.index < start + this.extraFieldsLength) { - extraFieldId = reader.readInt(2); - extraFieldLength = reader.readInt(2); - extraFieldValue = reader.readString(extraFieldLength); - - this.extraFields[extraFieldId] = { - id: extraFieldId, - length: extraFieldLength, - value: extraFieldValue - }; - } - }, - /** - * Apply an UTF8 transformation if needed. - */ - handleUTF8: function() { - if (this.useUTF8()) { - this.fileName = jszipProto.utf8decode(this.fileName); - this.fileComment = jszipProto.utf8decode(this.fileComment); - } else { - var upath = this.findExtraFieldUnicodePath(); - if (upath !== null) { - this.fileName = upath; - } - var ucomment = this.findExtraFieldUnicodeComment(); - if (ucomment !== null) { - this.fileComment = ucomment; - } - } - }, - - /** - * Find the unicode path declared in the extra field, if any. - * @return {String} the unicode path, null otherwise. - */ - findExtraFieldUnicodePath: function() { - var upathField = this.extraFields[0x7075]; - if (upathField) { - var extraReader = new StringReader(upathField.value); - - // wrong version - if (extraReader.readInt(1) !== 1) { - return null; - } - - // the crc of the filename changed, this field is out of date. - if (jszipProto.crc32(this.fileName) !== extraReader.readInt(4)) { - return null; - } - - return jszipProto.utf8decode(extraReader.readString(upathField.length - 5)); - } - return null; - }, - - /** - * Find the unicode comment declared in the extra field, if any. - * @return {String} the unicode comment, null otherwise. - */ - findExtraFieldUnicodeComment: function() { - var ucommentField = this.extraFields[0x6375]; - if (ucommentField) { - var extraReader = new StringReader(ucommentField.value); - - // wrong version - if (extraReader.readInt(1) !== 1) { - return null; - } - - // the crc of the comment changed, this field is out of date. - if (jszipProto.crc32(this.fileComment) !== extraReader.readInt(4)) { - return null; - } - - return jszipProto.utf8decode(extraReader.readString(ucommentField.length - 5)); - } - return null; - } -}; -module.exports = ZipEntry; - -},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(_dereq_,module,exports){ -// Top level file is just a mixin of submodules & constants -'use strict'; - -var assign = _dereq_('./lib/utils/common').assign; - -var deflate = _dereq_('./lib/deflate'); -var inflate = _dereq_('./lib/inflate'); -var constants = _dereq_('./lib/zlib/constants'); - -var pako = {}; - -assign(pako, deflate, inflate, constants); - -module.exports = pako; -},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(_dereq_,module,exports){ -'use strict'; - - -var zlib_deflate = _dereq_('./zlib/deflate.js'); -var utils = _dereq_('./utils/common'); -var strings = _dereq_('./utils/strings'); -var msg = _dereq_('./zlib/messages'); -var zstream = _dereq_('./zlib/zstream'); - - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - -var Z_NO_FLUSH = 0; -var Z_FINISH = 4; - -var Z_OK = 0; -var Z_STREAM_END = 1; - -var Z_DEFAULT_COMPRESSION = -1; - -var Z_DEFAULT_STRATEGY = 0; - -var Z_DEFLATED = 8; - -/* ===========================================================================*/ - - -/** - * class Deflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[deflate]], - * [[deflateRaw]] and [[gzip]]. - **/ - -/* internal - * Deflate.chunks -> Array - * - * Chunks of output data, if [[Deflate#onData]] not overriden. - **/ - -/** - * Deflate.result -> Uint8Array|Array - * - * Compressed result, generated by default [[Deflate#onData]] - * and [[Deflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Deflate#push]] with `Z_FINISH` / `true` param). - **/ - -/** - * Deflate.err -> Number - * - * Error code after deflate finished. 0 (Z_OK) on success. - * You will not need it in real life, because deflate errors - * are possible only on wrong options or bad `onData` / `onEnd` - * custom handlers. - **/ - -/** - * Deflate.msg -> String - * - * Error message, if [[Deflate.err]] != 0 - **/ - - -/** - * new Deflate(options) - * - options (Object): zlib deflate options. - * - * Creates new deflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `level` - * - `windowBits` - * - `memLevel` - * - `strategy` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw deflate - * - `gzip` (Boolean) - create gzip wrapper - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - `header` (Object) - custom header for gzip - * - `text` (Boolean) - true if compressed data believed to be text - * - `time` (Number) - modification time, unix timestamp - * - `os` (Number) - operation system code - * - `extra` (Array) - array of bytes with extra data (max 65536) - * - `name` (String) - file name (binary string) - * - `comment` (String) - comment (binary string) - * - `hcrc` (Boolean) - true if header crc should be added - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var deflate = new pako.Deflate({ level: 3}); - * - * deflate.push(chunk1, false); - * deflate.push(chunk2, true); // true -> last chunk - * - * if (deflate.err) { throw new Error(deflate.err); } - * - * console.log(deflate.result); - * ``` - **/ -var Deflate = function(options) { - - this.options = utils.assign({ - level: Z_DEFAULT_COMPRESSION, - method: Z_DEFLATED, - chunkSize: 16384, - windowBits: 15, - memLevel: 8, - strategy: Z_DEFAULT_STRATEGY, - to: '' - }, options || {}); - - var opt = this.options; - - if (opt.raw && (opt.windowBits > 0)) { - opt.windowBits = -opt.windowBits; - } - - else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { - opt.windowBits += 16; - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new zstream(); - this.strm.avail_out = 0; - - var status = zlib_deflate.deflateInit2( - this.strm, - opt.level, - opt.method, - opt.windowBits, - opt.memLevel, - opt.strategy - ); - - if (status !== Z_OK) { - throw new Error(msg[status]); - } - - if (opt.header) { - zlib_deflate.deflateSetHeader(this.strm, opt.header); - } -}; - -/** - * Deflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|String): input data. Strings will be converted to - * utf8 byte sequence. - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH. - * - * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with - * new compressed chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That flush internal pending buffers and call - * [[Deflate#onEnd]]. - * - * On fail call [[Deflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * array format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Deflate.prototype.push = function(data, mode) { - var strm = this.strm; - var chunkSize = this.options.chunkSize; - var status, _mode; - - if (this.ended) { return false; } - - _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // If we need to compress text, change encoding to utf8. - strm.input = strings.string2buf(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - status = zlib_deflate.deflate(strm, _mode); /* no bad return value */ - - if (status !== Z_STREAM_END && status !== Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - if (strm.avail_out === 0 || (strm.avail_in === 0 && _mode === Z_FINISH)) { - if (this.options.to === 'string') { - this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out))); - } else { - this.onData(utils.shrinkBuf(strm.output, strm.next_out)); - } - } - } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - - // Finalize on the last chunk. - if (_mode === Z_FINISH) { - status = zlib_deflate.deflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === Z_OK; - } - - return true; -}; - - -/** - * Deflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): ouput data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Deflate.prototype.onData = function(chunk) { - this.chunks.push(chunk); -}; - - -/** - * Deflate#onEnd(status) -> Void - * - status (Number): deflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell deflate that input stream complete - * or error happenned. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Deflate.prototype.onEnd = function(status) { - // On success - join - if (status === Z_OK) { - if (this.options.to === 'string') { - this.result = this.chunks.join(''); - } else { - this.result = utils.flattenChunks(this.chunks); - } - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; - - -/** - * deflate(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * Compress `data` with deflate alrorythm and `options`. - * - * Supported options are: - * - * - level - * - windowBits - * - memLevel - * - strategy - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - `to` (String) - if equal to 'string', then result will be "binary string" - * (each char code [0..255]) - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , data = Uint8Array([1,2,3,4,5,6,7,8,9]); - * - * console.log(pako.deflate(data)); - * ``` - **/ -function deflate(input, options) { - var deflator = new Deflate(options); - - deflator.push(input, true); - - // That will never happens, if you don't cheat with options :) - if (deflator.err) { throw deflator.msg; } - - return deflator.result; -} - - -/** - * deflateRaw(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function deflateRaw(input, options) { - options = options || {}; - options.raw = true; - return deflate(input, options); -} - - -/** - * gzip(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to compress. - * - options (Object): zlib deflate options. - * - * The same as [[deflate]], but create gzip wrapper instead of - * deflate one. - **/ -function gzip(input, options) { - options = options || {}; - options.gzip = true; - return deflate(input, options); -} - - -exports.Deflate = Deflate; -exports.deflate = deflate; -exports.deflateRaw = deflateRaw; -exports.gzip = gzip; -},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(_dereq_,module,exports){ -'use strict'; - - -var zlib_inflate = _dereq_('./zlib/inflate.js'); -var utils = _dereq_('./utils/common'); -var strings = _dereq_('./utils/strings'); -var c = _dereq_('./zlib/constants'); -var msg = _dereq_('./zlib/messages'); -var zstream = _dereq_('./zlib/zstream'); -var gzheader = _dereq_('./zlib/gzheader'); - - -/** - * class Inflate - * - * Generic JS-style wrapper for zlib calls. If you don't need - * streaming behaviour - use more simple functions: [[inflate]] - * and [[inflateRaw]]. - **/ - -/* internal - * inflate.chunks -> Array - * - * Chunks of output data, if [[Inflate#onData]] not overriden. - **/ - -/** - * Inflate.result -> Uint8Array|Array|String - * - * Uncompressed result, generated by default [[Inflate#onData]] - * and [[Inflate#onEnd]] handlers. Filled after you push last chunk - * (call [[Inflate#push]] with `Z_FINISH` / `true` param). - **/ - -/** - * Inflate.err -> Number - * - * Error code after inflate finished. 0 (Z_OK) on success. - * Should be checked if broken data possible. - **/ - -/** - * Inflate.msg -> String - * - * Error message, if [[Inflate.err]] != 0 - **/ - - -/** - * new Inflate(options) - * - options (Object): zlib inflate options. - * - * Creates new inflator instance with specified params. Throws exception - * on bad params. Supported options: - * - * - `windowBits` - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information on these. - * - * Additional options, for internal needs: - * - * - `chunkSize` - size of generated data chunks (16K by default) - * - `raw` (Boolean) - do raw inflate - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * By default, when no options set, autodetect deflate/gzip data format via - * wrapper header. - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) - * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); - * - * var inflate = new pako.Inflate({ level: 3}); - * - * inflate.push(chunk1, false); - * inflate.push(chunk2, true); // true -> last chunk - * - * if (inflate.err) { throw new Error(inflate.err); } - * - * console.log(inflate.result); - * ``` - **/ -var Inflate = function(options) { - - this.options = utils.assign({ - chunkSize: 16384, - windowBits: 0, - to: '' - }, options || {}); - - var opt = this.options; - - // Force window size for `raw` data, if not set directly, - // because we have no header for autodetect. - if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { - opt.windowBits = -opt.windowBits; - if (opt.windowBits === 0) { opt.windowBits = -15; } - } - - // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate - if ((opt.windowBits >= 0) && (opt.windowBits < 16) && - !(options && options.windowBits)) { - opt.windowBits += 32; - } - - // Gzip header has no info about windows size, we can do autodetect only - // for deflate. So, if window size not set, force it to max when gzip possible - if ((opt.windowBits > 15) && (opt.windowBits < 48)) { - // bit 3 (16) -> gzipped data - // bit 4 (32) -> autodetect gzip/deflate - if ((opt.windowBits & 15) === 0) { - opt.windowBits |= 15; - } - } - - this.err = 0; // error code, if happens (0 = Z_OK) - this.msg = ''; // error message - this.ended = false; // used to avoid multiple onEnd() calls - this.chunks = []; // chunks of compressed data - - this.strm = new zstream(); - this.strm.avail_out = 0; - - var status = zlib_inflate.inflateInit2( - this.strm, - opt.windowBits - ); - - if (status !== c.Z_OK) { - throw new Error(msg[status]); - } - - this.header = new gzheader(); - - zlib_inflate.inflateGetHeader(this.strm, this.header); -}; - -/** - * Inflate#push(data[, mode]) -> Boolean - * - data (Uint8Array|Array|String): input data - * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. - * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH. - * - * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with - * new output chunks. Returns `true` on success. The last data block must have - * mode Z_FINISH (or `true`). That flush internal pending buffers and call - * [[Inflate#onEnd]]. - * - * On fail call [[Inflate#onEnd]] with error code and return false. - * - * We strongly recommend to use `Uint8Array` on input for best speed (output - * format is detected automatically). Also, don't skip last param and always - * use the same type in your code (boolean or number). That will improve JS speed. - * - * For regular `Array`-s make sure all elements are [0..255]. - * - * ##### Example - * - * ```javascript - * push(chunk, false); // push one of data chunks - * ... - * push(chunk, true); // push last chunk - * ``` - **/ -Inflate.prototype.push = function(data, mode) { - var strm = this.strm; - var chunkSize = this.options.chunkSize; - var status, _mode; - var next_out_utf8, tail, utf8str; - - if (this.ended) { return false; } - _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); - - // Convert data if needed - if (typeof data === 'string') { - // Only binary strings can be decompressed on practice - strm.input = strings.binstring2buf(data); - } else { - strm.input = data; - } - - strm.next_in = 0; - strm.avail_in = strm.input.length; - - do { - if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); - strm.next_out = 0; - strm.avail_out = chunkSize; - } - - status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */ - - if (status !== c.Z_STREAM_END && status !== c.Z_OK) { - this.onEnd(status); - this.ended = true; - return false; - } - - if (strm.next_out) { - if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && _mode === c.Z_FINISH)) { - - if (this.options.to === 'string') { - - next_out_utf8 = strings.utf8border(strm.output, strm.next_out); - - tail = strm.next_out - next_out_utf8; - utf8str = strings.buf2string(strm.output, next_out_utf8); - - // move tail - strm.next_out = tail; - strm.avail_out = chunkSize - tail; - if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } - - this.onData(utf8str); - - } else { - this.onData(utils.shrinkBuf(strm.output, strm.next_out)); - } - } - } - } while ((strm.avail_in > 0) && status !== c.Z_STREAM_END); - - if (status === c.Z_STREAM_END) { - _mode = c.Z_FINISH; - } - // Finalize on the last chunk. - if (_mode === c.Z_FINISH) { - status = zlib_inflate.inflateEnd(this.strm); - this.onEnd(status); - this.ended = true; - return status === c.Z_OK; - } - - return true; -}; - - -/** - * Inflate#onData(chunk) -> Void - * - chunk (Uint8Array|Array|String): ouput data. Type of array depends - * on js engine support. When string output requested, each chunk - * will be string. - * - * By default, stores data blocks in `chunks[]` property and glue - * those in `onEnd`. Override this handler, if you need another behaviour. - **/ -Inflate.prototype.onData = function(chunk) { - this.chunks.push(chunk); -}; - - -/** - * Inflate#onEnd(status) -> Void - * - status (Number): inflate status. 0 (Z_OK) on success, - * other if not. - * - * Called once after you tell inflate that input stream complete - * or error happenned. By default - join collected chunks, - * free memory and fill `results` / `err` properties. - **/ -Inflate.prototype.onEnd = function(status) { - // On success - join - if (status === c.Z_OK) { - if (this.options.to === 'string') { - // Glue & convert here, until we teach pako to send - // utf8 alligned strings to onData - this.result = this.chunks.join(''); - } else { - this.result = utils.flattenChunks(this.chunks); - } - } - this.chunks = []; - this.err = status; - this.msg = this.strm.msg; -}; - - -/** - * inflate(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * Decompress `data` with inflate/ungzip and `options`. Autodetect - * format via wrapper header by default. That's why we don't provide - * separate `ungzip` method. - * - * Supported options are: - * - * - windowBits - * - * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) - * for more information. - * - * Sugar (options): - * - * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify - * negative windowBits implicitly. - * - `to` (String) - if equal to 'string', then result will be converted - * from utf8 to utf16 (javascript) string. When string output requested, - * chunk length can differ from `chunkSize`, depending on content. - * - * - * ##### Example: - * - * ```javascript - * var pako = require('pako') - * , input = pako.deflate([1,2,3,4,5,6,7,8,9]) - * , output; - * - * try { - * output = pako.inflate(input); - * } catch (err) - * console.log(err); - * } - * ``` - **/ -function inflate(input, options) { - var inflator = new Inflate(options); - - inflator.push(input, true); - - // That will never happens, if you don't cheat with options :) - if (inflator.err) { throw inflator.msg; } - - return inflator.result; -} - - -/** - * inflateRaw(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * The same as [[inflate]], but creates raw data, without wrapper - * (header and adler32 crc). - **/ -function inflateRaw(input, options) { - options = options || {}; - options.raw = true; - return inflate(input, options); -} - - -/** - * ungzip(data[, options]) -> Uint8Array|Array|String - * - data (Uint8Array|Array|String): input data to decompress. - * - options (Object): zlib inflate options. - * - * Just shortcut to [[inflate]], because it autodetects format - * by header.content. Done for convenience. - **/ - - -exports.Inflate = Inflate; -exports.inflate = inflate; -exports.inflateRaw = inflateRaw; -exports.ungzip = inflate; - -},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(_dereq_,module,exports){ -'use strict'; - - -var TYPED_OK = (typeof Uint8Array !== 'undefined') && - (typeof Uint16Array !== 'undefined') && - (typeof Int32Array !== 'undefined'); - - -exports.assign = function (obj /*from1, from2, from3, ...*/) { - var sources = Array.prototype.slice.call(arguments, 1); - while (sources.length) { - var source = sources.shift(); - if (!source) { continue; } - - if (typeof(source) !== 'object') { - throw new TypeError(source + 'must be non-object'); - } - - for (var p in source) { - if (source.hasOwnProperty(p)) { - obj[p] = source[p]; - } - } - } - - return obj; -}; - - -// reduce buffer size, avoiding mem copy -exports.shrinkBuf = function (buf, size) { - if (buf.length === size) { return buf; } - if (buf.subarray) { return buf.subarray(0, size); } - buf.length = size; - return buf; -}; - - -var fnTyped = { - arraySet: function (dest, src, src_offs, len, dest_offs) { - if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs+len), dest_offs); - return; - } - // Fallback to ordinary array - for(var i=0; i= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); -} -_utf8len[254]=_utf8len[254]=1; // Invalid sequence start - - -// convert string to array (typed, when possible) -exports.string2buf = function (str) { - var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { - c2 = str.charCodeAt(m_pos+1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - buf = new utils.Buf8(buf_len); - - // convert - for (i=0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { - c2 = str.charCodeAt(m_pos+1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | (c >>> 6); - buf[i++] = 0x80 | (c & 0x3f); - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | (c >>> 12); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } else { - /* four bytes */ - buf[i++] = 0xf0 | (c >>> 18); - buf[i++] = 0x80 | (c >>> 12 & 0x3f); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } - } - - return buf; -}; - -// Helper (used in 2 places) -function buf2binstring(buf, len) { - // use fallback for big arrays to avoid stack overflow - if (len < 65537) { - if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) { - return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); - } - } - - var result = ''; - for(var i=0; i < len; i++) { - result += String.fromCharCode(buf[i]); - } - return result; -} - - -// Convert byte array to binary string -exports.buf2binstring = function(buf) { - return buf2binstring(buf, buf.length); -}; - - -// Convert binary string (typed, when possible) -exports.binstring2buf = function(str) { - var buf = new utils.Buf8(str.length); - for(var i=0, len=buf.length; i < len; i++) { - buf[i] = str.charCodeAt(i); - } - return buf; -}; - - -// convert array to string -exports.buf2string = function (buf, max) { - var i, out, c, c_len; - var len = max || buf.length; - - // Reserve max possible length (2 words per char) - // NB: by unknown reasons, Array is significantly faster for - // String.fromCharCode.apply than Uint16Array. - var utf16buf = new Array(len*2); - - for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } - - // apply mask on first byte - c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; - // join the rest - while (c_len > 1 && i < len) { - c = (c << 6) | (buf[i++] & 0x3f); - c_len--; - } - - // terminated by end of string? - if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } - - if (c < 0x10000) { - utf16buf[out++] = c; - } else { - c -= 0x10000; - utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); - utf16buf[out++] = 0xdc00 | (c & 0x3ff); - } - } - - return buf2binstring(utf16buf, out); -}; - - -// Calculate max possible position in utf8 buffer, -// that will not break sequence. If that's not possible -// - (very small limits) return max size as is. -// -// buf[] - utf8 bytes array -// max - length limit (mandatory); -exports.utf8border = function(buf, max) { - var pos; - - max = max || buf.length; - if (max > buf.length) { max = buf.length; } - - // go back from last position, until start of sequence found - pos = max-1; - while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } - - // Fuckup - very small and broken sequence, - // return max, because we should return something anyway. - if (pos < 0) { return max; } - - // If we came to start of buffer - that means vuffer is too small, - // return max too. - if (pos === 0) { return max; } - - return (pos + _utf8len[buf[pos]] > max) ? pos : max; -}; - -},{"./common":27}],29:[function(_dereq_,module,exports){ -'use strict'; - -// Note: adler32 takes 12% for level 0 and 2% for level 6. -// It doesn't worth to make additional optimizationa as in original. -// Small size is preferable. - -function adler32(adler, buf, len, pos) { - var s1 = (adler & 0xffff) |0 - , s2 = ((adler >>> 16) & 0xffff) |0 - , n = 0; - - while (len !== 0) { - // Set limit ~ twice less than 5552, to keep - // s2 in 31-bits, because we force signed ints. - // in other case %= will fail. - n = len > 2000 ? 2000 : len; - len -= n; - - do { - s1 = (s1 + buf[pos++]) |0; - s2 = (s2 + s1) |0; - } while (--n); - - s1 %= 65521; - s2 %= 65521; - } - - return (s1 | (s2 << 16)) |0; -} - - -module.exports = adler32; -},{}],30:[function(_dereq_,module,exports){ -module.exports = { - - /* Allowed flush values; see deflate() and inflate() below for details */ - Z_NO_FLUSH: 0, - Z_PARTIAL_FLUSH: 1, - Z_SYNC_FLUSH: 2, - Z_FULL_FLUSH: 3, - Z_FINISH: 4, - Z_BLOCK: 5, - Z_TREES: 6, - - /* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - Z_OK: 0, - Z_STREAM_END: 1, - Z_NEED_DICT: 2, - Z_ERRNO: -1, - Z_STREAM_ERROR: -2, - Z_DATA_ERROR: -3, - //Z_MEM_ERROR: -4, - Z_BUF_ERROR: -5, - //Z_VERSION_ERROR: -6, - - /* compression levels */ - Z_NO_COMPRESSION: 0, - Z_BEST_SPEED: 1, - Z_BEST_COMPRESSION: 9, - Z_DEFAULT_COMPRESSION: -1, - - - Z_FILTERED: 1, - Z_HUFFMAN_ONLY: 2, - Z_RLE: 3, - Z_FIXED: 4, - Z_DEFAULT_STRATEGY: 0, - - /* Possible values of the data_type field (though see inflate()) */ - Z_BINARY: 0, - Z_TEXT: 1, - //Z_ASCII: 1, // = Z_TEXT (deprecated) - Z_UNKNOWN: 2, - - /* The deflate compression method */ - Z_DEFLATED: 8 - //Z_NULL: null // Use -1 or null inline, depending on var type -}; -},{}],31:[function(_dereq_,module,exports){ -'use strict'; - -// Note: we can't get significant speed boost here. -// So write code to minimize size - no pregenerated tables -// and array tools dependencies. - - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - var c, table = []; - - for(var n =0; n < 256; n++){ - c = n; - for(var k =0; k < 8; k++){ - c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -var crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - var t = crcTable - , end = pos + len; - - crc = crc ^ (-1); - - for (var i = pos; i < end; i++ ) { - crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return (crc ^ (-1)); // >>> 0; -} - - -module.exports = crc32; -},{}],32:[function(_dereq_,module,exports){ -'use strict'; - -var utils = _dereq_('../utils/common'); -var trees = _dereq_('./trees'); -var adler32 = _dereq_('./adler32'); -var crc32 = _dereq_('./crc32'); -var msg = _dereq_('./messages'); - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -var Z_NO_FLUSH = 0; -var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -//var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -//var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -//var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - - -/* compression levels */ -//var Z_NO_COMPRESSION = 0; -//var Z_BEST_SPEED = 1; -//var Z_BEST_COMPRESSION = 9; -var Z_DEFAULT_COMPRESSION = -1; - - -var Z_FILTERED = 1; -var Z_HUFFMAN_ONLY = 2; -var Z_RLE = 3; -var Z_FIXED = 4; -var Z_DEFAULT_STRATEGY = 0; - -/* Possible values of the data_type field (though see inflate()) */ -//var Z_BINARY = 0; -//var Z_TEXT = 1; -//var Z_ASCII = 1; // = Z_TEXT -var Z_UNKNOWN = 2; - - -/* The deflate compression method */ -var Z_DEFLATED = 8; - -/*============================================================================*/ - - -var MAX_MEM_LEVEL = 9; -/* Maximum value for memLevel in deflateInit2 */ -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_MEM_LEVEL = 8; - - -var LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ -var LITERALS = 256; -/* number of literal bytes 0..255 */ -var L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ -var D_CODES = 30; -/* number of distance codes */ -var BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ -var HEAP_SIZE = 2*L_CODES + 1; -/* maximum heap size */ -var MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -var MIN_MATCH = 3; -var MAX_MATCH = 258; -var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); - -var PRESET_DICT = 0x20; - -var INIT_STATE = 42; -var EXTRA_STATE = 69; -var NAME_STATE = 73; -var COMMENT_STATE = 91; -var HCRC_STATE = 103; -var BUSY_STATE = 113; -var FINISH_STATE = 666; - -var BS_NEED_MORE = 1; /* block not completed, need more input or more output */ -var BS_BLOCK_DONE = 2; /* block flush performed */ -var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ -var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ - -var OS_CODE = 0x03; // Unix :) . Don't detect, use this default. - -function err(strm, errorCode) { - strm.msg = msg[errorCode]; - return errorCode; -} - -function rank(f) { - return ((f) << 1) - ((f) > 4 ? 9 : 0); -} - -function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } - - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->output buffer and copying into it. - * (See also read_buf()). - */ -function flush_pending(strm) { - var s = strm.state; - - //_tr_flush_bits(s); - var len = s.pending; - if (len > strm.avail_out) { - len = strm.avail_out; - } - if (len === 0) { return; } - - utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); - strm.next_out += len; - s.pending_out += len; - strm.total_out += len; - strm.avail_out -= len; - s.pending -= len; - if (s.pending === 0) { - s.pending_out = 0; - } -} - - -function flush_block_only (s, last) { - trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); - s.block_start = s.strstart; - flush_pending(s.strm); -} - - -function put_byte(s, b) { - s.pending_buf[s.pending++] = b; -} - - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -function putShortMSB(s, b) { -// put_byte(s, (Byte)(b >> 8)); -// put_byte(s, (Byte)(b & 0xff)); - s.pending_buf[s.pending++] = (b >>> 8) & 0xff; - s.pending_buf[s.pending++] = b & 0xff; -} - - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->input buffer and copying from it. - * (See also flush_pending()). - */ -function read_buf(strm, buf, start, size) { - var len = strm.avail_in; - - if (len > size) { len = size; } - if (len === 0) { return 0; } - - strm.avail_in -= len; - - utils.arraySet(buf, strm.input, strm.next_in, len, start); - if (strm.state.wrap === 1) { - strm.adler = adler32(strm.adler, buf, len, start); - } - - else if (strm.state.wrap === 2) { - strm.adler = crc32(strm.adler, buf, len, start); - } - - strm.next_in += len; - strm.total_in += len; - - return len; -} - - -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -function longest_match(s, cur_match) { - var chain_length = s.max_chain_length; /* max hash chain length */ - var scan = s.strstart; /* current string */ - var match; /* matched string */ - var len; /* length of current match */ - var best_len = s.prev_length; /* best match length so far */ - var nice_match = s.nice_match; /* stop if match long enough */ - var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? - s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - - var _win = s.window; // shortcut - - var wmask = s.w_mask; - var prev = s.prev; - - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - var strend = s.strstart + MAX_MATCH; - var scan_end1 = _win[scan + best_len - 1]; - var scan_end = _win[scan + best_len]; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s.prev_length >= s.good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if (nice_match > s.lookahead) { nice_match = s.lookahead; } - - // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - // Assert(cur_match < s->strstart, "no future"); - match = cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ - - if (_win[match + best_len] !== scan_end || - _win[match + best_len - 1] !== scan_end1 || - _win[match] !== _win[scan] || - _win[++match] !== _win[scan + 1]) { - continue; - } - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2; - match++; - // Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - /*jshint noempty:false*/ - } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && - scan < strend); - - // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (strend - scan); - scan = strend - MAX_MATCH; - - if (len > best_len) { - s.match_start = cur_match; - best_len = len; - if (len >= nice_match) { - break; - } - scan_end1 = _win[scan + best_len - 1]; - scan_end = _win[scan + best_len]; - } - } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); - - if (best_len <= s.lookahead) { - return best_len; - } - return s.lookahead; -} - - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -function fill_window(s) { - var _w_size = s.w_size; - var p, n, m, more, str; - - //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); - - do { - more = s.window_size - s.lookahead - s.strstart; - - // JS ints have 32 bit, block below not needed - /* Deal with !@#$% 64K limit: */ - //if (sizeof(int) <= 2) { - // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - // more = wsize; - // - // } else if (more == (unsigned)(-1)) { - // /* Very unlikely, but possible on 16 bit machine if - // * strstart == 0 && lookahead == 1 (input done a byte at time) - // */ - // more--; - // } - //} - - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - - utils.arraySet(s.window, s.window, _w_size, _w_size, 0); - s.match_start -= _w_size; - s.strstart -= _w_size; - /* we now have strstart >= MAX_DIST */ - s.block_start -= _w_size; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - - n = s.hash_size; - p = n; - do { - m = s.head[--p]; - s.head[p] = (m >= _w_size ? m - _w_size : 0); - } while (--n); - - n = _w_size; - p = n; - do { - m = s.prev[--p]; - s.prev[p] = (m >= _w_size ? m - _w_size : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); - - more += _w_size; - } - if (s.strm.avail_in === 0) { - break; - } - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - //Assert(more >= 2, "more < 2"); - n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); - s.lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s.lookahead + s.insert >= MIN_MATCH) { - str = s.strstart - s.insert; - s.ins_h = s.window[str]; - - /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; -//#if MIN_MATCH != 3 -// Call update_hash() MIN_MATCH-3 more times -//#endif - while (s.insert) { - /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH-1]) & s.hash_mask; - - s.prev[str & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = str; - str++; - s.insert--; - if (s.lookahead + s.insert < MIN_MATCH) { - break; - } - } - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - - /* If the WIN_INIT bytes after the end of the current data have never been - * written, then zero those bytes in order to avoid memory check reports of - * the use of uninitialized (or uninitialised as Julian writes) bytes by - * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. - */ -// if (s.high_water < s.window_size) { -// var curr = s.strstart + s.lookahead; -// var init = 0; -// -// if (s.high_water < curr) { -// /* Previous high water mark below current data -- zero WIN_INIT -// * bytes or up to end of window, whichever is less. -// */ -// init = s.window_size - curr; -// if (init > WIN_INIT) -// init = WIN_INIT; -// zmemzero(s->window + curr, (unsigned)init); -// s->high_water = curr + init; -// } -// else if (s->high_water < (ulg)curr + WIN_INIT) { -// /* High water mark at or above current data, but below current data -// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up -// * to end of window, whichever is less. -// */ -// init = (ulg)curr + WIN_INIT - s->high_water; -// if (init > s->window_size - s->high_water) -// init = s->window_size - s->high_water; -// zmemzero(s->window + s->high_water, (unsigned)init); -// s->high_water += init; -// } -// } -// -// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, -// "not enough room for search"); -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -function deflate_stored(s, flush) { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - var max_block_size = 0xffff; - - if (max_block_size > s.pending_buf_size - 5) { - max_block_size = s.pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s.lookahead <= 1) { - - //Assert(s->strstart < s->w_size+MAX_DIST(s) || - // s->block_start >= (long)s->w_size, "slide too late"); -// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || -// s.block_start >= s.w_size)) { -// throw new Error("slide too late"); -// } - - fill_window(s); - if (s.lookahead === 0 && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - - if (s.lookahead === 0) { - break; - } - /* flush the current block */ - } - //Assert(s->block_start >= 0L, "block gone"); -// if (s.block_start < 0) throw new Error("block gone"); - - s.strstart += s.lookahead; - s.lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - var max_start = s.block_start + max_block_size; - - if (s.strstart === 0 || s.strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s.lookahead = s.strstart - max_start; - s.strstart = max_start; - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - - - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - - s.insert = 0; - - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - - if (s.strstart > s.block_start) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_NEED_MORE; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -function deflate_fast(s, flush) { - var hash_head; /* head of the hash chain */ - var bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { - break; /* flush the current block */ - } - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - } - if (s.match_length >= MIN_MATCH) { - // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only - - /*** _tr_tally_dist(s, s.strstart - s.match_start, - s.match_length - MIN_MATCH, bflush); ***/ - bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); - - s.lookahead -= s.match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { - s.match_length--; /* string at strstart already in table */ - do { - s.strstart++; - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s.match_length !== 0); - s.strstart++; - } else - { - s.strstart += s.match_length; - s.match_length = 0; - s.ins_h = s.window[s.strstart]; - /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; - -//#if MIN_MATCH != 3 -// Call UPDATE_HASH() MIN_MATCH-3 more times -//#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s.window[s.strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = ((s.strstart < (MIN_MATCH-1)) ? s.strstart : MIN_MATCH-1); - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -function deflate_slow(s, flush) { - var hash_head; /* head of hash chain */ - var bflush; /* set if current block must be flushed */ - - var max_insert; - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s.lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - hash_head = 0/*NIL*/; - if (s.lookahead >= MIN_MATCH) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - - /* Find the longest match, discarding those <= prev_length. - */ - s.prev_length = s.match_length; - s.prev_match = s.match_start; - s.match_length = MIN_MATCH-1; - - if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && - s.strstart - hash_head <= (s.w_size-MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - s.match_length = longest_match(s, hash_head); - /* longest_match() sets match_start */ - - if (s.match_length <= 5 && - (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s.match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { - max_insert = s.strstart + s.lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - //check_match(s, s.strstart-1, s.prev_match, s.prev_length); - - /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, - s.prev_length - MIN_MATCH, bflush);***/ - bflush = trees._tr_tally(s, s.strstart - 1- s.prev_match, s.prev_length - MIN_MATCH); - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s.lookahead -= s.prev_length-1; - s.prev_length -= 2; - do { - if (++s.strstart <= max_insert) { - /*** INSERT_STRING(s, s.strstart, hash_head); ***/ - s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; - hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; - s.head[s.ins_h] = s.strstart; - /***/ - } - } while (--s.prev_length !== 0); - s.match_available = 0; - s.match_length = MIN_MATCH-1; - s.strstart++; - - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - } else if (s.match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]); - - if (bflush) { - /*** FLUSH_BLOCK_ONLY(s, 0) ***/ - flush_block_only(s, false); - /***/ - } - s.strstart++; - s.lookahead--; - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s.match_available = 1; - s.strstart++; - s.lookahead--; - } - } - //Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s.match_available) { - //Tracevv((stderr,"%c", s->window[s->strstart-1])); - /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]); - - s.match_available = 0; - } - s.insert = s.strstart < MIN_MATCH-1 ? s.strstart : MIN_MATCH-1; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - - return BS_BLOCK_DONE; -} - - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -function deflate_rle(s, flush) { - var bflush; /* set if current block must be flushed */ - var prev; /* byte at distance one to match */ - var scan, strend; /* scan goes up to strend for length of run */ - - var _win = s.window; - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s.lookahead <= MAX_MATCH) { - fill_window(s); - if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - if (s.lookahead === 0) { break; } /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - s.match_length = 0; - if (s.lookahead >= MIN_MATCH && s.strstart > 0) { - scan = s.strstart - 1; - prev = _win[scan]; - if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { - strend = s.strstart + MAX_MATCH; - do { - /*jshint noempty:false*/ - } while (prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - prev === _win[++scan] && prev === _win[++scan] && - scan < strend); - s.match_length = MAX_MATCH - (strend - scan); - if (s.match_length > s.lookahead) { - s.match_length = s.lookahead; - } - } - //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (s.match_length >= MIN_MATCH) { - //check_match(s, s.strstart, s.strstart - 1, s.match_length); - - /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ - bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); - - s.lookahead -= s.match_length; - s.strstart += s.match_length; - s.match_length = 0; - } else { - /* No match, output a literal byte */ - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - - s.lookahead--; - s.strstart++; - } - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -function deflate_huff(s, flush) { - var bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s.lookahead === 0) { - fill_window(s); - if (s.lookahead === 0) { - if (flush === Z_NO_FLUSH) { - return BS_NEED_MORE; - } - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - s.match_length = 0; - //Tracevv((stderr,"%c", s->window[s->strstart])); - /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ - bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - s.lookahead--; - s.strstart++; - if (bflush) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - } - s.insert = 0; - if (flush === Z_FINISH) { - /*** FLUSH_BLOCK(s, 1); ***/ - flush_block_only(s, true); - if (s.strm.avail_out === 0) { - return BS_FINISH_STARTED; - } - /***/ - return BS_FINISH_DONE; - } - if (s.last_lit) { - /*** FLUSH_BLOCK(s, 0); ***/ - flush_block_only(s, false); - if (s.strm.avail_out === 0) { - return BS_NEED_MORE; - } - /***/ - } - return BS_BLOCK_DONE; -} - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -var Config = function (good_length, max_lazy, nice_length, max_chain, func) { - this.good_length = good_length; - this.max_lazy = max_lazy; - this.nice_length = nice_length; - this.max_chain = max_chain; - this.func = func; -}; - -var configuration_table; - -configuration_table = [ - /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), /* 3 */ - - new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ -]; - - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -function lm_init(s) { - s.window_size = 2 * s.w_size; - - /*** CLEAR_HASH(s); ***/ - zero(s.head); // Fill with NIL (= 0); - - /* Set the default configuration parameters: - */ - s.max_lazy_match = configuration_table[s.level].max_lazy; - s.good_match = configuration_table[s.level].good_length; - s.nice_match = configuration_table[s.level].nice_length; - s.max_chain_length = configuration_table[s.level].max_chain; - - s.strstart = 0; - s.block_start = 0; - s.lookahead = 0; - s.insert = 0; - s.match_length = s.prev_length = MIN_MATCH - 1; - s.match_available = 0; - s.ins_h = 0; -} - - -function DeflateState() { - this.strm = null; /* pointer back to this zlib stream */ - this.status = 0; /* as the name implies */ - this.pending_buf = null; /* output still pending */ - this.pending_buf_size = 0; /* size of pending_buf */ - this.pending_out = 0; /* next pending byte to output to the stream */ - this.pending = 0; /* nb of bytes in the pending buffer */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.gzhead = null; /* gzip header information to write */ - this.gzindex = 0; /* where in extra, name, or comment */ - this.method = Z_DEFLATED; /* can only be DEFLATED */ - this.last_flush = -1; /* value of flush param for previous deflate call */ - - this.w_size = 0; /* LZ77 window size (32K by default) */ - this.w_bits = 0; /* log2(w_size) (8..16) */ - this.w_mask = 0; /* w_size - 1 */ - - this.window = null; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. - */ - - this.window_size = 0; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - this.prev = null; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - this.head = null; /* Heads of the hash chains or NIL. */ - - this.ins_h = 0; /* hash index of string to be inserted */ - this.hash_size = 0; /* number of elements in hash table */ - this.hash_bits = 0; /* log2(hash_size) */ - this.hash_mask = 0; /* hash_size-1 */ - - this.hash_shift = 0; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - this.block_start = 0; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - this.match_length = 0; /* length of best match */ - this.prev_match = 0; /* previous match */ - this.match_available = 0; /* set if previous match exists */ - this.strstart = 0; /* start of string to insert */ - this.match_start = 0; /* start of matching string */ - this.lookahead = 0; /* number of valid bytes ahead in window */ - - this.prev_length = 0; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - this.max_chain_length = 0; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - this.max_lazy_match = 0; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ - // That's alias to max_lazy_match, don't use directly - //this.max_insert_length = 0; - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - this.level = 0; /* compression level (1..9) */ - this.strategy = 0; /* favor or force Huffman coding*/ - - this.good_match = 0; - /* Use a faster search when the previous match is longer than this */ - - this.nice_match = 0; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - - /* Didn't use ct_data typedef below to suppress compiler warning */ - - // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - // Use flat array of DOUBLE size, with interleaved fata, - // because JS does not support effective - this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); - this.dyn_dtree = new utils.Buf16((2*D_CODES+1) * 2); - this.bl_tree = new utils.Buf16((2*BL_CODES+1) * 2); - zero(this.dyn_ltree); - zero(this.dyn_dtree); - zero(this.bl_tree); - - this.l_desc = null; /* desc. for literal tree */ - this.d_desc = null; /* desc. for distance tree */ - this.bl_desc = null; /* desc. for bit length tree */ - - //ush bl_count[MAX_BITS+1]; - this.bl_count = new utils.Buf16(MAX_BITS+1); - /* number of codes at each bit length for an optimal tree */ - - //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - this.heap = new utils.Buf16(2*L_CODES+1); /* heap used to build the Huffman trees */ - zero(this.heap); - - this.heap_len = 0; /* number of elements in the heap */ - this.heap_max = 0; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - this.depth = new utils.Buf16(2*L_CODES+1); //uch depth[2*L_CODES+1]; - zero(this.depth); - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - this.l_buf = 0; /* buffer index for literals or lengths */ - - this.lit_bufsize = 0; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - this.last_lit = 0; /* running index in l_buf */ - - this.d_buf = 0; - /* Buffer index for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - this.opt_len = 0; /* bit length of current block with optimal trees */ - this.static_len = 0; /* bit length of current block with static trees */ - this.matches = 0; /* number of string matches in current block */ - this.insert = 0; /* bytes at end of window left to insert */ - - - this.bi_buf = 0; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - this.bi_valid = 0; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - - // Used for window memory init. We safely ignore it for JS. That makes - // sense only for pointers and memory check tools. - //this.high_water = 0; - /* High water mark offset in window for initialized bytes -- bytes above - * this are set to zero in order to avoid memory check warnings when - * longest match routines access bytes past the input. This is then - * updated to the new high water mark. - */ -} - - -function deflateResetKeep(strm) { - var s; - - if (!strm || !strm.state) { - return err(strm, Z_STREAM_ERROR); - } - - strm.total_in = strm.total_out = 0; - strm.data_type = Z_UNKNOWN; - - s = strm.state; - s.pending = 0; - s.pending_out = 0; - - if (s.wrap < 0) { - s.wrap = -s.wrap; - /* was made negative by deflate(..., Z_FINISH); */ - } - s.status = (s.wrap ? INIT_STATE : BUSY_STATE); - strm.adler = (s.wrap === 2) ? - 0 // crc32(0, Z_NULL, 0) - : - 1; // adler32(0, Z_NULL, 0) - s.last_flush = Z_NO_FLUSH; - trees._tr_init(s); - return Z_OK; -} - - -function deflateReset(strm) { - var ret = deflateResetKeep(strm); - if (ret === Z_OK) { - lm_init(strm.state); - } - return ret; -} - - -function deflateSetHeader(strm, head) { - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } - strm.state.gzhead = head; - return Z_OK; -} - - -function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { - if (!strm) { // === Z_NULL - return Z_STREAM_ERROR; - } - var wrap = 1; - - if (level === Z_DEFAULT_COMPRESSION) { - level = 6; - } - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } - - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } - - - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return err(strm, Z_STREAM_ERROR); - } - - - if (windowBits === 8) { - windowBits = 9; - } - /* until 256-byte window bug fixed */ - - var s = new DeflateState(); - - strm.state = s; - s.strm = strm; - - s.wrap = wrap; - s.gzhead = null; - s.w_bits = windowBits; - s.w_size = 1 << s.w_bits; - s.w_mask = s.w_size - 1; - - s.hash_bits = memLevel + 7; - s.hash_size = 1 << s.hash_bits; - s.hash_mask = s.hash_size - 1; - s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); - - s.window = new utils.Buf8(s.w_size * 2); - s.head = new utils.Buf16(s.hash_size); - s.prev = new utils.Buf16(s.w_size); - - // Don't need mem init magic for JS. - //s.high_water = 0; /* nothing written to s->window yet */ - - s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - s.pending_buf_size = s.lit_bufsize * 4; - s.pending_buf = new utils.Buf8(s.pending_buf_size); - - s.d_buf = s.lit_bufsize >> 1; - s.l_buf = (1 + 2) * s.lit_bufsize; - - s.level = level; - s.strategy = strategy; - s.method = method; - - return deflateReset(strm); -} - -function deflateInit(strm, level) { - return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); -} - - -function deflate(strm, flush) { - var old_flush, s; - var beg, val; // for gzip header write only - - if (!strm || !strm.state || - flush > Z_BLOCK || flush < 0) { - return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; - } - - s = strm.state; - - if (!strm.output || - (!strm.input && strm.avail_in !== 0) || - (s.status === FINISH_STATE && flush !== Z_FINISH)) { - return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); - } - - s.strm = strm; /* just in case */ - old_flush = s.last_flush; - s.last_flush = flush; - - /* Write the header */ - if (s.status === INIT_STATE) { - - if (s.wrap === 2) { // GZIP header - strm.adler = 0; //crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (!s.gzhead) { // s->gzhead == Z_NULL - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s.status = BUSY_STATE; - } - else { - put_byte(s, (s.gzhead.text ? 1 : 0) + - (s.gzhead.hcrc ? 2 : 0) + - (!s.gzhead.extra ? 0 : 4) + - (!s.gzhead.name ? 0 : 8) + - (!s.gzhead.comment ? 0 : 16) - ); - put_byte(s, s.gzhead.time & 0xff); - put_byte(s, (s.gzhead.time >> 8) & 0xff); - put_byte(s, (s.gzhead.time >> 16) & 0xff); - put_byte(s, (s.gzhead.time >> 24) & 0xff); - put_byte(s, s.level === 9 ? 2 : - (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? - 4 : 0)); - put_byte(s, s.gzhead.os & 0xff); - if (s.gzhead.extra && s.gzhead.extra.length) { - put_byte(s, s.gzhead.extra.length & 0xff); - put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); - } - if (s.gzhead.hcrc) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); - } - s.gzindex = 0; - s.status = EXTRA_STATE; - } - } - else // DEFLATE header - { - var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; - var level_flags = -1; - - if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { - level_flags = 0; - } else if (s.level < 6) { - level_flags = 1; - } else if (s.level === 6) { - level_flags = 2; - } else { - level_flags = 3; - } - header |= (level_flags << 6); - if (s.strstart !== 0) { header |= PRESET_DICT; } - header += 31 - (header % 31); - - s.status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s.strstart !== 0) { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - strm.adler = 1; // adler32(0L, Z_NULL, 0); - } - } - -//#ifdef GZIP - if (s.status === EXTRA_STATE) { - if (s.gzhead.extra/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - - while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - break; - } - } - put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); - s.gzindex++; - } - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (s.gzindex === s.gzhead.extra.length) { - s.gzindex = 0; - s.status = NAME_STATE; - } - } - else { - s.status = NAME_STATE; - } - } - if (s.status === NAME_STATE) { - if (s.gzhead.name/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.name.length) { - val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg){ - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.gzindex = 0; - s.status = COMMENT_STATE; - } - } - else { - s.status = COMMENT_STATE; - } - } - if (s.status === COMMENT_STATE) { - if (s.gzhead.comment/* != Z_NULL*/) { - beg = s.pending; /* start of bytes to update crc */ - //int val; - - do { - if (s.pending === s.pending_buf_size) { - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - flush_pending(strm); - beg = s.pending; - if (s.pending === s.pending_buf_size) { - val = 1; - break; - } - } - // JS specific: little magic to add zero terminator to end of string - if (s.gzindex < s.gzhead.comment.length) { - val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; - } else { - val = 0; - } - put_byte(s, val); - } while (val !== 0); - - if (s.gzhead.hcrc && s.pending > beg) { - strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); - } - if (val === 0) { - s.status = HCRC_STATE; - } - } - else { - s.status = HCRC_STATE; - } - } - if (s.status === HCRC_STATE) { - if (s.gzhead.hcrc) { - if (s.pending + 2 > s.pending_buf_size) { - flush_pending(strm); - } - if (s.pending + 2 <= s.pending_buf_size) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - strm.adler = 0; //crc32(0L, Z_NULL, 0); - s.status = BUSY_STATE; - } - } - else { - s.status = BUSY_STATE; - } - } -//#endif - - /* Flush as much pending output as possible */ - if (s.pending !== 0) { - flush_pending(strm); - if (strm.avail_out === 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s.last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && - flush !== Z_FINISH) { - return err(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s.status === FINISH_STATE && strm.avail_in !== 0) { - return err(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm.avail_in !== 0 || s.lookahead !== 0 || - (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { - var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : - (s.strategy === Z_RLE ? deflate_rle(s, flush) : - configuration_table[s.level].func(s, flush)); - - if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { - s.status = FINISH_STATE; - } - if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { - if (strm.avail_out === 0) { - s.last_flush = -1; - /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate === BS_BLOCK_DONE) { - if (flush === Z_PARTIAL_FLUSH) { - trees._tr_align(s); - } - else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ - - trees._tr_stored_block(s, 0, 0, false); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush === Z_FULL_FLUSH) { - /*** CLEAR_HASH(s); ***/ /* forget history */ - zero(s.head); // Fill with NIL (= 0); - - if (s.lookahead === 0) { - s.strstart = 0; - s.block_start = 0; - s.insert = 0; - } - } - } - flush_pending(strm); - if (strm.avail_out === 0) { - s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - //Assert(strm->avail_out > 0, "bug2"); - //if (strm.avail_out <= 0) { throw new Error("bug2");} - - if (flush !== Z_FINISH) { return Z_OK; } - if (s.wrap <= 0) { return Z_STREAM_END; } - - /* Write the trailer */ - if (s.wrap === 2) { - put_byte(s, strm.adler & 0xff); - put_byte(s, (strm.adler >> 8) & 0xff); - put_byte(s, (strm.adler >> 16) & 0xff); - put_byte(s, (strm.adler >> 24) & 0xff); - put_byte(s, strm.total_in & 0xff); - put_byte(s, (strm.total_in >> 8) & 0xff); - put_byte(s, (strm.total_in >> 16) & 0xff); - put_byte(s, (strm.total_in >> 24) & 0xff); - } - else - { - putShortMSB(s, strm.adler >>> 16); - putShortMSB(s, strm.adler & 0xffff); - } - - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s.wrap > 0) { s.wrap = -s.wrap; } - /* write the trailer only once! */ - return s.pending !== 0 ? Z_OK : Z_STREAM_END; -} - -function deflateEnd(strm) { - var status; - - if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { - return Z_STREAM_ERROR; - } - - status = strm.state.status; - if (status !== INIT_STATE && - status !== EXTRA_STATE && - status !== NAME_STATE && - status !== COMMENT_STATE && - status !== HCRC_STATE && - status !== BUSY_STATE && - status !== FINISH_STATE - ) { - return err(strm, Z_STREAM_ERROR); - } - - strm.state = null; - - return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state - */ -//function deflateCopy(dest, source) { -// -//} - -exports.deflateInit = deflateInit; -exports.deflateInit2 = deflateInit2; -exports.deflateReset = deflateReset; -exports.deflateResetKeep = deflateResetKeep; -exports.deflateSetHeader = deflateSetHeader; -exports.deflate = deflate; -exports.deflateEnd = deflateEnd; -exports.deflateInfo = 'pako deflate (from Nodeca project)'; - -/* Not implemented -exports.deflateBound = deflateBound; -exports.deflateCopy = deflateCopy; -exports.deflateSetDictionary = deflateSetDictionary; -exports.deflateParams = deflateParams; -exports.deflatePending = deflatePending; -exports.deflatePrime = deflatePrime; -exports.deflateTune = deflateTune; -*/ -},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(_dereq_,module,exports){ -'use strict'; - - -function GZheader() { - /* true if compressed data believed to be text */ - this.text = 0; - /* modification time */ - this.time = 0; - /* extra flags (not used when writing a gzip file) */ - this.xflags = 0; - /* operating system */ - this.os = 0; - /* pointer to extra field or Z_NULL if none */ - this.extra = null; - /* extra field length (valid if extra != Z_NULL) */ - this.extra_len = 0; // Actually, we don't need it in JS, - // but leave for few code modifications - - // - // Setup limits is not necessary because in js we should not preallocate memory - // for inflate use constant limit in 65536 bytes - // - - /* space at extra (only when reading header) */ - // this.extra_max = 0; - /* pointer to zero-terminated file name or Z_NULL */ - this.name = ''; - /* space at name (only when reading header) */ - // this.name_max = 0; - /* pointer to zero-terminated comment or Z_NULL */ - this.comment = ''; - /* space at comment (only when reading header) */ - // this.comm_max = 0; - /* true if there was or will be a header crc */ - this.hcrc = 0; - /* true when done reading gzip header (not used when writing a gzip file) */ - this.done = false; -} - -module.exports = GZheader; -},{}],34:[function(_dereq_,module,exports){ -'use strict'; - -// See state defs from inflate.js -var BAD = 30; /* got a data error -- remain here until reset */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state.mode === LEN - strm.avail_in >= 6 - strm.avail_out >= 258 - start >= strm.avail_out - state.bits < 8 - - On return, state.mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm.avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm.avail_out >= 258 for each loop to avoid checking for - output space. - */ -module.exports = function inflate_fast(strm, start) { - var state; - var _in; /* local strm.input */ - var last; /* have enough input while in < last */ - var _out; /* local strm.output */ - var beg; /* inflate()'s initial strm.output */ - var end; /* while out < end, enough space available */ -//#ifdef INFLATE_STRICT - var dmax; /* maximum distance from zlib header */ -//#endif - var wsize; /* window size or zero if not using window */ - var whave; /* valid bytes in the window */ - var wnext; /* window write index */ - var window; /* allocated sliding window, if wsize != 0 */ - var hold; /* local strm.hold */ - var bits; /* local strm.bits */ - var lcode; /* local strm.lencode */ - var dcode; /* local strm.distcode */ - var lmask; /* mask for first level of length codes */ - var dmask; /* mask for first level of distance codes */ - var here; /* retrieved table entry */ - var op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - var len; /* match length, unused bytes */ - var dist; /* match distance */ - var from; /* where to copy match from */ - var from_source; - - - var input, output; // JS specific, because we have no pointers - - /* copy state to local variables */ - state = strm.state; - //here = state.here; - _in = strm.next_in; - input = strm.input; - last = _in + (strm.avail_in - 5); - _out = strm.next_out; - output = strm.output; - beg = _out - (start - strm.avail_out); - end = _out + (strm.avail_out - 257); -//#ifdef INFLATE_STRICT - dmax = state.dmax; -//#endif - wsize = state.wsize; - whave = state.whave; - wnext = state.wnext; - window = state.window; - hold = state.hold; - bits = state.bits; - lcode = state.lencode; - dcode = state.distcode; - lmask = (1 << state.lenbits) - 1; - dmask = (1 << state.distbits) - 1; - - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - top: - do { - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - - here = lcode[hold & lmask]; - - dolen: - for (;;) { // Goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - if (op === 0) { /* literal */ - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - output[_out++] = here & 0xffff/*here.val*/; - } - else if (op & 16) { /* length base */ - len = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - len += hold & ((1 << op) - 1); - hold >>>= op; - bits -= op; - } - //Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += input[_in++] << bits; - bits += 8; - hold += input[_in++] << bits; - bits += 8; - } - here = dcode[hold & dmask]; - - dodist: - for (;;) { // goto emulation - op = here >>> 24/*here.bits*/; - hold >>>= op; - bits -= op; - op = (here >>> 16) & 0xff/*here.op*/; - - if (op & 16) { /* distance base */ - dist = here & 0xffff/*here.val*/; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - if (bits < op) { - hold += input[_in++] << bits; - bits += 8; - } - } - dist += hold & ((1 << op) - 1); -//#ifdef INFLATE_STRICT - if (dist > dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } -//#endif - hold >>>= op; - bits -= op; - //Tracevv((stderr, "inflate: distance %u\n", dist)); - op = _out - beg; /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break top; - } - -// (!) This block is disabled in zlib defailts, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// if (len <= op - whave) { -// do { -// output[_out++] = 0; -// } while (--len); -// continue top; -// } -// len -= op - whave; -// do { -// output[_out++] = 0; -// } while (--op > whave); -// if (op === 0) { -// from = _out - dist; -// do { -// output[_out++] = output[from++]; -// } while (--len); -// continue top; -// } -//#endif - } - from = 0; // window index - from_source = window; - if (wnext === 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - else if (wnext < op) { /* wrap around window */ - from += wsize + wnext - op; - op -= wnext; - if (op < len) { /* some from end of window */ - len -= op; - do { - output[_out++] = window[from++]; - } while (--op); - from = 0; - if (wnext < len) { /* some from start of window */ - op = wnext; - len -= op; - do { - output[_out++] = window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - } - else { /* contiguous in window */ - from += wnext - op; - if (op < len) { /* some from window */ - len -= op; - do { - output[_out++] = window[from++]; - } while (--op); - from = _out - dist; /* rest from output */ - from_source = output; - } - } - while (len > 2) { - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - output[_out++] = from_source[from++]; - len -= 3; - } - if (len) { - output[_out++] = from_source[from++]; - if (len > 1) { - output[_out++] = from_source[from++]; - } - } - } - else { - from = _out - dist; /* copy direct from output */ - do { /* minimum length is three */ - output[_out++] = output[from++]; - output[_out++] = output[from++]; - output[_out++] = output[from++]; - len -= 3; - } while (len > 2); - if (len) { - output[_out++] = output[from++]; - if (len > 1) { - output[_out++] = output[from++]; - } - } - } - } - else if ((op & 64) === 0) { /* 2nd level distance code */ - here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dodist; - } - else { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } - else if ((op & 64) === 0) { /* 2nd level length code */ - here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dolen; - } - else if (op & 32) { /* end-of-block */ - //Tracevv((stderr, "inflate: end of block\n")); - state.mode = TYPE; - break top; - } - else { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break top; - } - - break; // need to emulate goto via "continue" - } - } while (_in < last && _out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - _in -= len; - bits -= len << 3; - hold &= (1 << bits) - 1; - - /* update state and return */ - strm.next_in = _in; - strm.next_out = _out; - strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); - strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); - state.hold = hold; - state.bits = bits; - return; -}; - -},{}],35:[function(_dereq_,module,exports){ -'use strict'; - - -var utils = _dereq_('../utils/common'); -var adler32 = _dereq_('./adler32'); -var crc32 = _dereq_('./crc32'); -var inflate_fast = _dereq_('./inffast'); -var inflate_table = _dereq_('./inftrees'); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -/* Allowed flush values; see deflate() and inflate() below for details */ -//var Z_NO_FLUSH = 0; -//var Z_PARTIAL_FLUSH = 1; -//var Z_SYNC_FLUSH = 2; -//var Z_FULL_FLUSH = 3; -var Z_FINISH = 4; -var Z_BLOCK = 5; -var Z_TREES = 6; - - -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ -var Z_OK = 0; -var Z_STREAM_END = 1; -var Z_NEED_DICT = 2; -//var Z_ERRNO = -1; -var Z_STREAM_ERROR = -2; -var Z_DATA_ERROR = -3; -var Z_MEM_ERROR = -4; -var Z_BUF_ERROR = -5; -//var Z_VERSION_ERROR = -6; - -/* The deflate compression method */ -var Z_DEFLATED = 8; - - -/* STATES ====================================================================*/ -/* ===========================================================================*/ - - -var HEAD = 1; /* i: waiting for magic header */ -var FLAGS = 2; /* i: waiting for method and flags (gzip) */ -var TIME = 3; /* i: waiting for modification time (gzip) */ -var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ -var EXLEN = 5; /* i: waiting for extra length (gzip) */ -var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ -var NAME = 7; /* i: waiting for end of file name (gzip) */ -var COMMENT = 8; /* i: waiting for end of comment (gzip) */ -var HCRC = 9; /* i: waiting for header crc (gzip) */ -var DICTID = 10; /* i: waiting for dictionary check value */ -var DICT = 11; /* waiting for inflateSetDictionary() call */ -var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ -var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ -var STORED = 14; /* i: waiting for stored size (length and complement) */ -var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ -var COPY = 16; /* i/o: waiting for input or output to copy stored block */ -var TABLE = 17; /* i: waiting for dynamic block table lengths */ -var LENLENS = 18; /* i: waiting for code length code lengths */ -var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ -var LEN_ = 20; /* i: same as LEN below, but only first time in */ -var LEN = 21; /* i: waiting for length/lit/eob code */ -var LENEXT = 22; /* i: waiting for length extra bits */ -var DIST = 23; /* i: waiting for distance code */ -var DISTEXT = 24; /* i: waiting for distance extra bits */ -var MATCH = 25; /* o: waiting for output space to copy string */ -var LIT = 26; /* o: waiting for output space to write literal */ -var CHECK = 27; /* i: waiting for 32-bit check value */ -var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ -var DONE = 29; /* finished check, done -- remain here until reset */ -var BAD = 30; /* got a data error -- remain here until reset */ -var MEM = 31; /* got an inflate() memory error -- remain here until reset */ -var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ - -/* ===========================================================================*/ - - - -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var MAX_WBITS = 15; -/* 32K LZ77 window */ -var DEF_WBITS = MAX_WBITS; - - -function ZSWAP32(q) { - return (((q >>> 24) & 0xff) + - ((q >>> 8) & 0xff00) + - ((q & 0xff00) << 8) + - ((q & 0xff) << 24)); -} - - -function InflateState() { - this.mode = 0; /* current inflate mode */ - this.last = false; /* true if processing last block */ - this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ - this.havedict = false; /* true if dictionary provided */ - this.flags = 0; /* gzip header method and flags (0 if zlib) */ - this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ - this.check = 0; /* protected copy of check value */ - this.total = 0; /* protected copy of output count */ - // TODO: may be {} - this.head = null; /* where to save gzip header information */ - - /* sliding window */ - this.wbits = 0; /* log base 2 of requested window size */ - this.wsize = 0; /* window size or zero if not using window */ - this.whave = 0; /* valid bytes in the window */ - this.wnext = 0; /* window write index */ - this.window = null; /* allocated sliding window, if needed */ - - /* bit accumulator */ - this.hold = 0; /* input bit accumulator */ - this.bits = 0; /* number of bits in "in" */ - - /* for string and stored block copying */ - this.length = 0; /* literal or length of data to copy */ - this.offset = 0; /* distance back to copy string from */ - - /* for table and code decoding */ - this.extra = 0; /* extra bits needed */ - - /* fixed and dynamic code tables */ - this.lencode = null; /* starting table for length/literal codes */ - this.distcode = null; /* starting table for distance codes */ - this.lenbits = 0; /* index bits for lencode */ - this.distbits = 0; /* index bits for distcode */ - - /* dynamic table building */ - this.ncode = 0; /* number of code length code lengths */ - this.nlen = 0; /* number of length code lengths */ - this.ndist = 0; /* number of distance code lengths */ - this.have = 0; /* number of code lengths in lens[] */ - this.next = null; /* next available space in codes[] */ - - this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ - this.work = new utils.Buf16(288); /* work area for code table building */ - - /* - because we don't have pointers in js, we use lencode and distcode directly - as buffers so we don't need codes - */ - //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ - this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ - this.distdyn = null; /* dynamic table for distance codes (JS specific) */ - this.sane = 0; /* if false, allow invalid distance too far */ - this.back = 0; /* bits back of last unprocessed length/lit */ - this.was = 0; /* initial length of match */ -} - -function inflateResetKeep(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - strm.total_in = strm.total_out = state.total = 0; - strm.msg = ''; /*Z_NULL*/ - if (state.wrap) { /* to support ill-conceived Java test suite */ - strm.adler = state.wrap & 1; - } - state.mode = HEAD; - state.last = 0; - state.havedict = 0; - state.dmax = 32768; - state.head = null/*Z_NULL*/; - state.hold = 0; - state.bits = 0; - //state.lencode = state.distcode = state.next = state.codes; - state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); - state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); - - state.sane = 1; - state.back = -1; - //Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -function inflateReset(strm) { - var state; - - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - state.wsize = 0; - state.whave = 0; - state.wnext = 0; - return inflateResetKeep(strm); - -} - -function inflateReset2(strm, windowBits) { - var wrap; - var state; - - /* get the state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - - /* extract wrap request from windowBits parameter */ - if (windowBits < 0) { - wrap = 0; - windowBits = -windowBits; - } - else { - wrap = (windowBits >> 4) + 1; - if (windowBits < 48) { - windowBits &= 15; - } - } - - /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) { - return Z_STREAM_ERROR; - } - if (state.window !== null && state.wbits !== windowBits) { - state.window = null; - } - - /* update state and reset the rest of it */ - state.wrap = wrap; - state.wbits = windowBits; - return inflateReset(strm); -} - -function inflateInit2(strm, windowBits) { - var ret; - var state; - - if (!strm) { return Z_STREAM_ERROR; } - //strm.msg = Z_NULL; /* in case we return an error */ - - state = new InflateState(); - - //if (state === Z_NULL) return Z_MEM_ERROR; - //Tracev((stderr, "inflate: allocated\n")); - strm.state = state; - state.window = null/*Z_NULL*/; - ret = inflateReset2(strm, windowBits); - if (ret !== Z_OK) { - strm.state = null/*Z_NULL*/; - } - return ret; -} - -function inflateInit(strm) { - return inflateInit2(strm, DEF_WBITS); -} - - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -var virgin = true; - -var lenfix, distfix; // We have no pointers in JS, so keep tables separate - -function fixedtables(state) { - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - var sym; - - lenfix = new utils.Buf32(512); - distfix = new utils.Buf32(32); - - /* literal/length table */ - sym = 0; - while (sym < 144) { state.lens[sym++] = 8; } - while (sym < 256) { state.lens[sym++] = 9; } - while (sym < 280) { state.lens[sym++] = 7; } - while (sym < 288) { state.lens[sym++] = 8; } - - inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, {bits: 9}); - - /* distance table */ - sym = 0; - while (sym < 32) { state.lens[sym++] = 5; } - - inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, {bits: 5}); - - /* do this just once */ - virgin = false; - } - - state.lencode = lenfix; - state.lenbits = 9; - state.distcode = distfix; - state.distbits = 5; -} - - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -function updatewindow(strm, src, end, copy) { - var dist; - var state = strm.state; - - /* if it hasn't been done already, allocate space for the window */ - if (state.window === null) { - state.wsize = 1 << state.wbits; - state.wnext = 0; - state.whave = 0; - - state.window = new utils.Buf8(state.wsize); - } - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state.wsize) { - utils.arraySet(state.window,src, end - state.wsize, state.wsize, 0); - state.wnext = 0; - state.whave = state.wsize; - } - else { - dist = state.wsize - state.wnext; - if (dist > copy) { - dist = copy; - } - //zmemcpy(state->window + state->wnext, end - copy, dist); - utils.arraySet(state.window,src, end - copy, dist, state.wnext); - copy -= dist; - if (copy) { - //zmemcpy(state->window, end - copy, copy); - utils.arraySet(state.window,src, end - copy, copy, 0); - state.wnext = copy; - state.whave = state.wsize; - } - else { - state.wnext += dist; - if (state.wnext === state.wsize) { state.wnext = 0; } - if (state.whave < state.wsize) { state.whave += dist; } - } - } - return 0; -} - -function inflate(strm, flush) { - var state; - var input, output; // input/output buffers - var next; /* next input INDEX */ - var put; /* next output INDEX */ - var have, left; /* available input and output */ - var hold; /* bit buffer */ - var bits; /* bits in bit buffer */ - var _in, _out; /* save starting available input and output */ - var copy; /* number of stored or match bytes to copy */ - var from; /* where to copy match bytes from */ - var from_source; - var here = 0; /* current decoding table entry */ - var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) - //var last; /* parent table entry */ - var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) - var len; /* length to copy for repeats, bits to drop */ - var ret; /* return code */ - var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ - var opts; - - var n; // temporary var for NEED_BITS - - var order = /* permutation of code lengths */ - [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; - - - if (!strm || !strm.state || !strm.output || - (!strm.input && strm.avail_in !== 0)) { - return Z_STREAM_ERROR; - } - - state = strm.state; - if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ - - - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - _in = have; - _out = left; - ret = Z_OK; - - inf_leave: // goto emulation - for (;;) { - switch (state.mode) { - case HEAD: - if (state.wrap === 0) { - state.mode = TYPEDO; - break; - } - //=== NEEDBITS(16); - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ - state.check = 0/*crc32(0L, Z_NULL, 0)*/; - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = FLAGS; - break; - } - state.flags = 0; /* expect zlib header */ - if (state.head) { - state.head.done = false; - } - if (!(state.wrap & 1) || /* check if zlib header allowed */ - (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { - strm.msg = 'incorrect header check'; - state.mode = BAD; - break; - } - if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// - len = (hold & 0x0f)/*BITS(4)*/ + 8; - if (state.wbits === 0) { - state.wbits = len; - } - else if (len > state.wbits) { - strm.msg = 'invalid window size'; - state.mode = BAD; - break; - } - state.dmax = 1 << len; - //Tracev((stderr, "inflate: zlib header ok\n")); - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = hold & 0x200 ? DICTID : TYPE; - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - break; - case FLAGS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.flags = hold; - if ((state.flags & 0xff) !== Z_DEFLATED) { - strm.msg = 'unknown compression method'; - state.mode = BAD; - break; - } - if (state.flags & 0xe000) { - strm.msg = 'unknown header flags set'; - state.mode = BAD; - break; - } - if (state.head) { - state.head.text = ((hold >> 8) & 1); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = TIME; - /* falls through */ - case TIME: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.time = hold; - } - if (state.flags & 0x0200) { - //=== CRC4(state.check, hold) - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - hbuf[2] = (hold >>> 16) & 0xff; - hbuf[3] = (hold >>> 24) & 0xff; - state.check = crc32(state.check, hbuf, 4, 0); - //=== - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = OS; - /* falls through */ - case OS: - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (state.head) { - state.head.xflags = (hold & 0xff); - state.head.os = (hold >> 8); - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = EXLEN; - /* falls through */ - case EXLEN: - if (state.flags & 0x0400) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length = hold; - if (state.head) { - state.head.extra_len = hold; - } - if (state.flags & 0x0200) { - //=== CRC2(state.check, hold); - hbuf[0] = hold & 0xff; - hbuf[1] = (hold >>> 8) & 0xff; - state.check = crc32(state.check, hbuf, 2, 0); - //===// - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - else if (state.head) { - state.head.extra = null/*Z_NULL*/; - } - state.mode = EXTRA; - /* falls through */ - case EXTRA: - if (state.flags & 0x0400) { - copy = state.length; - if (copy > have) { copy = have; } - if (copy) { - if (state.head) { - len = state.head.extra_len - state.length; - if (!state.head.extra) { - // Use untyped array for more conveniend processing later - state.head.extra = new Array(state.head.extra_len); - } - utils.arraySet( - state.head.extra, - input, - next, - // extra field is limited to 65536 bytes - // - no need for additional size check - copy, - /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ - len - ); - //zmemcpy(state.head.extra + len, next, - // len + copy > state.head.extra_max ? - // state.head.extra_max - len : copy); - } - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - state.length -= copy; - } - if (state.length) { break inf_leave; } - } - state.length = 0; - state.mode = NAME; - /* falls through */ - case NAME: - if (state.flags & 0x0800) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - // TODO: 2 or 1 bytes? - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.name_max*/)) { - state.head.name += String.fromCharCode(len); - } - } while (len && copy < have); - - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.name = null; - } - state.length = 0; - state.mode = COMMENT; - /* falls through */ - case COMMENT: - if (state.flags & 0x1000) { - if (have === 0) { break inf_leave; } - copy = 0; - do { - len = input[next + copy++]; - /* use constant limit because in js we should not preallocate memory */ - if (state.head && len && - (state.length < 65536 /*state.head.comm_max*/)) { - state.head.comment += String.fromCharCode(len); - } - } while (len && copy < have); - if (state.flags & 0x0200) { - state.check = crc32(state.check, input, copy, next); - } - have -= copy; - next += copy; - if (len) { break inf_leave; } - } - else if (state.head) { - state.head.comment = null; - } - state.mode = HCRC; - /* falls through */ - case HCRC: - if (state.flags & 0x0200) { - //=== NEEDBITS(16); */ - while (bits < 16) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.check & 0xffff)) { - strm.msg = 'header crc mismatch'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - } - if (state.head) { - state.head.hcrc = ((state.flags >> 9) & 1); - state.head.done = true; - } - strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/; - state.mode = TYPE; - break; - case DICTID: - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - strm.adler = state.check = ZSWAP32(hold); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = DICT; - /* falls through */ - case DICT: - if (state.havedict === 0) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - return Z_NEED_DICT; - } - strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; - state.mode = TYPE; - /* falls through */ - case TYPE: - if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } - /* falls through */ - case TYPEDO: - if (state.last) { - //--- BYTEBITS() ---// - hold >>>= bits & 7; - bits -= bits & 7; - //---// - state.mode = CHECK; - break; - } - //=== NEEDBITS(3); */ - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.last = (hold & 0x01)/*BITS(1)*/; - //--- DROPBITS(1) ---// - hold >>>= 1; - bits -= 1; - //---// - - switch ((hold & 0x03)/*BITS(2)*/) { - case 0: /* stored block */ - //Tracev((stderr, "inflate: stored block%s\n", - // state.last ? " (last)" : "")); - state.mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - //Tracev((stderr, "inflate: fixed codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = LEN_; /* decode codes */ - if (flush === Z_TREES) { - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break inf_leave; - } - break; - case 2: /* dynamic block */ - //Tracev((stderr, "inflate: dynamic codes block%s\n", - // state.last ? " (last)" : "")); - state.mode = TABLE; - break; - case 3: - strm.msg = 'invalid block type'; - state.mode = BAD; - } - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - break; - case STORED: - //--- BYTEBITS() ---// /* go to byte boundary */ - hold >>>= bits & 7; - bits -= bits & 7; - //---// - //=== NEEDBITS(32); */ - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { - strm.msg = 'invalid stored block lengths'; - state.mode = BAD; - break; - } - state.length = hold & 0xffff; - //Tracev((stderr, "inflate: stored length %u\n", - // state.length)); - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - state.mode = COPY_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case COPY_: - state.mode = COPY; - /* falls through */ - case COPY: - copy = state.length; - if (copy) { - if (copy > have) { copy = have; } - if (copy > left) { copy = left; } - if (copy === 0) { break inf_leave; } - //--- zmemcpy(put, next, copy); --- - utils.arraySet(output, input, next, copy, put); - //---// - have -= copy; - next += copy; - left -= copy; - put += copy; - state.length -= copy; - break; - } - //Tracev((stderr, "inflate: stored end\n")); - state.mode = TYPE; - break; - case TABLE: - //=== NEEDBITS(14); */ - while (bits < 14) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; - //--- DROPBITS(5) ---// - hold >>>= 5; - bits -= 5; - //---// - state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; - //--- DROPBITS(4) ---// - hold >>>= 4; - bits -= 4; - //---// -//#ifndef PKZIP_BUG_WORKAROUND - if (state.nlen > 286 || state.ndist > 30) { - strm.msg = 'too many length or distance symbols'; - state.mode = BAD; - break; - } -//#endif - //Tracev((stderr, "inflate: table sizes ok\n")); - state.have = 0; - state.mode = LENLENS; - /* falls through */ - case LENLENS: - while (state.have < state.ncode) { - //=== NEEDBITS(3); - while (bits < 3) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - while (state.have < 19) { - state.lens[order[state.have++]] = 0; - } - // We have separate tables & no pointers. 2 commented lines below not needed. - //state.next = state.codes; - //state.lencode = state.next; - // Switch to use dynamic table - state.lencode = state.lendyn; - state.lenbits = 7; - - opts = {bits: state.lenbits}; - ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); - state.lenbits = opts.bits; - - if (ret) { - strm.msg = 'invalid code lengths set'; - state.mode = BAD; - break; - } - //Tracev((stderr, "inflate: code lengths ok\n")); - state.have = 0; - state.mode = CODELENS; - /* falls through */ - case CODELENS: - while (state.have < state.nlen + state.ndist) { - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_val < 16) { - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.lens[state.have++] = here_val; - } - else { - if (here_val === 16) { - //=== NEEDBITS(here.bits + 2); - n = here_bits + 2; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - if (state.have === 0) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - len = state.lens[state.have - 1]; - copy = 3 + (hold & 0x03);//BITS(2); - //--- DROPBITS(2) ---// - hold >>>= 2; - bits -= 2; - //---// - } - else if (here_val === 17) { - //=== NEEDBITS(here.bits + 3); - n = here_bits + 3; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 3 + (hold & 0x07);//BITS(3); - //--- DROPBITS(3) ---// - hold >>>= 3; - bits -= 3; - //---// - } - else { - //=== NEEDBITS(here.bits + 7); - n = here_bits + 7; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - len = 0; - copy = 11 + (hold & 0x7f);//BITS(7); - //--- DROPBITS(7) ---// - hold >>>= 7; - bits -= 7; - //---// - } - if (state.have + copy > state.nlen + state.ndist) { - strm.msg = 'invalid bit length repeat'; - state.mode = BAD; - break; - } - while (copy--) { - state.lens[state.have++] = len; - } - } - } - - /* handle error breaks in while */ - if (state.mode === BAD) { break; } - - /* check for end-of-block code (better have one) */ - if (state.lens[256] === 0) { - strm.msg = 'invalid code -- missing end-of-block'; - state.mode = BAD; - break; - } - - /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h - concerning the ENOUGH constants, which depend on those values */ - state.lenbits = 9; - - opts = {bits: state.lenbits}; - ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.lenbits = opts.bits; - // state.lencode = state.next; - - if (ret) { - strm.msg = 'invalid literal/lengths set'; - state.mode = BAD; - break; - } - - state.distbits = 6; - //state.distcode.copy(state.codes); - // Switch to use dynamic table - state.distcode = state.distdyn; - opts = {bits: state.distbits}; - ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); - // We have separate tables & no pointers. 2 commented lines below not needed. - // state.next_index = opts.table_index; - state.distbits = opts.bits; - // state.distcode = state.next; - - if (ret) { - strm.msg = 'invalid distances set'; - state.mode = BAD; - break; - } - //Tracev((stderr, 'inflate: codes ok\n')); - state.mode = LEN_; - if (flush === Z_TREES) { break inf_leave; } - /* falls through */ - case LEN_: - state.mode = LEN; - /* falls through */ - case LEN: - if (have >= 6 && left >= 258) { - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - inflate_fast(strm, _out); - //--- LOAD() --- - put = strm.next_out; - output = strm.output; - left = strm.avail_out; - next = strm.next_in; - input = strm.input; - have = strm.avail_in; - hold = state.hold; - bits = state.bits; - //--- - - if (state.mode === TYPE) { - state.back = -1; - } - break; - } - state.back = 0; - for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) -1)]; /*BITS(state.lenbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if (here_bits <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if (here_op && (here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - state.length = here_val; - if (here_op === 0) { - //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? - // "inflate: literal '%c'\n" : - // "inflate: literal 0x%02x\n", here.val)); - state.mode = LIT; - break; - } - if (here_op & 32) { - //Tracevv((stderr, "inflate: end of block\n")); - state.back = -1; - state.mode = TYPE; - break; - } - if (here_op & 64) { - strm.msg = 'invalid literal/length code'; - state.mode = BAD; - break; - } - state.extra = here_op & 15; - state.mode = LENEXT; - /* falls through */ - case LENEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.length += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } - //Tracevv((stderr, "inflate: length %u\n", state.length)); - state.was = state.length; - state.mode = DIST; - /* falls through */ - case DIST: - for (;;) { - here = state.distcode[hold & ((1 << state.distbits) -1)];/*BITS(state.distbits)*/ - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - if ((here_op & 0xf0) === 0) { - last_bits = here_bits; - last_op = here_op; - last_val = here_val; - for (;;) { - here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; - here_bits = here >>> 24; - here_op = (here >>> 16) & 0xff; - here_val = here & 0xffff; - - if ((last_bits + here_bits) <= bits) { break; } - //--- PULLBYTE() ---// - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - //---// - } - //--- DROPBITS(last.bits) ---// - hold >>>= last_bits; - bits -= last_bits; - //---// - state.back += last_bits; - } - //--- DROPBITS(here.bits) ---// - hold >>>= here_bits; - bits -= here_bits; - //---// - state.back += here_bits; - if (here_op & 64) { - strm.msg = 'invalid distance code'; - state.mode = BAD; - break; - } - state.offset = here_val; - state.extra = (here_op) & 15; - state.mode = DISTEXT; - /* falls through */ - case DISTEXT: - if (state.extra) { - //=== NEEDBITS(state.extra); - n = state.extra; - while (bits < n) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - state.offset += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; - //--- DROPBITS(state.extra) ---// - hold >>>= state.extra; - bits -= state.extra; - //---// - state.back += state.extra; - } -//#ifdef INFLATE_STRICT - if (state.offset > state.dmax) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -//#endif - //Tracevv((stderr, "inflate: distance %u\n", state.offset)); - state.mode = MATCH; - /* falls through */ - case MATCH: - if (left === 0) { break inf_leave; } - copy = _out - left; - if (state.offset > copy) { /* copy from window */ - copy = state.offset - copy; - if (copy > state.whave) { - if (state.sane) { - strm.msg = 'invalid distance too far back'; - state.mode = BAD; - break; - } -// (!) This block is disabled in zlib defailts, -// don't enable it for binary compatibility -//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR -// Trace((stderr, "inflate.c too far\n")); -// copy -= state.whave; -// if (copy > state.length) { copy = state.length; } -// if (copy > left) { copy = left; } -// left -= copy; -// state.length -= copy; -// do { -// output[put++] = 0; -// } while (--copy); -// if (state.length === 0) { state.mode = LEN; } -// break; -//#endif - } - if (copy > state.wnext) { - copy -= state.wnext; - from = state.wsize - copy; - } - else { - from = state.wnext - copy; - } - if (copy > state.length) { copy = state.length; } - from_source = state.window; - } - else { /* copy from output */ - from_source = output; - from = put - state.offset; - copy = state.length; - } - if (copy > left) { copy = left; } - left -= copy; - state.length -= copy; - do { - output[put++] = from_source[from++]; - } while (--copy); - if (state.length === 0) { state.mode = LEN; } - break; - case LIT: - if (left === 0) { break inf_leave; } - output[put++] = state.length; - left--; - state.mode = LEN; - break; - case CHECK: - if (state.wrap) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - // Use '|' insdead of '+' to make sure that result is signed - hold |= input[next++] << bits; - bits += 8; - } - //===// - _out -= left; - strm.total_out += _out; - state.total += _out; - if (_out) { - strm.adler = state.check = - /*UPDATE(state.check, put - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); - - } - _out = left; - // NB: crc32 stored as signed 32-bit int, ZSWAP32 returns signed too - if ((state.flags ? hold : ZSWAP32(hold)) !== state.check) { - strm.msg = 'incorrect data check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: check matches trailer\n")); - } - state.mode = LENGTH; - /* falls through */ - case LENGTH: - if (state.wrap && state.flags) { - //=== NEEDBITS(32); - while (bits < 32) { - if (have === 0) { break inf_leave; } - have--; - hold += input[next++] << bits; - bits += 8; - } - //===// - if (hold !== (state.total & 0xffffffff)) { - strm.msg = 'incorrect length check'; - state.mode = BAD; - break; - } - //=== INITBITS(); - hold = 0; - bits = 0; - //===// - //Tracev((stderr, "inflate: length matches trailer\n")); - } - state.mode = DONE; - /* falls through */ - case DONE: - ret = Z_STREAM_END; - break inf_leave; - case BAD: - ret = Z_DATA_ERROR; - break inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - /* falls through */ - default: - return Z_STREAM_ERROR; - } - } - - // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - - //--- RESTORE() --- - strm.next_out = put; - strm.avail_out = left; - strm.next_in = next; - strm.avail_in = have; - state.hold = hold; - state.bits = bits; - //--- - - if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && - (state.mode < CHECK || flush !== Z_FINISH))) { - if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { - state.mode = MEM; - return Z_MEM_ERROR; - } - } - _in -= strm.avail_in; - _out -= strm.avail_out; - strm.total_in += _in; - strm.total_out += _out; - state.total += _out; - if (state.wrap && _out) { - strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ - (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); - } - strm.data_type = state.bits + (state.last ? 64 : 0) + - (state.mode === TYPE ? 128 : 0) + - (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); - if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { - ret = Z_BUF_ERROR; - } - return ret; -} - -function inflateEnd(strm) { - - if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { - return Z_STREAM_ERROR; - } - - var state = strm.state; - if (state.window) { - state.window = null; - } - strm.state = null; - return Z_OK; -} - -function inflateGetHeader(strm, head) { - var state; - - /* check state */ - if (!strm || !strm.state) { return Z_STREAM_ERROR; } - state = strm.state; - if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } - - /* save header structure */ - state.head = head; - head.done = false; - return Z_OK; -} - - -exports.inflateReset = inflateReset; -exports.inflateReset2 = inflateReset2; -exports.inflateResetKeep = inflateResetKeep; -exports.inflateInit = inflateInit; -exports.inflateInit2 = inflateInit2; -exports.inflate = inflate; -exports.inflateEnd = inflateEnd; -exports.inflateGetHeader = inflateGetHeader; -exports.inflateInfo = 'pako inflate (from Nodeca project)'; - -/* Not implemented -exports.inflateCopy = inflateCopy; -exports.inflateGetDictionary = inflateGetDictionary; -exports.inflateMark = inflateMark; -exports.inflatePrime = inflatePrime; -exports.inflateSetDictionary = inflateSetDictionary; -exports.inflateSync = inflateSync; -exports.inflateSyncPoint = inflateSyncPoint; -exports.inflateUndermine = inflateUndermine; -*/ -},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(_dereq_,module,exports){ -'use strict'; - - -var utils = _dereq_('../utils/common'); - -var MAXBITS = 15; -var ENOUGH_LENS = 852; -var ENOUGH_DISTS = 592; -//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); - -var CODES = 0; -var LENS = 1; -var DISTS = 2; - -var lbase = [ /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 -]; - -var lext = [ /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 -]; - -var dbase = [ /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0 -]; - -var dext = [ /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64 -]; - -module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) -{ - var bits = opts.bits; - //here = opts.here; /* table entry for duplication */ - - var len = 0; /* a code's length in bits */ - var sym = 0; /* index of code symbols */ - var min = 0, max = 0; /* minimum and maximum code lengths */ - var root = 0; /* number of index bits for root table */ - var curr = 0; /* number of index bits for current table */ - var drop = 0; /* code bits to drop for sub-table */ - var left = 0; /* number of prefix codes available */ - var used = 0; /* code entries in table used */ - var huff = 0; /* Huffman code */ - var incr; /* for incrementing code, index */ - var fill; /* index for replicating entries */ - var low; /* low bits for current root entry */ - var mask; /* mask for low root bits */ - var next; /* next available space in table */ - var base = null; /* base value table to use */ - var base_index = 0; -// var shoextra; /* extra bits table to use */ - var end; /* use base and extra for symbol > end */ - var count = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* number of codes of each length */ - var offs = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* offsets in table for each length */ - var extra = null; - var extra_index = 0; - - var here_bits, here_op, here_val; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) { - count[len] = 0; - } - for (sym = 0; sym < codes; sym++) { - count[lens[lens_index + sym]]++; - } - - /* bound code lengths, force root to be within code lengths */ - root = bits; - for (max = MAXBITS; max >= 1; max--) { - if (count[max] !== 0) { break; } - } - if (root > max) { - root = max; - } - if (max === 0) { /* no symbols to code at all */ - //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ - //table.bits[opts.table_index] = 1; //here.bits = (var char)1; - //table.val[opts.table_index++] = 0; //here.val = (var short)0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - - //table.op[opts.table_index] = 64; - //table.bits[opts.table_index] = 1; - //table.val[opts.table_index++] = 0; - table[table_index++] = (1 << 24) | (64 << 16) | 0; - - opts.bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min < max; min++) { - if (count[min] !== 0) { break; } - } - if (root < min) { - root = min; - } - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) { - return -1; - } /* over-subscribed */ - } - if (left > 0 && (type === CODES || max !== 1)) { - return -1; /* incomplete set */ - } - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) { - offs[len + 1] = offs[len] + count[len]; - } - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) { - if (lens[lens_index + sym] !== 0) { - work[offs[lens[lens_index + sym]]++] = sym; - } - } - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked for LENS and DIST tables against - the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in - the initial root table size constants. See the comments in inftrees.h - for more information. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - // poor man optimization - use if-else instead of switch, - // to avoid deopts in old v8 - if (type === CODES) { - base = extra = work; /* dummy value--not used */ - end = 19; - } else if (type === LENS) { - base = lbase; - base_index -= 257; - extra = lext; - extra_index -= 257; - end = 256; - } else { /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize opts for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = table_index; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = -1; /* trigger new sub-table when len > root */ - used = 1 << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - var i=0; - /* process all codes and make table entries */ - for (;;) { - i++; - /* create table entry */ - here_bits = len - drop; - if (work[sym] < end) { - here_op = 0; - here_val = work[sym]; - } - else if (work[sym] > end) { - here_op = extra[extra_index + work[sym]]; - here_val = base[base_index + work[sym]]; - } - else { - here_op = 32 + 64; /* end of block */ - here_val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1 << (len - drop); - fill = 1 << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; - } while (fill !== 0); - - /* backwards increment the len-bit code huff */ - incr = 1 << (len - 1); - while (huff & incr) { - incr >>= 1; - } - if (incr !== 0) { - huff &= incr - 1; - huff += incr; - } else { - huff = 0; - } - - /* go to next symbol, update count, len */ - sym++; - if (--count[len] === 0) { - if (len === max) { break; } - len = lens[lens_index + work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) !== low) { - /* if first time, transition to sub-tables */ - if (drop === 0) { - drop = root; - } - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = 1 << curr; - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) { break; } - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1 << curr; - if ((type === LENS && used > ENOUGH_LENS) || - (type === DISTS && used > ENOUGH_DISTS)) { - return 1; - } - - /* point entry in root table to sub-table */ - low = huff & mask; - /*table.op[low] = curr; - table.bits[low] = root; - table.val[low] = next - opts.table_index;*/ - table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; - } - } - - /* fill in remaining table entry if code is incomplete (guaranteed to have - at most one remaining entry, since if the code is incomplete, the - maximum code length that was allowed to get this far is one bit) */ - if (huff !== 0) { - //table.op[next + huff] = 64; /* invalid code marker */ - //table.bits[next + huff] = len - drop; - //table.val[next + huff] = 0; - table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; - } - - /* set return parameters */ - //opts.table_index += used; - opts.bits = root; - return 0; -}; - -},{"../utils/common":27}],37:[function(_dereq_,module,exports){ -'use strict'; - -module.exports = { - '2': 'need dictionary', /* Z_NEED_DICT 2 */ - '1': 'stream end', /* Z_STREAM_END 1 */ - '0': '', /* Z_OK 0 */ - '-1': 'file error', /* Z_ERRNO (-1) */ - '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ - '-3': 'data error', /* Z_DATA_ERROR (-3) */ - '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ - '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ - '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ -}; -},{}],38:[function(_dereq_,module,exports){ -'use strict'; - - -var utils = _dereq_('../utils/common'); - -/* Public constants ==========================================================*/ -/* ===========================================================================*/ - - -//var Z_FILTERED = 1; -//var Z_HUFFMAN_ONLY = 2; -//var Z_RLE = 3; -var Z_FIXED = 4; -//var Z_DEFAULT_STRATEGY = 0; - -/* Possible values of the data_type field (though see inflate()) */ -var Z_BINARY = 0; -var Z_TEXT = 1; -//var Z_ASCII = 1; // = Z_TEXT -var Z_UNKNOWN = 2; - -/*============================================================================*/ - - -function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } - -// From zutil.h - -var STORED_BLOCK = 0; -var STATIC_TREES = 1; -var DYN_TREES = 2; -/* The three kinds of block type */ - -var MIN_MATCH = 3; -var MAX_MATCH = 258; -/* The minimum and maximum match lengths */ - -// From deflate.h -/* =========================================================================== - * Internal compression state. - */ - -var LENGTH_CODES = 29; -/* number of length codes, not counting the special END_BLOCK code */ - -var LITERALS = 256; -/* number of literal bytes 0..255 */ - -var L_CODES = LITERALS + 1 + LENGTH_CODES; -/* number of Literal or Length codes, including the END_BLOCK code */ - -var D_CODES = 30; -/* number of distance codes */ - -var BL_CODES = 19; -/* number of codes used to transfer the bit lengths */ - -var HEAP_SIZE = 2*L_CODES + 1; -/* maximum heap size */ - -var MAX_BITS = 15; -/* All codes must not exceed MAX_BITS bits */ - -var Buf_size = 16; -/* size of bit buffer in bi_buf */ - - -/* =========================================================================== - * Constants - */ - -var MAX_BL_BITS = 7; -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -var END_BLOCK = 256; -/* end of block literal code */ - -var REP_3_6 = 16; -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -var REPZ_3_10 = 17; -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -var REPZ_11_138 = 18; -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -var extra_lbits = /* extra bits for each length code */ - [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; - -var extra_dbits = /* extra bits for each distance code */ - [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; - -var extra_blbits = /* extra bits for each bit length code */ - [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; - -var bl_order = - [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -// We pre-fill arrays with 0 to avoid uninitialized gaps - -var DIST_CODE_LEN = 512; /* see definition of array dist_code below */ - -// !!!! Use flat array insdead of structure, Freq = i*2, Len = i*2+1 -var static_ltree = new Array((L_CODES+2) * 2); -zero(static_ltree); -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -var static_dtree = new Array(D_CODES * 2); -zero(static_dtree); -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -var _dist_code = new Array(DIST_CODE_LEN); -zero(_dist_code); -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -var _length_code = new Array(MAX_MATCH-MIN_MATCH+1); -zero(_length_code); -/* length code for each normalized match length (0 == MIN_MATCH) */ - -var base_length = new Array(LENGTH_CODES); -zero(base_length); -/* First normalized length for each code (0 = MIN_MATCH) */ - -var base_dist = new Array(D_CODES); -zero(base_dist); -/* First normalized distance for each code (0 = distance of 1) */ - - -var StaticTreeDesc = function (static_tree, extra_bits, extra_base, elems, max_length) { - - this.static_tree = static_tree; /* static tree or NULL */ - this.extra_bits = extra_bits; /* extra bits for each code or NULL */ - this.extra_base = extra_base; /* base index for extra_bits */ - this.elems = elems; /* max number of elements in the tree */ - this.max_length = max_length; /* max bit length for the codes */ - - // show if `static_tree` has data or dummy - needed for monomorphic objects - this.has_stree = static_tree && static_tree.length; -}; - - -var static_l_desc; -var static_d_desc; -var static_bl_desc; - - -var TreeDesc = function(dyn_tree, stat_desc) { - this.dyn_tree = dyn_tree; /* the dynamic tree */ - this.max_code = 0; /* largest code with non zero frequency */ - this.stat_desc = stat_desc; /* the corresponding static tree */ -}; - - - -function d_code(dist) { - return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; -} - - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -function put_short (s, w) { -// put_byte(s, (uch)((w) & 0xff)); -// put_byte(s, (uch)((ush)(w) >> 8)); - s.pending_buf[s.pending++] = (w) & 0xff; - s.pending_buf[s.pending++] = (w >>> 8) & 0xff; -} - - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -function send_bits(s, value, length) { - if (s.bi_valid > (Buf_size - length)) { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - put_short(s, s.bi_buf); - s.bi_buf = value >> (Buf_size - s.bi_valid); - s.bi_valid += length - Buf_size; - } else { - s.bi_buf |= (value << s.bi_valid) & 0xffff; - s.bi_valid += length; - } -} - - -function send_code(s, c, tree) { - send_bits(s, tree[c*2]/*.Code*/, tree[c*2 + 1]/*.Len*/); -} - - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -function bi_reverse(code, len) { - var res = 0; - do { - res |= code & 1; - code >>>= 1; - res <<= 1; - } while (--len > 0); - return res >>> 1; -} - - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -function bi_flush(s) { - if (s.bi_valid === 16) { - put_short(s, s.bi_buf); - s.bi_buf = 0; - s.bi_valid = 0; - - } else if (s.bi_valid >= 8) { - s.pending_buf[s.pending++] = s.bi_buf & 0xff; - s.bi_buf >>= 8; - s.bi_valid -= 8; - } -} - - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -function gen_bitlen(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - var tree = desc.dyn_tree; - var max_code = desc.max_code; - var stree = desc.stat_desc.static_tree; - var has_stree = desc.stat_desc.has_stree; - var extra = desc.stat_desc.extra_bits; - var base = desc.stat_desc.extra_base; - var max_length = desc.stat_desc.max_length; - var h; /* heap index */ - var n, m; /* iterate over the tree elements */ - var bits; /* bit length */ - var xbits; /* extra bits */ - var f; /* frequency */ - var overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) { - s.bl_count[bits] = 0; - } - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s.heap[s.heap_max]*2 + 1]/*.Len*/ = 0; /* root of the heap */ - - for (h = s.heap_max+1; h < HEAP_SIZE; h++) { - n = s.heap[h]; - bits = tree[tree[n*2 +1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; - if (bits > max_length) { - bits = max_length; - overflow++; - } - tree[n*2 + 1]/*.Len*/ = bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) { continue; } /* not a leaf node */ - - s.bl_count[bits]++; - xbits = 0; - if (n >= base) { - xbits = extra[n-base]; - } - f = tree[n * 2]/*.Freq*/; - s.opt_len += f * (bits + xbits); - if (has_stree) { - s.static_len += f * (stree[n*2 + 1]/*.Len*/ + xbits); - } - } - if (overflow === 0) { return; } - - // Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s.bl_count[bits] === 0) { bits--; } - s.bl_count[bits]--; /* move one leaf down the tree */ - s.bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits !== 0; bits--) { - n = s.bl_count[bits]; - while (n !== 0) { - m = s.heap[--h]; - if (m > max_code) { continue; } - if (tree[m*2 + 1]/*.Len*/ !== bits) { - // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s.opt_len += (bits - tree[m*2 + 1]/*.Len*/)*tree[m*2]/*.Freq*/; - tree[m*2 + 1]/*.Len*/ = bits; - } - n--; - } - } -} - - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -function gen_codes(tree, max_code, bl_count) -// ct_data *tree; /* the tree to decorate */ -// int max_code; /* largest code with non zero frequency */ -// ushf *bl_count; /* number of codes at each bit length */ -{ - var next_code = new Array(MAX_BITS+1); /* next code value for each bit length */ - var code = 0; /* running code value */ - var bits; /* bit index */ - var n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = code; - } - } - //Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) { - bl_count[bits] = 0; - } - - n = 0; - while (n <= 143) { - static_ltree[n*2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - while (n <= 255) { - static_ltree[n*2 + 1]/*.Len*/ = 9; - n++; - bl_count[9]++; - } - while (n <= 279) { - static_ltree[n*2 + 1]/*.Len*/ = 7; - n++; - bl_count[7]++; - } - while (n <= 287) { - static_ltree[n*2 + 1]/*.Len*/ = 8; - n++; - bl_count[8]++; - } - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n*2 + 1]/*.Len*/ = 5; - static_dtree[n*2]/*.Code*/ = bi_reverse(n, 5); - } - - // Now data ready and we can init static trees - static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS); - static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); - static_bl_desc =new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); - - //static_init_done = true; -} - - -/* =========================================================================== - * Initialize a new block. - */ -function init_block(s) { - var n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n*2]/*.Freq*/ = 0; } - for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n*2]/*.Freq*/ = 0; } - for (n = 0; n < BL_CODES; n++) { s.bl_tree[n*2]/*.Freq*/ = 0; } - - s.dyn_ltree[END_BLOCK*2]/*.Freq*/ = 1; - s.opt_len = s.static_len = 0; - s.last_lit = s.matches = 0; -} - - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -function bi_windup(s) -{ - if (s.bi_valid > 8) { - put_short(s, s.bi_buf); - } else if (s.bi_valid > 0) { - //put_byte(s, (Byte)s->bi_buf); - s.pending_buf[s.pending++] = s.bi_buf; - } - s.bi_buf = 0; - s.bi_valid = 0; -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -function copy_block(s, buf, len, header) -//DeflateState *s; -//charf *buf; /* the input data */ -//unsigned len; /* its length */ -//int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, len); - put_short(s, ~len); - } -// while (len--) { -// put_byte(s, *buf++); -// } - utils.arraySet(s.pending_buf, s.window, buf, len, s.pending); - s.pending += len; -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -function smaller(tree, n, m, depth) { - var _n2 = n*2; - var _m2 = m*2; - return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || - (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); -} - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -function pqdownheap(s, tree, k) -// deflate_state *s; -// ct_data *tree; /* the tree to restore */ -// int k; /* node to move down */ -{ - var v = s.heap[k]; - var j = k << 1; /* left son of k */ - while (j <= s.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s.heap_len && - smaller(tree, s.heap[j+1], s.heap[j], s.depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s.heap[j], s.depth)) { break; } - - /* Exchange v with the smallest son */ - s.heap[k] = s.heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s.heap[k] = v; -} - - -// inlined manually -// var SMALLEST = 1; - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -function compress_block(s, ltree, dtree) -// deflate_state *s; -// const ct_data *ltree; /* literal tree */ -// const ct_data *dtree; /* distance tree */ -{ - var dist; /* distance of matched string */ - var lc; /* match length or unmatched char (if dist == 0) */ - var lx = 0; /* running index in l_buf */ - var code; /* the code to send */ - var extra; /* number of extra bits to send */ - - if (s.last_lit !== 0) { - do { - dist = (s.pending_buf[s.d_buf + lx*2] << 8) | (s.pending_buf[s.d_buf + lx*2 + 1]); - lc = s.pending_buf[s.l_buf + lx]; - lx++; - - if (dist === 0) { - send_code(s, lc, ltree); /* send a literal byte */ - //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra !== 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - //Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra !== 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - // "pendingBuf overflow"); - - } while (lx < s.last_lit); - } - - send_code(s, END_BLOCK, ltree); -} - - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -function build_tree(s, desc) -// deflate_state *s; -// tree_desc *desc; /* the tree descriptor */ -{ - var tree = desc.dyn_tree; - var stree = desc.stat_desc.static_tree; - var has_stree = desc.stat_desc.has_stree; - var elems = desc.stat_desc.elems; - var n, m; /* iterate over heap elements */ - var max_code = -1; /* largest code with non zero frequency */ - var node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n * 2]/*.Freq*/ !== 0) { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - - } else { - tree[n*2 + 1]/*.Len*/ = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s.heap_len < 2) { - node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); - tree[node * 2]/*.Freq*/ = 1; - s.depth[node] = 0; - s.opt_len--; - - if (has_stree) { - s.static_len -= stree[node*2 + 1]/*.Len*/; - } - /* node is 0 or 1 so it does not have extra bits */ - } - desc.max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - //pqremove(s, tree, n); /* n = node of least frequency */ - /*** pqremove ***/ - n = s.heap[1/*SMALLEST*/]; - s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; - pqdownheap(s, tree, 1/*SMALLEST*/); - /***/ - - m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ - - s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ - s.heap[--s.heap_max] = m; - - /* Create a new node father of n and m */ - tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; - s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; - tree[n*2 + 1]/*.Dad*/ = tree[m*2 + 1]/*.Dad*/ = node; - - /* and insert the new node in the heap */ - s.heap[1/*SMALLEST*/] = node++; - pqdownheap(s, tree, 1/*SMALLEST*/); - - } while (s.heap_len >= 2); - - s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes(tree, max_code, s.bl_count); -} - - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -function scan_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - var n; /* iterates over all tree elements */ - var prevlen = -1; /* last emitted length */ - var curlen; /* length of current code */ - - var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */ - - var count = 0; /* repeat count of the current code */ - var max_count = 7; /* max repeat count */ - var min_count = 4; /* min repeat count */ - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - tree[(max_code+1)*2 + 1]/*.Len*/ = 0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n+1)*2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - s.bl_tree[curlen * 2]/*.Freq*/ += count; - - } else if (curlen !== 0) { - - if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } - s.bl_tree[REP_3_6*2]/*.Freq*/++; - - } else if (count <= 10) { - s.bl_tree[REPZ_3_10*2]/*.Freq*/++; - - } else { - s.bl_tree[REPZ_11_138*2]/*.Freq*/++; - } - - count = 0; - prevlen = curlen; - - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -function send_tree(s, tree, max_code) -// deflate_state *s; -// ct_data *tree; /* the tree to be scanned */ -// int max_code; /* and its largest code of non zero frequency */ -{ - var n; /* iterates over all tree elements */ - var prevlen = -1; /* last emitted length */ - var curlen; /* length of current code */ - - var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */ - - var count = 0; /* repeat count of the current code */ - var max_count = 7; /* max repeat count */ - var min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen === 0) { - max_count = 138; - min_count = 3; - } - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[(n+1)*2 + 1]/*.Len*/; - - if (++count < max_count && curlen === nextlen) { - continue; - - } else if (count < min_count) { - do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); - - } else if (curlen !== 0) { - if (curlen !== prevlen) { - send_code(s, curlen, s.bl_tree); - count--; - } - //Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s.bl_tree); - send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s.bl_tree); - send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s.bl_tree); - send_bits(s, count-11, 7); - } - - count = 0; - prevlen = curlen; - if (nextlen === 0) { - max_count = 138; - min_count = 3; - - } else if (curlen === nextlen) { - max_count = 6; - min_count = 3; - - } else { - max_count = 7; - min_count = 4; - } - } -} - - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -function build_bl_tree(s) { - var max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, s.dyn_ltree, s.l_desc.max_code); - scan_tree(s, s.dyn_dtree, s.d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, s.bl_desc); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s.bl_tree[bl_order[max_blindex]*2 + 1]/*.Len*/ !== 0) { - break; - } - } - /* Update opt_len to include the bit length tree and counts */ - s.opt_len += 3*(max_blindex+1) + 5+5+4; - //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - // s->opt_len, s->static_len)); - - return max_blindex; -} - - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -function send_all_trees(s, lcodes, dcodes, blcodes) -// deflate_state *s; -// int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - var rank; /* index in bl_order */ - - //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - // "too many codes"); - //Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s.bl_tree[bl_order[rank]*2 + 1]/*.Len*/, 3); - } - //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_ltree, lcodes-1); /* literal tree */ - //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, s.dyn_dtree, dcodes-1); /* distance tree */ - //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - - -/* =========================================================================== - * Check if the data type is TEXT or BINARY, using the following algorithm: - * - TEXT if the two conditions below are satisfied: - * a) There are no non-portable control characters belonging to the - * "black list" (0..6, 14..25, 28..31). - * b) There is at least one printable character belonging to the - * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - * - BINARY otherwise. - * - The following partially-portable control characters form a - * "gray list" that is ignored in this detection algorithm: - * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). - * IN assertion: the fields Freq of dyn_ltree are set. - */ -function detect_data_type(s) { - /* black_mask is the bit mask of black-listed bytes - * set bits 0..6, 14..25, and 28..31 - * 0xf3ffc07f = binary 11110011111111111100000001111111 - */ - var black_mask = 0xf3ffc07f; - var n; - - /* Check for non-textual ("black-listed") bytes. */ - for (n = 0; n <= 31; n++, black_mask >>>= 1) { - if ((black_mask & 1) && (s.dyn_ltree[n*2]/*.Freq*/ !== 0)) { - return Z_BINARY; - } - } - - /* Check for textual ("white-listed") bytes. */ - if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || - s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - for (n = 32; n < LITERALS; n++) { - if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { - return Z_TEXT; - } - } - - /* There are no "black-listed" or "white-listed" bytes: - * this stream either is empty or has tolerated ("gray-listed") bytes only. - */ - return Z_BINARY; -} - - -var static_init_done = false; - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -function _tr_init(s) -{ - - if (!static_init_done) { - tr_static_init(); - static_init_done = true; - } - - s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); - s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); - s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); - - s.bi_buf = 0; - s.bi_valid = 0; - - /* Initialize the first block of the first file: */ - init_block(s); -} - - -/* =========================================================================== - * Send a stored block - */ -function _tr_stored_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+(last ? 1 : 0), 3); /* send block type */ - copy_block(s, buf, stored_len, true); /* with header */ -} - - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - */ -function _tr_align(s) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); - bi_flush(s); -} - - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -function _tr_flush_block(s, buf, stored_len, last) -//DeflateState *s; -//charf *buf; /* input block, or NULL if too old */ -//ulg stored_len; /* length of input block */ -//int last; /* one if this is the last block for a file */ -{ - var opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - var max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s.level > 0) { - - /* Check if the file is binary or text */ - if (s.strm.data_type === Z_UNKNOWN) { - s.strm.data_type = detect_data_type(s); - } - - /* Construct the literal and distance trees */ - build_tree(s, s.l_desc); - // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - - build_tree(s, s.d_desc); - // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - // s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s.opt_len+3+7) >>> 3; - static_lenb = (s.static_len+3+7) >>> 3; - - // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - // s->last_lit)); - - if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } - - } else { - // Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - - if ((stored_len+4 <= opt_lenb) && (buf !== -1)) { - /* 4: two words for the lengths */ - - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, last); - - } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { - - send_bits(s, (STATIC_TREES<<1) + (last ? 1 : 0), 3); - compress_block(s, static_ltree, static_dtree); - - } else { - send_bits(s, (DYN_TREES<<1) + (last ? 1 : 0), 3); - send_all_trees(s, s.l_desc.max_code+1, s.d_desc.max_code+1, max_blindex+1); - compress_block(s, s.dyn_ltree, s.dyn_dtree); - } - // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (last) { - bi_windup(s); - } - // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - // s->compressed_len-7*last)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -function _tr_tally(s, dist, lc) -// deflate_state *s; -// unsigned dist; /* distance of matched string */ -// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - //var out_length, in_length, dcode; - - s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff; - s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; - - s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; - s.last_lit++; - - if (dist === 0) { - /* lc is the unmatched char */ - s.dyn_ltree[lc*2]/*.Freq*/++; - } else { - s.matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - //Assert((ush)dist < (ush)MAX_DIST(s) && - // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s.dyn_ltree[(_length_code[lc]+LITERALS+1) * 2]/*.Freq*/++; - s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; - } - -// (!) This block is disabled in zlib defailts, -// don't enable it for binary compatibility - -//#ifdef TRUNCATE_BLOCK -// /* Try to guess if it is profitable to stop the current block here */ -// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { -// /* Compute an upper bound for the compressed length */ -// out_length = s.last_lit*8; -// in_length = s.strstart - s.block_start; -// -// for (dcode = 0; dcode < D_CODES; dcode++) { -// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); -// } -// out_length >>>= 3; -// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", -// // s->last_lit, in_length, out_length, -// // 100L - out_length*100L/in_length)); -// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { -// return true; -// } -// } -//#endif - - return (s.last_lit === s.lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -exports._tr_init = _tr_init; -exports._tr_stored_block = _tr_stored_block; -exports._tr_flush_block = _tr_flush_block; -exports._tr_tally = _tr_tally; -exports._tr_align = _tr_align; -},{"../utils/common":27}],39:[function(_dereq_,module,exports){ -'use strict'; - - -function ZStream() { - /* next input byte */ - this.input = null; // JS specific, because we have no pointers - this.next_in = 0; - /* number of bytes available at input */ - this.avail_in = 0; - /* total number of input bytes read so far */ - this.total_in = 0; - /* next output byte should be put there */ - this.output = null; // JS specific, because we have no pointers - this.next_out = 0; - /* remaining free space at output */ - this.avail_out = 0; - /* total number of bytes output so far */ - this.total_out = 0; - /* last error message, NULL if no error */ - this.msg = ''/*Z_NULL*/; - /* not visible by applications */ - this.state = null; - /* best guess about the data type: binary or text */ - this.data_type = 2/*Z_UNKNOWN*/; - /* adler32 value of the uncompressed data */ - this.adler = 0; -} - -module.exports = ZStream; -},{}]},{},[9]) -(9) -}); \ No newline at end of file diff --git a/cps/static/js/compress/jszip.min.js b/cps/static/js/compress/jszip.min.js new file mode 100644 index 00000000..3b36cd8b --- /dev/null +++ b/cps/static/js/compress/jszip.min.js @@ -0,0 +1,14 @@ +/*! + +JSZip - A Javascript class for generating and reading zip files + + +(c) 2009-2014 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE +*/ +!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f-this.zero;return-1},d.prototype.readData=function(a){if(this.checkOffset(a),0===a)return[];var b=this.data.slice(this.zero+this.index,this.zero+this.index+a);return this.index+=a,b},b.exports=d},{"./dataReader":6}],2:[function(a,b,c){"use strict";var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";c.encode=function(a,b){for(var c,e,f,g,h,i,j,k="",l=0;l>2,h=(3&c)<<4|e>>4,i=(15&e)<<2|f>>6,j=63&f,isNaN(e)?i=j=64:isNaN(f)&&(j=64),k=k+d.charAt(g)+d.charAt(h)+d.charAt(i)+d.charAt(j);return k},c.decode=function(a,b){var c,e,f,g,h,i,j,k="",l=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");l>4,e=(15&h)<<4|i>>2,f=(3&i)<<6|j,k+=String.fromCharCode(c),64!=i&&(k+=String.fromCharCode(e)),64!=j&&(k+=String.fromCharCode(f));return k}},{}],3:[function(a,b,c){"use strict";function d(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}d.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=d},{}],4:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a,b){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":9}],5:[function(a,b,c){"use strict";var d=a("./utils"),e=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var c="string"!==d.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=c?a[i]:a.charCodeAt(i),g=255&(b^h),f=e[g],b=b>>>8^f;return-1^b}},{"./utils":22}],6:[function(a,b,c){"use strict";function d(a){this.data=null,this.length=0,this.index=0,this.zero=0}var e=a("./utils");d.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.lengtha)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(a){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return e.transformTo("string",this.readData(a))},readData:function(a){},lastIndexOfSignature:function(a){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=d},{"./utils":22}],7:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.compressionOptions=null,c.comment=null,c.unixPermissions=null,c.dosPermissions=null},{}],8:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":22}],9:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a,b){return e.deflateRaw(a,{level:b.level||-1})},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:25}],10:[function(a,b,c){"use strict";function d(a,b){return this instanceof d?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new d;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new d(a,b)}var e=a("./base64");d.prototype=a("./object"),d.prototype.load=a("./load"),d.support=a("./support"),d.defaults=a("./defaults"),d.utils=a("./deprecatedPublicUtils"),d.base64={encode:function(a){return e.encode(a)},decode:function(a){return e.decode(a)}},d.compressions=a("./compressions"),b.exports=d},{"./base64":2,"./compressions":4,"./defaults":7,"./deprecatedPublicUtils":8,"./load":11,"./object":14,"./support":18}],11:[function(a,b,c){"use strict";var d=a("./base64"),e=a("./utf8"),f=a("./utils"),g=a("./zipEntries");b.exports=function(a,b){var c,h,i,j;for(b=f.extend(b||{},{base64:!1,checkCRC32:!1,optimizedBinaryString:!1,createFolders:!1,decodeFileName:e.utf8decode}),b.base64&&(a=d.decode(a)),h=new g(a,b),c=h.files,i=0;ic;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},u=function(a){return a=a||{},a.base64!==!0||null!==a.binary&&void 0!==a.binary||(a.binary=!0),a=e.extend(a,h),a.date=a.date||new Date,null!==a.compression&&(a.compression=a.compression.toUpperCase()),a},v=function(a,b,c){var d,f=e.getTypeOf(b);if(c=u(c),"string"==typeof c.unixPermissions&&(c.unixPermissions=parseInt(c.unixPermissions,8)),c.unixPermissions&&16384&c.unixPermissions&&(c.dir=!0),c.dosPermissions&&16&c.dosPermissions&&(c.dir=!0),c.dir&&(a=x(a)),c.createFolders&&(d=w(a))&&y.call(this,d,!0),c.dir||null===b||"undefined"==typeof b)c.base64=!1,c.binary=!1,b=null,f=null;else if("string"===f)c.binary&&!c.base64&&c.optimizedBinaryString!==!0&&(b=e.string2binary(b));else{if(c.base64=!1,c.binary=!0,!(f||b instanceof k))throw new Error("The data of '"+a+"' is in an unsupported format !");"arraybuffer"===f&&(b=e.transformTo("uint8array",b))}var g=new s(a,b,c);return this.files[a]=g,g},w=function(a){"/"==a.slice(-1)&&(a=a.substring(0,a.length-1));var b=a.lastIndexOf("/");return b>0?a.substring(0,b):""},x=function(a){return"/"!=a.slice(-1)&&(a+="/"),a},y=function(a,b){return b="undefined"!=typeof b?b:!1,a=x(a),this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},z=function(a,b,c){var d,g=new k;return a._data instanceof k?(g.uncompressedSize=a._data.uncompressedSize,g.crc32=a._data.crc32,0===g.uncompressedSize||a.dir?(b=j.STORE,g.compressedContent="",g.crc32=0):a._data.compressionMethod===b.magic?g.compressedContent=a._data.getCompressedContent():(d=a._data.getContent(),g.compressedContent=b.compress(e.transformTo(b.compressInputType,d),c))):(d=q(a),d&&0!==d.length&&!a.dir||(b=j.STORE,d=""),g.uncompressedSize=d.length,g.crc32=f(d),g.compressedContent=b.compress(e.transformTo(b.compressInputType,d),c)),g.compressedSize=g.compressedContent.length,g.compressionMethod=b.magic,g},A=function(a,b){var c=a;return a||(c=b?16893:33204),(65535&c)<<16},B=function(a,b){return 63&(a||0)},C=function(a,b,c,d,h,i){var j,k,l,n,o=(c.compressedContent,i!==m.utf8encode),p=e.transformTo("string",i(b.name)),q=e.transformTo("string",m.utf8encode(b.name)),r=b.comment||"",s=e.transformTo("string",i(r)),u=e.transformTo("string",m.utf8encode(r)),v=q.length!==b.name.length,w=u.length!==r.length,x=b.options,y="",z="",C="";l=b._initialMetadata.dir!==b.dir?b.dir:x.dir,n=b._initialMetadata.date!==b.date?b.date:x.date;var D=0,E=0;l&&(D|=16),"UNIX"===h?(E=798,D|=A(b.unixPermissions,l)):(E=20,D|=B(b.dosPermissions,l)),j=n.getHours(),j<<=6,j|=n.getMinutes(),j<<=5,j|=n.getSeconds()/2,k=n.getFullYear()-1980,k<<=4,k|=n.getMonth()+1,k<<=5,k|=n.getDate(),v&&(z=t(1,1)+t(f(p),4)+q,y+="up"+t(z.length,2)+z),w&&(C=t(1,1)+t(this.crc32(s),4)+u,y+="uc"+t(C.length,2)+C);var F="";F+="\n\x00",F+=o||!v&&!w?"\x00\x00":"\x00\b",F+=c.compressionMethod,F+=t(j,2),F+=t(k,2),F+=t(c.crc32,4),F+=t(c.compressedSize,4),F+=t(c.uncompressedSize,4),F+=t(p.length,2),F+=t(y.length,2);var G=g.LOCAL_FILE_HEADER+F+p+y,H=g.CENTRAL_FILE_HEADER+t(E,2)+F+t(s.length,2)+"\x00\x00\x00\x00"+t(D,4)+t(d,4)+p+y+s;return{fileRecord:G,dirRecord:H,compressedObject:c}},D={load:function(a,b){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,f,g=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],f=new s(d.name,d._data,e.extend(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,f)&&g.push(f));return g},file:function(a,b,c){if(1===arguments.length){if(e.isRegExp(a)){var d=a;return this.filter(function(a,b){return!b.dir&&d.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(e.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=y.call(this,b),d=this.clone();return d.root=c.name,d},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;dh;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));e.uint8array?b.push(k(a.subarray(c,h))):b.push(k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":12,"./support":18,"./utils":22}],22:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;cg&&b>1;)try{"array"===f||"nodebuffer"===f?d.push(String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e)))):d.push(String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;cb?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)},c.extend=function(){var a,b,c={};for(a=0;ae;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;aa){var b=!this.isSignature(0,j.LOCAL_FILE_HEADER);throw b?new Error("Can't find end of central directory : is this a zip file ? If it is, see http://stuk.github.io/jszip/documentation/howto/read_zip.html"):new Error("Corrupted zip : can't find end of central directory")}this.reader.setIndex(a);var c=a;if(this.checkSignature(j.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===i.MAX_VALUE_16BITS||this.diskWithCentralDirStart===i.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===i.MAX_VALUE_16BITS||this.centralDirRecords===i.MAX_VALUE_16BITS||this.centralDirSize===i.MAX_VALUE_32BITS||this.centralDirOffset===i.MAX_VALUE_32BITS){if(this.zip64=!0,a=this.reader.lastIndexOfSignature(j.ZIP64_CENTRAL_DIRECTORY_LOCATOR),0>a)throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");if(this.reader.setIndex(a),this.checkSignature(j.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),!this.isSignature(this.relativeOffsetEndOfZip64CentralDir,j.ZIP64_CENTRAL_DIRECTORY_END)&&(this.relativeOffsetEndOfZip64CentralDir=this.reader.lastIndexOfSignature(j.ZIP64_CENTRAL_DIRECTORY_END),this.relativeOffsetEndOfZip64CentralDir<0))throw new Error("Corrupted zip : can't find the ZIP64 end of central directory");this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(j.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}var d=this.centralDirOffset+this.centralDirSize;this.zip64&&(d+=20,d+=12+this.zip64EndOfCentralSize);var e=c-d;if(e>0)this.isSignature(c,j.CENTRAL_FILE_HEADER)||(this.reader.zero=e);else if(0>e)throw new Error("Corrupted zip: missing "+Math.abs(e)+" bytes.")},prepareReader:function(a){var b=i.getTypeOf(a);if(i.checkSupport(b),"string"!==b||l.uint8array)if("nodebuffer"===b)this.reader=new f(a);else if(l.uint8array)this.reader=new g(i.transformTo("uint8array",a));else{if(!l.array)throw new Error("Unexpected error: unsupported type '"+b+"'");this.reader=new h(i.transformTo("array",a))}else this.reader=new e(a,this.loadOptions.optimizedBinaryString)},load:function(a){this.prepareReader(a),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},b.exports=d},{"./arrayReader":1,"./nodeBufferReader":13,"./object":14,"./signature":15,"./stringReader":16,"./support":18,"./uint8ArrayReader":19,"./utils":22,"./zipEntry":24}],24:[function(a,b,c){"use strict";function d(a,b){this.options=a,this.loadOptions=b}var e=a("./stringReader"),f=a("./utils"),g=a("./compressedObject"),h=a("./object"),i=a("./support"),j=0,k=3;d.prototype={isEncrypted:function(){return 1===(1&this.bitFlag)},useUTF8:function(){return 2048===(2048&this.bitFlag)},prepareCompressedContent:function(a,b,c){return function(){var d=a.index;a.setIndex(b);var e=a.readData(c);return a.setIndex(d),e}},prepareContent:function(a,b,c,d,e){return function(){var a=f.transformTo(d.uncompressInputType,this.getCompressedContent()),b=d.uncompress(a);if(b.length!==e)throw new Error("Bug : uncompressed data size mismatch");return b}},readLocalPart:function(a){var b,c;if(a.skip(22),this.fileNameLength=a.readInt(2),c=a.readInt(2),this.fileName=a.readData(this.fileNameLength),a.skip(c),-1==this.compressedSize||-1==this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory (compressedSize == -1 || uncompressedSize == -1)");if(b=f.findCompression(this.compressionMethod),null===b)throw new Error("Corrupted zip : compression "+f.pretty(this.compressionMethod)+" unknown (inner file : "+f.transformTo("string",this.fileName)+")");if(this.decompressed=new g,this.decompressed.compressedSize=this.compressedSize,this.decompressed.uncompressedSize=this.uncompressedSize,this.decompressed.crc32=this.crc32,this.decompressed.compressionMethod=this.compressionMethod,this.decompressed.getCompressedContent=this.prepareCompressedContent(a,a.index,this.compressedSize,b),this.decompressed.getContent=this.prepareContent(a,a.index,this.compressedSize,b,this.uncompressedSize),this.loadOptions.checkCRC32&&(this.decompressed=f.transformTo("string",this.decompressed.getContent()), +h.crc32(this.decompressed)!==this.crc32))throw new Error("Corrupted zip : CRC32 mismatch")},readCentralPart:function(a){if(this.versionMadeBy=a.readInt(2),this.versionNeeded=a.readInt(2),this.bitFlag=a.readInt(2),this.compressionMethod=a.readString(2),this.date=a.readDate(),this.crc32=a.readInt(4),this.compressedSize=a.readInt(4),this.uncompressedSize=a.readInt(4),this.fileNameLength=a.readInt(2),this.extraFieldsLength=a.readInt(2),this.fileCommentLength=a.readInt(2),this.diskNumberStart=a.readInt(2),this.internalFileAttributes=a.readInt(2),this.externalFileAttributes=a.readInt(4),this.localHeaderOffset=a.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");this.fileName=a.readData(this.fileNameLength),this.readExtraFields(a),this.parseZIP64ExtraField(a),this.fileComment=a.readData(this.fileCommentLength)},processAttributes:function(){this.unixPermissions=null,this.dosPermissions=null;var a=this.versionMadeBy>>8;this.dir=!!(16&this.externalFileAttributes),a===j&&(this.dosPermissions=63&this.externalFileAttributes),a===k&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(a){if(this.extraFields[1]){var b=new e(this.extraFields[1].value);this.uncompressedSize===f.MAX_VALUE_32BITS&&(this.uncompressedSize=b.readInt(8)),this.compressedSize===f.MAX_VALUE_32BITS&&(this.compressedSize=b.readInt(8)),this.localHeaderOffset===f.MAX_VALUE_32BITS&&(this.localHeaderOffset=b.readInt(8)),this.diskNumberStart===f.MAX_VALUE_32BITS&&(this.diskNumberStart=b.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new l,this.strm.avail_out=0;var c=h.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==p)throw new Error(k[c]);b.header&&h.deflateSetHeader(this.strm,b.header)}function e(a,b){var c=new d(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function f(a,b){return b=b||{},b.raw=!0,e(a,b)}function g(a,b){return b=b||{},b.gzip=!0,e(a,b)}var h=a("./zlib/deflate"),i=a("./utils/common"),j=a("./utils/strings"),k=a("./zlib/messages"),l=a("./zlib/zstream"),m=Object.prototype.toString,n=0,o=4,p=0,q=1,r=2,s=-1,t=0,u=8;d.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?o:n,"string"==typeof a?e.input=j.string2buf(a):"[object ArrayBuffer]"===m.call(a)?e.input=new Uint8Array(a):e.input=a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new i.Buf8(f),e.next_out=0,e.avail_out=f),c=h.deflate(e,d),c!==q&&c!==p)return this.onEnd(c),this.ended=!0,!1;0!==e.avail_out&&(0!==e.avail_in||d!==o&&d!==r)||("string"===this.options.to?this.onData(j.buf2binstring(i.shrinkBuf(e.output,e.next_out))):this.onData(i.shrinkBuf(e.output,e.next_out)))}while((e.avail_in>0||0===e.avail_out)&&c!==q);return d===o?(c=h.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===p):d===r?(this.onEnd(p),e.avail_out=0,!0):!0},d.prototype.onData=function(a){this.chunks.push(a)},d.prototype.onEnd=function(a){a===p&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=i.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=d,c.deflate=e,c.deflateRaw=f,c.gzip=g},{"./utils/common":28,"./utils/strings":29,"./zlib/deflate":33,"./zlib/messages":38,"./zlib/zstream":40}],27:[function(a,b,c){"use strict";function d(a){if(!(this instanceof d))return new d(a);this.options=h.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new l,this.strm.avail_out=0;var c=g.inflateInit2(this.strm,b.windowBits);if(c!==j.Z_OK)throw new Error(k[c]);this.header=new m,g.inflateGetHeader(this.strm,this.header)}function e(a,b){var c=new d(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function f(a,b){return b=b||{},b.raw=!0,e(a,b)}var g=a("./zlib/inflate"),h=a("./utils/common"),i=a("./utils/strings"),j=a("./zlib/constants"),k=a("./zlib/messages"),l=a("./zlib/zstream"),m=a("./zlib/gzheader"),n=Object.prototype.toString;d.prototype.push=function(a,b){var c,d,e,f,k,l=this.strm,m=this.options.chunkSize,o=!1;if(this.ended)return!1;d=b===~~b?b:b===!0?j.Z_FINISH:j.Z_NO_FLUSH,"string"==typeof a?l.input=i.binstring2buf(a):"[object ArrayBuffer]"===n.call(a)?l.input=new Uint8Array(a):l.input=a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new h.Buf8(m),l.next_out=0,l.avail_out=m),c=g.inflate(l,j.Z_NO_FLUSH),c===j.Z_BUF_ERROR&&o===!0&&(c=j.Z_OK,o=!1),c!==j.Z_STREAM_END&&c!==j.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0!==l.avail_out&&c!==j.Z_STREAM_END&&(0!==l.avail_in||d!==j.Z_FINISH&&d!==j.Z_SYNC_FLUSH)||("string"===this.options.to?(e=i.utf8border(l.output,l.next_out),f=l.next_out-e,k=i.buf2string(l.output,e),l.next_out=f,l.avail_out=m-f,f&&h.arraySet(l.output,l.output,e,f,0),this.onData(k)):this.onData(h.shrinkBuf(l.output,l.next_out)))),0===l.avail_in&&0===l.avail_out&&(o=!0)}while((l.avail_in>0||0===l.avail_out)&&c!==j.Z_STREAM_END);return c===j.Z_STREAM_END&&(d=j.Z_FINISH),d===j.Z_FINISH?(c=g.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===j.Z_OK):d===j.Z_SYNC_FLUSH?(this.onEnd(j.Z_OK),l.avail_out=0,!0):!0},d.prototype.onData=function(a){this.chunks.push(a)},d.prototype.onEnd=function(a){a===j.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=d,c.inflate=e,c.inflateRaw=f,c.ungzip=e},{"./utils/common":28,"./utils/strings":29,"./zlib/constants":31,"./zlib/gzheader":34,"./zlib/inflate":36,"./zlib/messages":38,"./zlib/zstream":40}],28:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],29:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":28}],30:[function(a,b,c){"use strict";function d(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=d},{}],31:[function(a,b,c){"use strict";b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],32:[function(a,b,c){"use strict";function d(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function e(a,b,c,d){var e=f,g=d+c;a^=-1;for(var h=d;g>h;h++)a=a>>>8^e[255&(a^b[h])];return-1^a}var f=d();b.exports=e},{}],33:[function(a,b,c){"use strict";function d(a,b){return a.msg=H[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(D.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){E._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,D.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=F(a.adler,b,e,c):2===a.state.wrap&&(a.adler=G(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-ka?a.strstart-(a.w_size-ka):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ja,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ja-(m-f),f=m-ja,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-ka)){D.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=ia)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===I)return ta;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return ta;if(a.strstart-a.block_start>=a.w_size-ka&&(h(a,!1),0===a.strm.avail_out))return ta}return a.insert=0,b===L?(h(a,!0),0===a.strm.avail_out?va:wa):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?ta:ta}function o(a,b){for(var c,d;;){if(a.lookahead=ia&&(a.ins_h=(a.ins_h<=ia)if(d=E._tr_tally(a,a.strstart-a.match_start,a.match_length-ia),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=ia){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<=ia&&(a.ins_h=(a.ins_h<4096)&&(a.match_length=ia-1)),a.prev_length>=ia&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-ia,d=E._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-ia),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<=ia&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ja;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ja-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=ia?(c=E._tr_tally(a,1,a.match_length-ia),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=E._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return ta}return a.insert=0,b===L?(h(a,!0),0===a.strm.avail_out?va:wa):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?ta:ua}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===I)return ta;break}if(a.match_length=0,c=E._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return ta}return a.insert=0,b===L?(h(a,!0),0===a.strm.avail_out?va:wa):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?ta:ua}function s(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e}function t(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=C[a.level].max_lazy,a.good_match=C[a.level].good_length,a.nice_match=C[a.level].nice_length,a.max_chain_length=C[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=ia-1,a.match_available=0,a.ins_h=0}function u(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Z,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new D.Buf16(2*ga),this.dyn_dtree=new D.Buf16(2*(2*ea+1)),this.bl_tree=new D.Buf16(2*(2*fa+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new D.Buf16(ha+1),this.heap=new D.Buf16(2*da+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new D.Buf16(2*da+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function v(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=Y,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?ma:ra,a.adler=2===b.wrap?0:1,b.last_flush=I,E._tr_init(b),N):d(a,P)}function w(a){var b=v(a);return b===N&&t(a.state),b}function x(a,b){return a&&a.state?2!==a.state.wrap?P:(a.state.gzhead=b,N):P}function y(a,b,c,e,f,g){if(!a)return P;var h=1;if(b===S&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>$||c!==Z||8>e||e>15||0>b||b>9||0>g||g>W)return d(a,P);8===e&&(e=9);var i=new u;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,w(a)}function z(a,b){return y(a,b,Z,_,aa,X)}function A(a,b){var c,h,k,l;if(!a||!a.state||b>M||0>b)return a?d(a,P):P;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===sa&&b!==L)return d(a,0===a.avail_out?R:P);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===ma)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=U||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=G(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=na):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=U||h.level<2?4:0),i(h,xa),h.status=ra);else{var m=Z+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=U||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=la),m+=31-m%31,h.status=ra,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===na)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=G(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=G(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=oa)}else h.status=oa;if(h.status===oa)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=G(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=G(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=pa)}else h.status=pa;if(h.status===pa)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=G(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=G(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=qa)}else h.status=qa;if(h.status===qa&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=ra)):h.status=ra),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,N}else if(0===a.avail_in&&e(b)<=e(c)&&b!==L)return d(a,R);if(h.status===sa&&0!==a.avail_in)return d(a,R);if(0!==a.avail_in||0!==h.lookahead||b!==I&&h.status!==sa){var o=h.strategy===U?r(h,b):h.strategy===V?q(h,b):C[h.level].func(h,b);if(o!==va&&o!==wa||(h.status=sa),o===ta||o===va)return 0===a.avail_out&&(h.last_flush=-1),N;if(o===ua&&(b===J?E._tr_align(h):b!==M&&(E._tr_stored_block(h,0,0,!1),b===K&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,N}return b!==L?N:h.wrap<=0?O:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?N:O)}function B(a){var b;return a&&a.state?(b=a.state.status,b!==ma&&b!==na&&b!==oa&&b!==pa&&b!==qa&&b!==ra&&b!==sa?d(a,P):(a.state=null,b===ra?d(a,Q):N)):P}var C,D=a("../utils/common"),E=a("./trees"),F=a("./adler32"),G=a("./crc32"),H=a("./messages"),I=0,J=1,K=3,L=4,M=5,N=0,O=1,P=-2,Q=-3,R=-5,S=-1,T=1,U=2,V=3,W=4,X=0,Y=2,Z=8,$=9,_=15,aa=8,ba=29,ca=256,da=ca+1+ba,ea=30,fa=19,ga=2*da+1,ha=15,ia=3,ja=258,ka=ja+ia+1,la=32,ma=42,na=69,oa=73,pa=91,qa=103,ra=113,sa=666,ta=1,ua=2,va=3,wa=4,xa=3;C=[new s(0,0,0,0,n),new s(4,4,8,4,o),new s(4,5,16,8,o),new s(4,6,32,32,o),new s(4,4,16,16,p),new s(8,16,32,32,p),new s(8,16,128,128,p),new s(8,32,128,256,p),new s(32,128,258,1024,p),new s(32,258,258,4096,p)],c.deflateInit=z,c.deflateInit2=y,c.deflateReset=w,c.deflateResetKeep=v,c.deflateSetHeader=x,c.deflate=A,c.deflateEnd=B,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":28,"./adler32":30,"./crc32":32,"./messages":38,"./trees":39}],34:[function(a,b,c){"use strict";function d(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=d},{}],35:[function(a,b,c){"use strict";var d=30,e=12;b.exports=function(a,b){var c,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;c=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=c.dmax,l=c.wsize,m=c.whave,n=c.wnext,o=c.window,p=c.hold,q=c.bits,r=c.lencode,s=c.distcode,t=(1<q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<q&&(p+=B[f++]<>>=w,q-=w),15>q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<q&&(p+=B[f++]<q&&(p+=B[f++]<k){a.msg="invalid distance too far back",c.mode=d;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&c.sane){a.msg="invalid distance too far back",c.mode=d;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),c.hold=p,c.bits=q}},{}],36:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(oa),b.distcode=b.distdyn=new r.Buf32(pa),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,ra)}function k(a){if(sa){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sa=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whaven;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=la;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=la;break}if(m>>>=4,n-=4,wa=(15&m)+8,0===c.wbits)c.wbits=wa;else if(wa>c.wbits){a.msg="invalid window size",c.mode=la;break}c.dmax=1<n;){if(0===i)break a;i--,m+=e[g++]<>8&1),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,Ba[2]=m>>>16&255,Ba[3]=m>>>24&255,c.check=t(c.check,Ba,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>8),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wa=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wa)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.name+=String.fromCharCode(wa));while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.comment+=String.fromCharCode(wa));while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){ +if(0===i)break a;i--,m+=e[g++]<>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>=7&n,n-=7&n,c.mode=ia;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=ba,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=la}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<>>16^65535)){a.msg="invalid stored block lengths",c.mode=la;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=la;break}c.have=0,c.mode=_;case _:for(;c.haven;){if(0===i)break a;i--,m+=e[g++]<>>=3,n-=3}for(;c.have<19;)c.lens[Ca[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,ya={bits:c.lenbits},xa=v(w,c.lens,0,19,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid code lengths set",c.mode=la;break}c.have=0,c.mode=aa;case aa:for(;c.have>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<sa)m>>>=qa,n-=qa,c.lens[c.have++]=sa;else{if(16===sa){for(za=qa+2;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,0===c.have){a.msg="invalid bit length repeat",c.mode=la;break}wa=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sa){for(za=qa+3;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=3+(7&m),m>>>=3,n-=3}else{for(za=qa+7;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=la;break}for(;q--;)c.lens[c.have++]=wa}}if(c.mode===la)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=la;break}if(c.lenbits=9,ya={bits:c.lenbits},xa=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid literal/lengths set",c.mode=la;break}if(c.distbits=6,c.distcode=c.distdyn,ya={bits:c.distbits},xa=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,ya),c.distbits=ya.bits,xa){a.msg="invalid distances set",c.mode=la;break}if(c.mode=ba,b===B)break a;case ba:c.mode=ca;case ca:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Aa=c.lencode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,c.length=sa,0===ra){c.mode=ha;break}if(32&ra){c.back=-1,c.mode=V;break}if(64&ra){a.msg="invalid literal/length code",c.mode=la;break}c.extra=15&ra,c.mode=da;case da:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=ea;case ea:for(;Aa=c.distcode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,64&ra){a.msg="invalid distance code",c.mode=la;break}c.offset=sa,c.extra=15&ra,c.mode=fa;case fa:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=la;break}c.mode=ga;case ga:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=la;break}q>c.wnext?(q-=c.wnext,oa=c.wsize-q):oa=c.wnext-q,q>c.length&&(q=c.length),pa=c.window}else pa=f,oa=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pa[oa++];while(--q);0===c.length&&(c.mode=ca);break;case ha:if(0===j)break a;f[h++]=c.length,j--,c.mode=ca;break;case ia:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<n;){if(0===i)break a;i--,m+=e[g++]<=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[c+E]]++;for(H=C,G=e;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;e>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===h||1!==G))return-1;for(Q[1]=0,D=1;e>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[c+E]&&(r[Q[b[c+E]]++]=E);if(a===h?(N=R=r,y=19):a===i?(N=k,O-=257,R=l,S-=257,y=256):(N=m,R=n,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<f||a===j&&L>g)return 1;for(var T=0;;){T++,z=D-J,r[E]y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[c+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<f||a===j&&L>g)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":28}],38:[function(a,b,c){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],39:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length}function f(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b}function g(a){return 256>a?ia[a]:ia[256+(a>>>7)]}function h(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function i(a,b,c){a.bi_valid>X-c?(a.bi_buf|=b<>X-a.bi_valid,a.bi_valid+=c-X):(a.bi_buf|=b<>>=1,c<<=1;while(--b>0);return c>>>1}function l(a){16===a.bi_valid?(h(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function m(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;W>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;V>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function n(a,b,c){var d,e,f=new Array(W+1),g=0;for(d=1;W>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=k(f[h]++,h))}}function o(){var a,b,c,d,f,g=new Array(W+1);for(c=0,d=0;Q-1>d;d++)for(ka[d]=c,a=0;a<1<d;d++)for(la[d]=f,a=0;a<1<>=7;T>d;d++)for(la[d]=f<<7,a=0;a<1<=b;b++)g[b]=0;for(a=0;143>=a;)ga[2*a+1]=8,a++,g[8]++;for(;255>=a;)ga[2*a+1]=9,a++,g[9]++;for(;279>=a;)ga[2*a+1]=7,a++,g[7]++;for(;287>=a;)ga[2*a+1]=8,a++,g[8]++;for(n(ga,S+1,g),a=0;T>a;a++)ha[2*a+1]=5,ha[2*a]=k(a,5);ma=new e(ga,ba,R+1,S,W),na=new e(ha,ca,0,T,W),oa=new e(new Array(0),da,0,U,Y)}function p(a){var b;for(b=0;S>b;b++)a.dyn_ltree[2*b]=0;for(b=0;T>b;b++)a.dyn_dtree[2*b]=0;for(b=0;U>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*Z]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function q(a){a.bi_valid>8?h(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function r(a,b,c,d){q(a),d&&(h(a,c),h(a,~c)),G.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function s(a,b,c,d){var e=2*b,f=2*c;return a[e]c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)t(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],t(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,t(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],m(a,b),n(f,j,a.bl_count)}function w(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++hh?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*$]++):10>=h?a.bl_tree[2*_]++:a.bl_tree[2*aa]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function x(a,b,c){var d,e,f=-1,g=b[1],h=0,k=7,l=4;for(0===g&&(k=138,l=3),d=0;c>=d;d++)if(e=g,g=b[2*(d+1)+1],!(++hh){do j(a,e,a.bl_tree);while(0!==--h)}else 0!==e?(e!==f&&(j(a,e,a.bl_tree),h--),j(a,$,a.bl_tree),i(a,h-3,2)):10>=h?(j(a,_,a.bl_tree),i(a,h-3,3)):(j(a,aa,a.bl_tree),i(a,h-11,7));h=0,f=e,0===g?(k=138,l=3):e===g?(k=6,l=3):(k=7,l=4)}}function y(a){var b;for(w(a,a.dyn_ltree,a.l_desc.max_code),w(a,a.dyn_dtree,a.d_desc.max_code),v(a,a.bl_desc),b=U-1;b>=3&&0===a.bl_tree[2*ea[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function z(a,b,c,d){var e;for(i(a,b-257,5),i(a,c-1,5),i(a,d-4,4),e=0;d>e;e++)i(a,a.bl_tree[2*ea[e]+1],3);x(a,a.dyn_ltree,b-1),x(a,a.dyn_dtree,c-1)}function A(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return I;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return J;for(b=32;R>b;b++)if(0!==a.dyn_ltree[2*b])return J;return I}function B(a){pa||(o(),pa=!0),a.l_desc=new f(a.dyn_ltree,ma),a.d_desc=new f(a.dyn_dtree,na),a.bl_desc=new f(a.bl_tree,oa),a.bi_buf=0,a.bi_valid=0,p(a)}function C(a,b,c,d){i(a,(L<<1)+(d?1:0),3),r(a,b,c,!0)}function D(a){i(a,M<<1,3),j(a,Z,ga),l(a)}function E(a,b,c,d){var e,f,g=0;a.level>0?(a.strm.data_type===K&&(a.strm.data_type=A(a)),v(a,a.l_desc),v(a,a.d_desc),g=y(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?C(a,b,c,d):a.strategy===H||f===e?(i(a,(M<<1)+(d?1:0),3),u(a,ga,ha)):(i(a,(N<<1)+(d?1:0),3),z(a,a.l_desc.max_code+1,a.d_desc.max_code+1,g+1),u(a,a.dyn_ltree,a.dyn_dtree)),p(a),d&&q(a)}function F(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(ja[c]+R+1)]++,a.dyn_dtree[2*g(b)]++),a.last_lit===a.lit_bufsize-1}var G=a("../utils/common"),H=4,I=0,J=1,K=2,L=0,M=1,N=2,O=3,P=258,Q=29,R=256,S=R+1+Q,T=30,U=19,V=2*S+1,W=15,X=16,Y=7,Z=256,$=16,_=17,aa=18,ba=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ca=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],da=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],ea=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],fa=512,ga=new Array(2*(S+2));d(ga);var ha=new Array(2*T);d(ha);var ia=new Array(fa);d(ia);var ja=new Array(P-O+1);d(ja);var ka=new Array(Q);d(ka);var la=new Array(T);d(la);var ma,na,oa,pa=!1;c._tr_init=B,c._tr_stored_block=C,c._tr_flush_block=E,c._tr_tally=F,c._tr_align=D},{"../utils/common":28}],40:[function(a,b,c){"use strict";function d(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=d},{}]},{},[10])(10)}); \ No newline at end of file diff --git a/cps/static/js/compress/jszip_epub.min.js b/cps/static/js/compress/jszip_epub.min.js new file mode 100644 index 00000000..ff4cfd5e --- /dev/null +++ b/cps/static/js/compress/jszip_epub.min.js @@ -0,0 +1,13 @@ +/*! + +JSZip v3.10.1 - A JavaScript class for generating and reading zip files + + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/main/LICENSE +*/ + +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).JSZip=e()}}(function(){return function s(a,o,h){function u(r,e){if(!o[r]){if(!a[r]){var t="function"==typeof require&&require;if(!e&&t)return t(r,!0);if(l)return l(r,!0);var n=new Error("Cannot find module '"+r+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[r]={exports:{}};a[r][0].call(i.exports,function(e){var t=a[r][1][e];return u(t||e)},i,i.exports,s,a,o,h)}return o[r].exports}for(var l="function"==typeof require&&require,e=0;e>2,s=(3&t)<<4|r>>4,a=1>6:64,o=2>4,r=(15&i)<<4|(s=p.indexOf(e.charAt(o++)))>>2,n=(3&s)<<6|(a=p.indexOf(e.charAt(o++))),l[h++]=t,64!==s&&(l[h++]=r),64!==a&&(l[h++]=n);return l}},{"./support":30,"./utils":32}],2:[function(e,t,r){"use strict";var n=e("./external"),i=e("./stream/DataWorker"),s=e("./stream/Crc32Probe"),a=e("./stream/DataLengthProbe");function o(e,t,r,n,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=r,this.compression=n,this.compressedContent=i}o.prototype={getContentWorker:function(){var e=new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")),t=this;return e.on("end",function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),e},getCompressedWorker:function(){return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(e,t,r){return e.pipe(new s).pipe(new a("uncompressedSize")).pipe(t.compressWorker(r)).pipe(new a("compressedSize")).withStreamInfo("compression",t)},t.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,r){"use strict";var n=e("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(){return new n("STORE compression")},uncompressWorker:function(){return new n("STORE decompression")}},r.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,r){"use strict";var n=e("./utils");var o=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t){return void 0!==e&&e.length?"string"!==n.getTypeOf(e)?function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t[a])];return-1^e}(0|t,e,e.length,0):function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t.charCodeAt(a))];return-1^e}(0|t,e,e.length,0):0}},{"./utils":32}],5:[function(e,t,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(e,t,r){"use strict";var n=null;n="undefined"!=typeof Promise?Promise:e("lie"),t.exports={Promise:n}},{lie:37}],7:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,i=e("pako"),s=e("./utils"),a=e("./stream/GenericWorker"),o=n?"uint8array":"array";function h(e,t){a.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}r.magic="\b\0",s.inherits(h,a),h.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,e.data),!1)},h.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var t=this;this._pako.onData=function(e){t.push({data:e,meta:t.meta})}},r.compressWorker=function(e){return new h("Deflate",e)},r.uncompressWorker=function(){return new h("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,t,r){"use strict";function A(e,t){var r,n="";for(r=0;r>>=8;return n}function n(e,t,r,n,i,s){var a,o,h=e.file,u=e.compression,l=s!==O.utf8encode,f=I.transformTo("string",s(h.name)),c=I.transformTo("string",O.utf8encode(h.name)),d=h.comment,p=I.transformTo("string",s(d)),m=I.transformTo("string",O.utf8encode(d)),_=c.length!==h.name.length,g=m.length!==d.length,b="",v="",y="",w=h.dir,k=h.date,x={crc32:0,compressedSize:0,uncompressedSize:0};t&&!r||(x.crc32=e.crc32,x.compressedSize=e.compressedSize,x.uncompressedSize=e.uncompressedSize);var S=0;t&&(S|=8),l||!_&&!g||(S|=2048);var z=0,C=0;w&&(z|=16),"UNIX"===i?(C=798,z|=function(e,t){var r=e;return e||(r=t?16893:33204),(65535&r)<<16}(h.unixPermissions,w)):(C=20,z|=function(e){return 63&(e||0)}(h.dosPermissions)),a=k.getUTCHours(),a<<=6,a|=k.getUTCMinutes(),a<<=5,a|=k.getUTCSeconds()/2,o=k.getUTCFullYear()-1980,o<<=4,o|=k.getUTCMonth()+1,o<<=5,o|=k.getUTCDate(),_&&(v=A(1,1)+A(B(f),4)+c,b+="up"+A(v.length,2)+v),g&&(y=A(1,1)+A(B(p),4)+m,b+="uc"+A(y.length,2)+y);var E="";return E+="\n\0",E+=A(S,2),E+=u.magic,E+=A(a,2),E+=A(o,2),E+=A(x.crc32,4),E+=A(x.compressedSize,4),E+=A(x.uncompressedSize,4),E+=A(f.length,2),E+=A(b.length,2),{fileRecord:R.LOCAL_FILE_HEADER+E+f+b,dirRecord:R.CENTRAL_FILE_HEADER+A(C,2)+E+A(p.length,2)+"\0\0\0\0"+A(z,4)+A(n,4)+f+b+p}}var I=e("../utils"),i=e("../stream/GenericWorker"),O=e("../utf8"),B=e("../crc32"),R=e("../signature");function s(e,t,r,n){i.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=t,this.zipPlatform=r,this.encodeFileName=n,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}I.inherits(s,i),s.prototype.push=function(e){var t=e.meta.percent||0,r=this.entriesCount,n=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,i.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:r?(t+100*(r-n-1))/r:100}}))},s.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var t=this.streamFiles&&!e.file.dir;if(t){var r=n(e,t,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},s.prototype.closedSource=function(e){this.accumulate=!1;var t=this.streamFiles&&!e.file.dir,r=n(e,t,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(r.dirRecord),t)this.push({data:function(e){return R.DATA_DESCRIPTOR+A(e.crc32,4)+A(e.compressedSize,4)+A(e.uncompressedSize,4)}(e),meta:{percent:100}});else for(this.push({data:r.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},s.prototype.flush=function(){for(var e=this.bytesWritten,t=0;t=this.index;t--)r=(r<<8)+this.byteAt(t);return this.index+=e,r},readString:function(e){return n.transformTo("string",this.readData(e))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},t.exports=i},{"../utils":32}],19:[function(e,t,r){"use strict";var n=e("./Uint8ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},i.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},i.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],21:[function(e,t,r){"use strict";var n=e("./ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return new Uint8Array(0);var t=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./ArrayReader":17}],22:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../support"),s=e("./ArrayReader"),a=e("./StringReader"),o=e("./NodeBufferReader"),h=e("./Uint8ArrayReader");t.exports=function(e){var t=n.getTypeOf(e);return n.checkSupport(t),"string"!==t||i.uint8array?"nodebuffer"===t?new o(e):i.uint8array?new h(n.transformTo("uint8array",e)):new s(n.transformTo("array",e)):new a(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,t,r){"use strict";r.LOCAL_FILE_HEADER="PK",r.CENTRAL_FILE_HEADER="PK",r.CENTRAL_DIRECTORY_END="PK",r.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",r.ZIP64_CENTRAL_DIRECTORY_END="PK",r.DATA_DESCRIPTOR="PK\b"},{}],24:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../utils");function s(e){n.call(this,"ConvertWorker to "+e),this.destType=e}i.inherits(s,n),s.prototype.processChunk=function(e){this.push({data:i.transformTo(this.destType,e.data),meta:e.meta})},t.exports=s},{"../utils":32,"./GenericWorker":28}],25:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../crc32");function s(){n.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}e("../utils").inherits(s,n),s.prototype.processChunk=function(e){this.streamInfo.crc32=i(e.data,this.streamInfo.crc32||0),this.push(e)},t.exports=s},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataLengthProbe for "+e),this.propName=e,this.withStreamInfo(e,0)}n.inherits(s,i),s.prototype.processChunk=function(e){if(e){var t=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=t+e.data.length}i.prototype.processChunk.call(this,e)},t.exports=s},{"../utils":32,"./GenericWorker":28}],27:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataWorker");var t=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,e.then(function(e){t.dataIsReady=!0,t.data=e,t.max=e&&e.length||0,t.type=n.getTypeOf(e),t.isPaused||t._tickAndRepeat()},function(e){t.error(e)})}n.inherits(s,i),s.prototype.cleanUp=function(){i.prototype.cleanUp.call(this),this.data=null},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,n.delay(this._tickAndRepeat,[],this)),!0)},s.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(n.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},s.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,t=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":e=this.data.substring(this.index,t);break;case"uint8array":e=this.data.subarray(this.index,t);break;case"array":case"nodebuffer":e=this.data.slice(this.index,t)}return this.index=t,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},t.exports=s},{"../utils":32,"./GenericWorker":28}],28:[function(e,t,r){"use strict";function n(e){this.name=e||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}n.prototype={push:function(e){this.emit("data",e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(e){this.emit("error",e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit("error",e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,t){return this._listeners[e].push(t),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,t){if(this._listeners[e])for(var r=0;r "+e:e}},t.exports=n},{}],29:[function(e,t,r){"use strict";var h=e("../utils"),i=e("./ConvertWorker"),s=e("./GenericWorker"),u=e("../base64"),n=e("../support"),a=e("../external"),o=null;if(n.nodestream)try{o=e("../nodejs/NodejsStreamOutputAdapter")}catch(e){}function l(e,o){return new a.Promise(function(t,r){var n=[],i=e._internalType,s=e._outputType,a=e._mimeType;e.on("data",function(e,t){n.push(e),o&&o(t)}).on("error",function(e){n=[],r(e)}).on("end",function(){try{var e=function(e,t,r){switch(e){case"blob":return h.newBlob(h.transformTo("arraybuffer",t),r);case"base64":return u.encode(t);default:return h.transformTo(e,t)}}(s,function(e,t){var r,n=0,i=null,s=0;for(r=0;r>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t}(e)},s.utf8decode=function(e){return h.nodebuffer?o.transformTo("nodebuffer",e).toString("utf-8"):function(e){var t,r,n,i,s=e.length,a=new Array(2*s);for(t=r=0;t>10&1023,a[r++]=56320|1023&n)}return a.length!==r&&(a.subarray?a=a.subarray(0,r):a.length=r),o.applyFromCharCode(a)}(e=o.transformTo(h.uint8array?"uint8array":"array",e))},o.inherits(a,n),a.prototype.processChunk=function(e){var t=o.transformTo(h.uint8array?"uint8array":"array",e.data);if(this.leftOver&&this.leftOver.length){if(h.uint8array){var r=t;(t=new Uint8Array(r.length+this.leftOver.length)).set(this.leftOver,0),t.set(r,this.leftOver.length)}else t=this.leftOver.concat(t);this.leftOver=null}var n=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+u[e[r]]>t?r:t}(t),i=t;n!==t.length&&(h.uint8array?(i=t.subarray(0,n),this.leftOver=t.subarray(n,t.length)):(i=t.slice(0,n),this.leftOver=t.slice(n,t.length))),this.push({data:s.utf8decode(i),meta:e.meta})},a.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:s.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},s.Utf8DecodeWorker=a,o.inherits(l,n),l.prototype.processChunk=function(e){this.push({data:s.utf8encode(e.data),meta:e.meta})},s.Utf8EncodeWorker=l},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,t,a){"use strict";var o=e("./support"),h=e("./base64"),r=e("./nodejsUtils"),u=e("./external");function n(e){return e}function l(e,t){for(var r=0;r>8;this.dir=!!(16&this.externalFileAttributes),0==e&&(this.dosPermissions=63&this.externalFileAttributes),3==e&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var e=n(this.extraFields[1].value);this.uncompressedSize===s.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===s.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===s.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===s.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(e){var t,r,n,i=e.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});e.index+4>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t},r.buf2binstring=function(e){return l(e,e.length)},r.binstring2buf=function(e){for(var t=new h.Buf8(e.length),r=0,n=t.length;r>10&1023,o[n++]=56320|1023&i)}return l(o,n)},r.utf8border=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+u[e[r]]>t?r:t}},{"./common":41}],43:[function(e,t,r){"use strict";t.exports=function(e,t,r,n){for(var i=65535&e|0,s=e>>>16&65535|0,a=0;0!==r;){for(r-=a=2e3>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t[a])];return-1^e}},{}],46:[function(e,t,r){"use strict";var h,c=e("../utils/common"),u=e("./trees"),d=e("./adler32"),p=e("./crc32"),n=e("./messages"),l=0,f=4,m=0,_=-2,g=-1,b=4,i=2,v=8,y=9,s=286,a=30,o=19,w=2*s+1,k=15,x=3,S=258,z=S+x+1,C=42,E=113,A=1,I=2,O=3,B=4;function R(e,t){return e.msg=n[t],t}function T(e){return(e<<1)-(4e.avail_out&&(r=e.avail_out),0!==r&&(c.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function N(e,t){u._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,F(e.strm)}function U(e,t){e.pending_buf[e.pending++]=t}function P(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function L(e,t){var r,n,i=e.max_chain_length,s=e.strstart,a=e.prev_length,o=e.nice_match,h=e.strstart>e.w_size-z?e.strstart-(e.w_size-z):0,u=e.window,l=e.w_mask,f=e.prev,c=e.strstart+S,d=u[s+a-1],p=u[s+a];e.prev_length>=e.good_match&&(i>>=2),o>e.lookahead&&(o=e.lookahead);do{if(u[(r=t)+a]===p&&u[r+a-1]===d&&u[r]===u[s]&&u[++r]===u[s+1]){s+=2,r++;do{}while(u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&sh&&0!=--i);return a<=e.lookahead?a:e.lookahead}function j(e){var t,r,n,i,s,a,o,h,u,l,f=e.w_size;do{if(i=e.window_size-e.lookahead-e.strstart,e.strstart>=f+(f-z)){for(c.arraySet(e.window,e.window,f,f,0),e.match_start-=f,e.strstart-=f,e.block_start-=f,t=r=e.hash_size;n=e.head[--t],e.head[t]=f<=n?n-f:0,--r;);for(t=r=f;n=e.prev[--t],e.prev[t]=f<=n?n-f:0,--r;);i+=f}if(0===e.strm.avail_in)break;if(a=e.strm,o=e.window,h=e.strstart+e.lookahead,u=i,l=void 0,l=a.avail_in,u=x)for(s=e.strstart-e.insert,e.ins_h=e.window[s],e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x)if(n=u._tr_tally(e,e.strstart-e.match_start,e.match_length-x),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=x){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x&&e.match_length<=e.prev_length){for(i=e.strstart+e.lookahead-x,n=u._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-x),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=i&&(e.ins_h=(e.ins_h<e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(j(e),0===e.lookahead&&t===l)return A;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,N(e,!1),0===e.strm.avail_out))return A;if(e.strstart-e.block_start>=e.w_size-z&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):(e.strstart>e.block_start&&(N(e,!1),e.strm.avail_out),A)}),new M(4,4,8,4,Z),new M(4,5,16,8,Z),new M(4,6,32,32,Z),new M(4,4,16,16,W),new M(8,16,32,32,W),new M(8,16,128,128,W),new M(8,32,128,256,W),new M(32,128,258,1024,W),new M(32,258,258,4096,W)],r.deflateInit=function(e,t){return Y(e,t,v,15,8,0)},r.deflateInit2=Y,r.deflateReset=K,r.deflateResetKeep=G,r.deflateSetHeader=function(e,t){return e&&e.state?2!==e.state.wrap?_:(e.state.gzhead=t,m):_},r.deflate=function(e,t){var r,n,i,s;if(!e||!e.state||5>8&255),U(n,n.gzhead.time>>16&255),U(n,n.gzhead.time>>24&255),U(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),U(n,255&n.gzhead.os),n.gzhead.extra&&n.gzhead.extra.length&&(U(n,255&n.gzhead.extra.length),U(n,n.gzhead.extra.length>>8&255)),n.gzhead.hcrc&&(e.adler=p(e.adler,n.pending_buf,n.pending,0)),n.gzindex=0,n.status=69):(U(n,0),U(n,0),U(n,0),U(n,0),U(n,0),U(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),U(n,3),n.status=E);else{var a=v+(n.w_bits-8<<4)<<8;a|=(2<=n.strategy||n.level<2?0:n.level<6?1:6===n.level?2:3)<<6,0!==n.strstart&&(a|=32),a+=31-a%31,n.status=E,P(n,a),0!==n.strstart&&(P(n,e.adler>>>16),P(n,65535&e.adler)),e.adler=1}if(69===n.status)if(n.gzhead.extra){for(i=n.pending;n.gzindex<(65535&n.gzhead.extra.length)&&(n.pending!==n.pending_buf_size||(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending!==n.pending_buf_size));)U(n,255&n.gzhead.extra[n.gzindex]),n.gzindex++;n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),n.gzindex===n.gzhead.extra.length&&(n.gzindex=0,n.status=73)}else n.status=73;if(73===n.status)if(n.gzhead.name){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindexi&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.gzindex=0,n.status=91)}else n.status=91;if(91===n.status)if(n.gzhead.comment){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindexi&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.status=103)}else n.status=103;if(103===n.status&&(n.gzhead.hcrc?(n.pending+2>n.pending_buf_size&&F(e),n.pending+2<=n.pending_buf_size&&(U(n,255&e.adler),U(n,e.adler>>8&255),e.adler=0,n.status=E)):n.status=E),0!==n.pending){if(F(e),0===e.avail_out)return n.last_flush=-1,m}else if(0===e.avail_in&&T(t)<=T(r)&&t!==f)return R(e,-5);if(666===n.status&&0!==e.avail_in)return R(e,-5);if(0!==e.avail_in||0!==n.lookahead||t!==l&&666!==n.status){var o=2===n.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(j(e),0===e.lookahead)){if(t===l)return A;break}if(e.match_length=0,r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(n,t):3===n.strategy?function(e,t){for(var r,n,i,s,a=e.window;;){if(e.lookahead<=S){if(j(e),e.lookahead<=S&&t===l)return A;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=x&&0e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=x?(r=u._tr_tally(e,1,e.match_length-x),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(n,t):h[n.level].func(n,t);if(o!==O&&o!==B||(n.status=666),o===A||o===O)return 0===e.avail_out&&(n.last_flush=-1),m;if(o===I&&(1===t?u._tr_align(n):5!==t&&(u._tr_stored_block(n,0,0,!1),3===t&&(D(n.head),0===n.lookahead&&(n.strstart=0,n.block_start=0,n.insert=0))),F(e),0===e.avail_out))return n.last_flush=-1,m}return t!==f?m:n.wrap<=0?1:(2===n.wrap?(U(n,255&e.adler),U(n,e.adler>>8&255),U(n,e.adler>>16&255),U(n,e.adler>>24&255),U(n,255&e.total_in),U(n,e.total_in>>8&255),U(n,e.total_in>>16&255),U(n,e.total_in>>24&255)):(P(n,e.adler>>>16),P(n,65535&e.adler)),F(e),0=r.w_size&&(0===s&&(D(r.head),r.strstart=0,r.block_start=0,r.insert=0),u=new c.Buf8(r.w_size),c.arraySet(u,t,l-r.w_size,r.w_size,0),t=u,l=r.w_size),a=e.avail_in,o=e.next_in,h=e.input,e.avail_in=l,e.next_in=0,e.input=t,j(r);r.lookahead>=x;){for(n=r.strstart,i=r.lookahead-(x-1);r.ins_h=(r.ins_h<>>=y=v>>>24,p-=y,0===(y=v>>>16&255))C[s++]=65535&v;else{if(!(16&y)){if(0==(64&y)){v=m[(65535&v)+(d&(1<>>=y,p-=y),p<15&&(d+=z[n++]<>>=y=v>>>24,p-=y,!(16&(y=v>>>16&255))){if(0==(64&y)){v=_[(65535&v)+(d&(1<>>=y,p-=y,(y=s-a)>3,d&=(1<<(p-=w<<3))-1,e.next_in=n,e.next_out=s,e.avail_in=n>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function s(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new I.Buf16(320),this.work=new I.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function a(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=P,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new I.Buf32(n),t.distcode=t.distdyn=new I.Buf32(i),t.sane=1,t.back=-1,N):U}function o(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,a(e)):U}function h(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15=s.wsize?(I.arraySet(s.window,t,r-s.wsize,s.wsize,0),s.wnext=0,s.whave=s.wsize):(n<(i=s.wsize-s.wnext)&&(i=n),I.arraySet(s.window,t,r-n,i,s.wnext),(n-=i)?(I.arraySet(s.window,t,r-n,n,0),s.wnext=n,s.whave=s.wsize):(s.wnext+=i,s.wnext===s.wsize&&(s.wnext=0),s.whave>>8&255,r.check=B(r.check,E,2,0),l=u=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&u)<<8)+(u>>8))%31){e.msg="incorrect header check",r.mode=30;break}if(8!=(15&u)){e.msg="unknown compression method",r.mode=30;break}if(l-=4,k=8+(15&(u>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){e.msg="invalid window size",r.mode=30;break}r.dmax=1<>8&1),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=3;case 3:for(;l<32;){if(0===o)break e;o--,u+=n[s++]<>>8&255,E[2]=u>>>16&255,E[3]=u>>>24&255,r.check=B(r.check,E,4,0)),l=u=0,r.mode=4;case 4:for(;l<16;){if(0===o)break e;o--,u+=n[s++]<>8),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=5;case 5:if(1024&r.flags){for(;l<16;){if(0===o)break e;o--,u+=n[s++]<>>8&255,r.check=B(r.check,E,2,0)),l=u=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(o<(d=r.length)&&(d=o),d&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),I.arraySet(r.head.extra,n,s,d,k)),512&r.flags&&(r.check=B(r.check,n,d,s)),o-=d,s+=d,r.length-=d),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===o)break e;for(d=0;k=n[s+d++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k)),k&&d>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=12;break;case 10:for(;l<32;){if(0===o)break e;o--,u+=n[s++]<>>=7&l,l-=7&l,r.mode=27;break}for(;l<3;){if(0===o)break e;o--,u+=n[s++]<>>=1)){case 0:r.mode=14;break;case 1:if(j(r),r.mode=20,6!==t)break;u>>>=2,l-=2;break e;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=30}u>>>=2,l-=2;break;case 14:for(u>>>=7&l,l-=7&l;l<32;){if(0===o)break e;o--,u+=n[s++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&u,l=u=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(d=r.length){if(o>>=5,l-=5,r.ndist=1+(31&u),u>>>=5,l-=5,r.ncode=4+(15&u),u>>>=4,l-=4,286>>=3,l-=3}for(;r.have<19;)r.lens[A[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},x=T(0,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=_,l-=_,r.lens[r.have++]=b;else{if(16===b){for(z=_+2;l>>=_,l-=_,0===r.have){e.msg="invalid bit length repeat",r.mode=30;break}k=r.lens[r.have-1],d=3+(3&u),u>>>=2,l-=2}else if(17===b){for(z=_+3;l>>=_)),u>>>=3,l-=3}else{for(z=_+7;l>>=_)),u>>>=7,l-=7}if(r.have+d>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=30;break}for(;d--;)r.lens[r.have++]=k}}if(30===r.mode)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,S={bits:r.lenbits},x=T(D,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},x=T(F,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,x){e.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(6<=o&&258<=h){e.next_out=a,e.avail_out=h,e.next_in=s,e.avail_in=o,r.hold=u,r.bits=l,R(e,c),a=e.next_out,i=e.output,h=e.avail_out,s=e.next_in,n=e.input,o=e.avail_in,u=r.hold,l=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;g=(C=r.lencode[u&(1<>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,r.length=b,0===g){r.mode=26;break}if(32&g){r.back=-1,r.mode=12;break}if(64&g){e.msg="invalid literal/length code",r.mode=30;break}r.extra=15&g,r.mode=22;case 22:if(r.extra){for(z=r.extra;l>>=r.extra,l-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;g=(C=r.distcode[u&(1<>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,64&g){e.msg="invalid distance code",r.mode=30;break}r.offset=b,r.extra=15&g,r.mode=24;case 24:if(r.extra){for(z=r.extra;l>>=r.extra,l-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===h)break e;if(d=c-h,r.offset>d){if((d=r.offset-d)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=30;break}p=d>r.wnext?(d-=r.wnext,r.wsize-d):r.wnext-d,d>r.length&&(d=r.length),m=r.window}else m=i,p=a-r.offset,d=r.length;for(hd?(m=R[T+a[v]],A[I+a[v]]):(m=96,0),h=1<>S)+(u-=h)]=p<<24|m<<16|_|0,0!==u;);for(h=1<>=1;if(0!==h?(E&=h-1,E+=h):E=0,v++,0==--O[b]){if(b===w)break;b=t[r+a[v]]}if(k>>7)]}function U(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function P(e,t,r){e.bi_valid>d-r?(e.bi_buf|=t<>d-e.bi_valid,e.bi_valid+=r-d):(e.bi_buf|=t<>>=1,r<<=1,0<--t;);return r>>>1}function Z(e,t,r){var n,i,s=new Array(g+1),a=0;for(n=1;n<=g;n++)s[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var o=e[2*i+1];0!==o&&(e[2*i]=j(s[o]++,o))}}function W(e){var t;for(t=0;t>1;1<=r;r--)G(e,s,r);for(i=h;r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],G(e,s,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,s[2*i]=s[2*r]+s[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,s[2*r+1]=s[2*n+1]=i,e.heap[1]=i++,G(e,s,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,s,a,o,h=t.dyn_tree,u=t.max_code,l=t.stat_desc.static_tree,f=t.stat_desc.has_stree,c=t.stat_desc.extra_bits,d=t.stat_desc.extra_base,p=t.stat_desc.max_length,m=0;for(s=0;s<=g;s++)e.bl_count[s]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<_;r++)p<(s=h[2*h[2*(n=e.heap[r])+1]+1]+1)&&(s=p,m++),h[2*n+1]=s,u>=7;n>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return o;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return h;for(t=32;t>>3,(s=e.static_len+3+7>>>3)<=i&&(i=s)):i=s=r+5,r+4<=i&&-1!==t?J(e,t,r,n):4===e.strategy||s===i?(P(e,2+(n?1:0),3),K(e,z,C)):(P(e,4+(n?1:0),3),function(e,t,r,n){var i;for(P(e,t-257,5),P(e,r-1,5),P(e,n-4,4),i=0;i>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(A[r]+u+1)]++,e.dyn_dtree[2*N(t)]++),e.last_lit===e.lit_bufsize-1},r._tr_align=function(e){P(e,2,3),L(e,m,z),function(e){16===e.bi_valid?(U(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},{"../utils/common":41}],53:[function(e,t,r){"use strict";t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,t,r){(function(e){!function(r,n){"use strict";if(!r.setImmediate){var i,s,t,a,o=1,h={},u=!1,l=r.document,e=Object.getPrototypeOf&&Object.getPrototypeOf(r);e=e&&e.setTimeout?e:r,i="[object process]"==={}.toString.call(r.process)?function(e){process.nextTick(function(){c(e)})}:function(){if(r.postMessage&&!r.importScripts){var e=!0,t=r.onmessage;return r.onmessage=function(){e=!1},r.postMessage("","*"),r.onmessage=t,e}}()?(a="setImmediate$"+Math.random()+"$",r.addEventListener?r.addEventListener("message",d,!1):r.attachEvent("onmessage",d),function(e){r.postMessage(a+e,"*")}):r.MessageChannel?((t=new MessageChannel).port1.onmessage=function(e){c(e.data)},function(e){t.port2.postMessage(e)}):l&&"onreadystatechange"in l.createElement("script")?(s=l.documentElement,function(e){var t=l.createElement("script");t.onreadystatechange=function(){c(e),t.onreadystatechange=null,s.removeChild(t),t=null},s.appendChild(t)}):function(e){setTimeout(c,0,e)},e.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),r=0;r' + item.message + ''); + }); + } else { + data.forEach(function (item) { + $(".navbar").after('
' + + '
' + item.message + '
' + + '
'); + }); + } + } +} +$(".sendbtn-form").click(function() { + $.ajax({ + method: 'post', + url: $(this).data('href'), + data: {csrf_token: $("input[name='csrf_token']").val()}, + success: function (data) { + handleResponse(data) + } + }) +}); + $(function() { $("#have_read_form").ajaxForm(); }); diff --git a/cps/static/js/kthoom.js b/cps/static/js/kthoom.js index 51dbadba..67b18fc1 100644 --- a/cps/static/js/kthoom.js +++ b/cps/static/js/kthoom.js @@ -62,6 +62,7 @@ var currentImage = 0; var imageFiles = []; var imageFilenames = []; var totalImages = 0; +var prevScrollPosition = 0; var settings = { hflip: false, @@ -70,8 +71,9 @@ var settings = { fitMode: kthoom.Key.B, theme: "light", direction: 0, // 0 = Left to Right, 1 = Right to Left - nextPage: 0, // 0 = Reset to Top, 1 = Remember Position - scrollbar: 1 // 0 = Hide Scrollbar, 1 = Show Scrollbar + nextPage: 0, // 0 = Reset to Top, 1 = Remember Position + scrollbar: 1, // 0 = Hide Scrollbar, 1 = Show Scrollbar + pageDisplay: 0 // 0 = Single Page, 1 = Long Strip }; kthoom.saveSettings = function() { @@ -130,8 +132,8 @@ var createURLFromArray = function(array, mimeType) { } if ((typeof URL !== "function" && typeof URL !== "object") || - typeof URL.createObjectURL !== "function") { - throw "Browser support for Object URLs is missing"; + typeof URL.createObjectURL !== "function") { + throw "Browser support for Object URLs is missing"; } return URL.createObjectURL(blob); @@ -176,18 +178,38 @@ kthoom.ImageFile = function(file) { } }; +function updateDirectionButtons(){ + var left, right = 1; + if (currentImage == 0 ) { + if (settings.direction === 0) { + left = 0; + } else { + right = 0; + } + } + if ((currentImage + 1) >= Math.max(totalImages, imageFiles.length)) { + if (settings.direction === 0) { + right = 0; + } else { + left = 0; + } + } + left === 1 ? $("#left").show() : $("#left").hide(); + right === 1 ? $("#right").show() : $("#right").hide(); +} function initProgressClick() { $("#progress").click(function(e) { var offset = $(this).offset(); var x = e.pageX - offset.left; var rate = settings.direction === 0 ? x / $(this).width() : 1 - x / $(this).width(); currentImage = Math.max(1, Math.ceil(rate * totalImages)) - 1; + updateDirectionButtons(); + setBookmark(); updatePage(); }); } function loadFromArrayBuffer(ab) { - var lastCompletion = 0; const collator = new Intl.Collator('en', { numeric: true, sensitivity: 'base' }); loadArchiveFormats(['rar', 'zip', 'tar'], function() { // Open the file as an archive @@ -216,9 +238,14 @@ function loadFromArrayBuffer(ab) { "" + "" ); + + drawCanvas(); + setImage(test.dataURI, null); + // display first page if we haven't yet if (imageFiles.length === currentImage + 1) { - updatePage(lastCompletion); + updateDirectionButtons(); + updatePage(); } } else { totalImages--; @@ -233,6 +260,17 @@ function loadFromArrayBuffer(ab) { } function scrollTocToActive() { + $(".page").text((currentImage + 1 ) + "/" + totalImages); + + // Mark the current page in the TOC + $("#tocView a[data-page]") + // Remove the currently active thumbnail + .removeClass("active") + // Find the new one + .filter("[data-page=" + (currentImage + 1) + "]") + // Set it to active + .addClass("active"); + // Scroll to the thumbnail in the TOC on page change $("#tocView").stop().animate({ scrollTop: $("#tocView a.active").position().top @@ -240,33 +278,33 @@ function scrollTocToActive() { } function updatePage() { - $(".page").text((currentImage + 1 ) + "/" + totalImages); - - // Mark the current page in the TOC - $("#tocView a[data-page]") - // Remove the currently active thumbnail - .removeClass("active") - // Find the new one - .filter("[data-page=" + (currentImage + 1) + "]") - // Set it to active - .addClass("active"); - scrollTocToActive(); + scrollCurrentImageIntoView(); updateProgress(); - - if (imageFiles[currentImage]) { - setImage(imageFiles[currentImage].dataURI); - } else { - setImage("loading"); - } - - $("body").toggleClass("dark-theme", settings.theme === "dark"); - $("#mainContent").toggleClass("disabled-scrollbar", settings.scrollbar === 0); + pageDisplayUpdate(); + setTheme(); kthoom.setSettings(); kthoom.saveSettings(); } +function setTheme() { + $("body").toggleClass("dark-theme", settings.theme === "dark"); + $("#mainContent").toggleClass("disabled-scrollbar", settings.scrollbar === 0); +} + +function pageDisplayUpdate() { + if(settings.pageDisplay === 0) { + $(".mainImage").addClass("hide"); + $(".mainImage").eq(currentImage).removeClass("hide"); + $("#mainContent").removeClass("long-strip"); + } else { + $(".mainImage").removeClass("hide"); + $("#mainContent").addClass("long-strip"); + scrollCurrentImageIntoView(); + } +} + function updateProgress(loadPercentage) { if (settings.direction === 0) { $("#progress .bar-read") @@ -298,100 +336,93 @@ function updateProgress(loadPercentage) { $("#progress .bar-read").css({ width: totalImages === 0 ? 0 : Math.round((currentImage + 1) / totalImages * 100) + "%"}); } -function setImage(url) { - var canvas = $("#mainImage")[0]; - var x = $("#mainImage")[0].getContext("2d"); +function setImage(url, _canvas) { + var canvas = _canvas || $(".mainImage").slice(-1)[0]; // Select the last item on the array if _canvas is null + var x = canvas.getContext("2d"); + $("#mainText").hide(); - if (url === "loading") { - updateScale(true); - canvas.width = innerWidth - 100; - canvas.height = 200; + if (url === "error") { x.fillStyle = "black"; x.textAlign = "center"; x.font = "24px sans-serif"; - x.strokeStyle = "black"; - x.fillText("Loading Page #" + (currentImage + 1), innerWidth / 2, 100); + x.strokeStyle = (settings.theme === "dark") ? "white" : "black"; + x.fillText("Unable to decompress image #" + (currentImage + 1), innerWidth / 2, 100); + + $(".mainImage").slice(-1).addClass("error"); } else { - if (url === "error") { - updateScale(true); - canvas.width = innerWidth - 100; - canvas.height = 200; - x.fillStyle = "black"; - x.textAlign = "center"; - x.font = "24px sans-serif"; - x.strokeStyle = "black"; - x.fillText("Unable to decompress image #" + (currentImage + 1), innerWidth / 2, 100); - } else { - if ($("body").css("scrollHeight") / innerHeight > 1) { - $("body").css("overflowY", "scroll"); - } - - var img = new Image(); - img.onerror = function() { - canvas.width = innerWidth - 100; - canvas.height = 300; - updateScale(true); - x.fillStyle = "black"; - x.font = "50px sans-serif"; - x.strokeStyle = "black"; - x.fillText("Page #" + (currentImage + 1) + " (" + - imageFiles[currentImage].filename + ")", innerWidth / 2, 100); - x.fillStyle = "black"; - x.fillText("Is corrupt or not an image", innerWidth / 2, 200); - - var xhr = new XMLHttpRequest(); - if (/(html|htm)$/.test(imageFiles[currentImage].filename)) { - xhr.open("GET", url, true); - xhr.onload = function() { - $("#mainText").css("display", ""); - $("#mainText").innerHTML(""); - }; - xhr.send(null); - } else if (!/(jpg|jpeg|png|gif|webp)$/.test(imageFiles[currentImage].filename) && imageFiles[currentImage].data.uncompressedSize < 10 * 1024) { - xhr.open("GET", url, true); - xhr.onload = function() { - $("#mainText").css("display", ""); - $("#mainText").innerText(xhr.responseText); - }; - xhr.send(null); - } - }; - img.onload = function() { - var h = img.height, - w = img.width, - sw = w, - sh = h; - settings.rotateTimes = (4 + settings.rotateTimes) % 4; - x.save(); - if (settings.rotateTimes % 2 === 1) { - sh = w; - sw = h; - } - canvas.height = sh; - canvas.width = sw; - x.translate(sw / 2, sh / 2); - x.rotate(Math.PI / 2 * settings.rotateTimes); - x.translate(-w / 2, -h / 2); - if (settings.vflip) { - x.scale(1, -1); - x.translate(0, -h); - } - if (settings.hflip) { - x.scale(-1, 1); - x.translate(-w, 0); - } - canvas.style.display = "none"; - scrollTo(0, 0); - x.drawImage(img, 0, 0); - - updateScale(false); - - canvas.style.display = ""; - $("body").css("overflowY", ""); - x.restore(); - }; - img.src = url; + if ($("body").css("scrollHeight") / innerHeight > 1) { + $("body").css("overflowY", "scroll"); } + + var img = new Image(); + img.onerror = function() { + canvas.width = innerWidth - 100; + canvas.height = 300; + x.fillStyle = "black"; + x.font = "50px sans-serif"; + x.strokeStyle = "black"; + x.fillText("Page #" + (currentImage + 1) + " (" + + imageFiles[currentImage].filename + ")", innerWidth / 2, 100); + x.fillStyle = "black"; + x.fillText("Is corrupt or not an image", innerWidth / 2, 200); + + var xhr = new XMLHttpRequest(); + if (/(html|htm)$/.test(imageFiles[currentImage].filename)) { + xhr.open("GET", url, true); + xhr.onload = function() { + $("#mainText").css("display", ""); + $("#mainText").innerHTML(""); + }; + xhr.send(null); + } else if (!/(jpg|jpeg|png|gif|webp)$/.test(imageFiles[currentImage].filename) && imageFiles[currentImage].data.uncompressedSize < 10 * 1024) { + xhr.open("GET", url, true); + xhr.onload = function() { + $("#mainText").css("display", ""); + $("#mainText").innerText(xhr.responseText); + }; + xhr.send(null); + } + }; + img.onload = function() { + var h = img.height, + w = img.width, + sw = w, + sh = h; + settings.rotateTimes = (4 + settings.rotateTimes) % 4; + x.save(); + if (settings.rotateTimes % 2 === 1) { + sh = w; + sw = h; + } + canvas.height = sh; + canvas.width = sw; + x.translate(sw / 2, sh / 2); + x.rotate(Math.PI / 2 * settings.rotateTimes); + x.translate(-w / 2, -h / 2); + if (settings.vflip) { + x.scale(1, -1); + x.translate(0, -h); + } + if (settings.hflip) { + x.scale(-1, 1); + x.translate(-w, 0); + } + canvas.style.display = "none"; + scrollTo(0, 0); + x.drawImage(img, 0, 0); + + canvas.style.display = ""; + $("body").css("overflowY", ""); + x.restore(); + }; + img.src = url; + } +} + +// reloadImages is a slow process when multiple images are involved. Only used when rotating/mirroring +function reloadImages() { + for(i=0; i < imageFiles.length; i++) { + setImage(imageFiles[i].dataURI, $(".mainImage")[i]); } } @@ -401,6 +432,7 @@ function showLeftPage() { } else { showNextPage(); } + setBookmark(); } function showRightPage() { @@ -409,6 +441,7 @@ function showRightPage() { } else { showPrevPage(); } + setBookmark(); } function showPrevPage() { @@ -418,10 +451,8 @@ function showPrevPage() { currentImage++; } else { updatePage(); - if (settings.nextPage === 0) { - $("#mainContent").scrollTop(0); - } } + updateDirectionButtons(); } function showNextPage() { @@ -431,36 +462,54 @@ function showNextPage() { currentImage--; } else { updatePage(); - if (settings.nextPage === 0) { - $("#mainContent").scrollTop(0); - } + } + updateDirectionButtons(); +} + +function scrollCurrentImageIntoView() { + if(settings.pageDisplay == 0) { + // This will scroll all the way up when Single Page is selected + $("#mainContent").scrollTop(0); + } else { + // This will scroll to the image when Long Strip is selected + $("#mainContent").stop().animate({ + scrollTop: $(".mainImage").eq(currentImage).offset().top + $("#mainContent").scrollTop() - $("#mainContent").offset().top + }, 200); } } -function updateScale(clear) { - var mainImageStyle = getElem("mainImage").style; - mainImageStyle.width = ""; - mainImageStyle.height = ""; - mainImageStyle.maxWidth = ""; - mainImageStyle.maxHeight = ""; +function updateScale() { + var canvasArray = $("#mainContent > canvas"); var maxheight = innerHeight - 50; + + canvasArray.css("width", ""); + canvasArray.css("height", ""); + canvasArray.css("maxWidth", ""); + canvasArray.css("maxHeight", ""); - if (!clear) { - switch (settings.fitMode) { - case kthoom.Key.B: - mainImageStyle.maxWidth = "100%"; - mainImageStyle.maxHeight = maxheight + "px"; - break; - case kthoom.Key.H: - mainImageStyle.height = maxheight + "px"; - break; - case kthoom.Key.W: - mainImageStyle.width = "100%"; - break; - default: - break; - } + if(settings.pageDisplay === 0) { + canvasArray.addClass("hide"); + pageDisplayUpdate(); } + + switch (settings.fitMode) { + case kthoom.Key.B: + canvasArray.css("maxWidth", "100%"); + canvasArray.css("maxHeight", maxheight + "px"); + break; + case kthoom.Key.H: + canvasArray.css("maxHeight", maxheight + "px"); + break; + case kthoom.Key.W: + canvasArray.css("width", "100%"); + break; + default: + break; + } + + $("#mainContent > canvas.error").css("width", innerWidth - 100); + $("#mainContent > canvas.error").css("height", 200); + $("#mainContent").css({maxHeight: maxheight + 5}); kthoom.setSettings(); kthoom.saveSettings(); @@ -477,6 +526,20 @@ function keyHandler(evt) { if (hasModifier) break; showRightPage(); break; + case kthoom.Key.S: + if (hasModifier) break; + settings.pageDisplay = 0; + pageDisplayUpdate(); + kthoom.setSettings(); + kthoom.saveSettings(); + break; + case kthoom.Key.O: + if (hasModifier) break; + settings.pageDisplay = 1; + pageDisplayUpdate(); + kthoom.setSettings(); + kthoom.saveSettings(); + break; case kthoom.Key.L: if (hasModifier) break; settings.rotateTimes--; @@ -484,6 +547,7 @@ function keyHandler(evt) { settings.rotateTimes = 3; } updatePage(); + reloadImages(); break; case kthoom.Key.R: if (hasModifier) break; @@ -492,6 +556,7 @@ function keyHandler(evt) { settings.rotateTimes = 0; } updatePage(); + reloadImages(); break; case kthoom.Key.F: if (hasModifier) break; @@ -507,26 +572,27 @@ function keyHandler(evt) { settings.hflip = true; } updatePage(); + reloadImages(); break; case kthoom.Key.W: if (hasModifier) break; settings.fitMode = kthoom.Key.W; - updateScale(false); + updateScale(); break; case kthoom.Key.H: if (hasModifier) break; settings.fitMode = kthoom.Key.H; - updateScale(false); + updateScale(); break; case kthoom.Key.B: if (hasModifier) break; settings.fitMode = kthoom.Key.B; - updateScale(false); + updateScale(); break; case kthoom.Key.N: if (hasModifier) break; settings.fitMode = kthoom.Key.N; - updateScale(false); + updateScale(); break; case kthoom.Key.SPACE: if (evt.shiftKey) { @@ -545,37 +611,85 @@ function keyHandler(evt) { } } +function drawCanvas() { + var maxheight = innerHeight - 50; + var canvasElement = $(""); + var x = canvasElement[0].getContext("2d"); + canvasElement.addClass("mainImage"); + + switch (settings.fitMode) { + case kthoom.Key.B: + canvasElement.css("maxWidth", "100%"); + canvasElement.css("maxHeight", maxheight + "px"); + break; + case kthoom.Key.H: + canvasElement.css("maxHeight", maxheight + "px"); + break; + case kthoom.Key.W: + canvasElement.css("width", "100%"); + break; + default: + break; + } + + if(settings.pageDisplay === 0) { + canvasElement.addClass("hide"); + } + + //Fill with Placeholder text. setImage will override this + canvasElement.width = innerWidth - 100; + canvasElement.height = 200; + x.fillStyle = "black"; + x.textAlign = "center"; + x.font = "24px sans-serif"; + x.strokeStyle = (settings.theme === "dark") ? "white" : "black"; + x.fillText("Loading Page #" + (currentImage + 1), innerWidth / 2, 100); + + $("#mainContent").append(canvasElement); +} + +function updateArrows() { + if ($('input[name="direction"]:checked').val() === "0") { + $("#prev_page_key").html("←"); + $("#next_page_key").html("→"); + } else { + $("#prev_page_key").html("→"); + $("#next_page_key").html("←"); + } +}; + function init(filename) { var request = new XMLHttpRequest(); request.open("GET", filename); request.responseType = "arraybuffer"; - request.addEventListener("load", function() { + request.addEventListener("load", function () { if (request.status >= 200 && request.status < 300) { loadFromArrayBuffer(request.response); } else { console.warn(request.statusText, request.responseText); } }); + kthoom.loadSettings(); + setTheme(); + updateScale(); request.send(); initProgressClick(); document.body.className += /AppleWebKit/.test(navigator.userAgent) ? " webkit" : ""; - kthoom.loadSettings(); - updateScale(true); $(document).keydown(keyHandler); - $(window).resize(function() { - updateScale(false); + $(window).resize(function () { + updateScale(); }); // Open TOC menu - $("#slider").click(function() { + $("#slider").click(function () { $("#sidebar").toggleClass("open"); $("#main").toggleClass("closed"); $(this).toggleClass("icon-menu icon-right"); // We need this in a timeout because if we call it during the CSS transition, IE11 shakes the page ¯\_(ツ)_/¯ - setTimeout(function() { + setTimeout(function () { // Focus on the TOC or the main content area, depending on which is open $("#main:not(.closed) #mainContent, #sidebar.open #tocView").focus(); scrollTocToActive(); @@ -583,12 +697,12 @@ function init(filename) { }); // Open Settings modal - $("#setting").click(function() { + $("#setting").click(function () { $("#settings-modal").toggleClass("md-show"); }); // On Settings input change - $("#settings input").on("change", function() { + $("#settings input").on("change", function () { // Get either the checked boolean or the assigned value var value = this.type === "checkbox" ? this.checked : this.value; @@ -596,33 +710,41 @@ function init(filename) { value = /^\d+$/.test(value) ? parseInt(value) : value; settings[this.name] = value; + + if (["hflip", "vflip", "rotateTimes"].includes(this.name)) { + reloadImages(); + } else if (this.name === "direction") { + updateDirectionButtons(); + return updateProgress(); + } + updatePage(); - updateScale(false); + updateScale(); }); // Close modal - $(".closer, .overlay").click(function() { + $(".closer, .overlay").click(function () { $(".md-show").removeClass("md-show"); + $("#mainContent").focus(); // focus back on the main container so you use up/down keys without having to click on it }); // TOC thumbnail pagination - $("#thumbnails").on("click", "a", function() { + $("#thumbnails").on("click", "a", function () { currentImage = $(this).data("page") - 1; updatePage(); - if (settings.nextPage === 0) { - $("#mainContent").scrollTop(0); - } }); // Fullscreen mode if (typeof screenfull !== "undefined") { - $("#fullscreen").click(function() { + $("#fullscreen").click(function () { screenfull.toggle($("#container")[0]); + // Focus on main container so you can use up/down keys immediately after fullscreen + $("#mainContent").focus(); }); if (screenfull.raw) { var $button = $("#fullscreen"); - document.addEventListener(screenfull.raw.fullscreenchange, function() { + document.addEventListener(screenfull.raw.fullscreenchange, function () { screenfull.isFullscreen ? $button.addClass("icon-resize-small").removeClass("icon-resize-full") : $button.addClass("icon-resize-full").removeClass("icon-resize-small"); @@ -633,16 +755,16 @@ function init(filename) { // Focus the scrollable area so that keyboard scrolling work as expected $("#mainContent").focus(); - $("#mainContent").swipe( { - swipeRight:function() { + $("#mainContent").swipe({ + swipeRight: function () { showLeftPage(); }, - swipeLeft:function() { + swipeLeft: function () { showRightPage(); }, }); - $("#mainImage").click(function(evt) { - // Firefox does not support offsetX/Y so we have to manually calculate + $(".mainImage").click(function (evt) { + // Firefox does not support offsetX/Y, so we have to manually calculate // where the user clicked in the image. var mainContentWidth = $("#mainContent").width(); var mainContentHeight = $("#mainContent").height(); @@ -676,5 +798,73 @@ function init(filename) { showRightPage(); } }); + + // Scrolling up/down will update current image if a new image is into view (for Long Strip Display) + $("#mainContent").scroll(function (){ + var scroll = $("#mainContent").scrollTop(); + var viewLength = 0; + $(".mainImage").each(function(){ + viewLength += $(this).height(); + }); + if (settings.pageDisplay === 0) { + // Don't trigger the scroll for Single Page + } else if (scroll > prevScrollPosition) { + //Scroll Down + if (currentImage + 1 < imageFiles.length) { + if (currentImageOffset(currentImage + 1) <= 1) { + currentImage = Math.floor((imageFiles.length) / (viewLength-viewLength/(imageFiles.length)) * scroll, 0); + if ( currentImage >= imageFiles.length) { + currentImage = imageFiles.length - 1; + } + console.log(currentImage); + scrollTocToActive(); + updateProgress(); + } + } + } else { + //Scroll Up + if (currentImage - 1 > -1) { + if (currentImageOffset(currentImage - 1) >= 0) { + currentImage = Math.floor((imageFiles.length) / (viewLength-viewLength/(imageFiles.length)) * scroll, 0); + console.log(currentImage); + scrollTocToActive(); + updateProgress(); + } + } + } + // Update scroll position + prevScrollPosition = scroll; + }); } +function currentImageOffset(imageIndex) { + return $(".mainImage").eq(imageIndex).offset().top - $("#mainContent").position().top +} + +function setBookmark() { + // get csrf_token + let csrf_token = $("input[name='csrf_token']").val(); + //This sends a bookmark update to calibreweb. + $.ajax(calibre.bookmarkUrl, { + method: "post", + data: { + csrf_token: csrf_token, + bookmark: currentImage + } + }).fail(function (xhr, status, error) { + console.error(error); + }); +} + +$(function() { + $('input[name="direction"]').change(function () { + updateArrows(); + }); + + $('#left').click(function () { + showLeftPage(); + }); + $('#right').click(function () { + showRightPage(); + }); +}); diff --git a/cps/static/js/libs/Sortable.min.js b/cps/static/js/libs/Sortable.min.js index 4fe7f0c3..17bb16c7 100644 --- a/cps/static/js/libs/Sortable.min.js +++ b/cps/static/js/libs/Sortable.min.js @@ -1,2 +1,2 @@ -/*! Sortable 1.13.0 - MIT | git://github.com/SortableJS/Sortable.git */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return!1}return!1}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"===e[0]?t.parentNode===n&&h(t,e):h(t,e))||o&&t===n)return t;if(t===n)break}while(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode)}var i;return null}var f,p=/\s+/g;function k(t,e,n){if(t&&e)if(t.classList)t.classList[n?"add":"remove"](e);else{var o=(" "+t.className+" ").replace(p," ").replace(" "+e+" "," ");t.className=(o+(n?" "+e:"")).replace(p," ")}}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in o||-1!==e.indexOf("webkit")||(e="-webkit-"+e),o[e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform");o&&"none"!==o&&(n=o+" "+n)}while(!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function g(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i=e.left-n&&r<=e.right+n,i=a>=e.top-n&&a<=e.bottom+n;return n&&o&&i?l=t:void 0}}),l}((t=t.touches?t.touches[0]:t).clientX,t.clientY);if(e){var n={};for(var o in t)t.hasOwnProperty(o)&&(n[o]=t[o]);n.target=n.rootEl=e,n.preventDefault=void 0,n.stopPropagation=void 0,e[j]._onDragOver(n)}}}function kt(t){z&&z.parentNode[j]._isOutsideThisEl(t.target)}function Rt(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[j]=this;var n={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Ot(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Rt.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(var o in O.initializePlugins(this,t,n),n)o in e||(e[o]=n[o]);for(var i in Nt(e),this)"_"===i.charAt(0)&&"function"==typeof this[i]&&(this[i]=this[i].bind(this));this.nativeDraggable=!e.forceFallback&&xt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?d(t,"pointerdown",this._onTapStart):(d(t,"mousedown",this._onTapStart),d(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(d(t,"dragover",this),d(t,"dragenter",this)),bt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,T())}function Xt(t,e,n,o,i,r,a,l){var s,c,u=t[j],d=u.options.onMove;return!window.CustomEvent||w||E?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),d&&(c=d.call(u,s,a)),c}function Yt(t){t.draggable=!1}function Bt(){Dt=!1}function Ft(t){for(var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;n--;)o+=e.charCodeAt(n);return o.toString(36)}function Ht(t){return setTimeout(t,0)}function Lt(t){return clearTimeout(t)}Rt.prototype={constructor:Rt,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(ht=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,z):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(function(t){St.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&St.push(o)}}(o),!z&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=P(l,t.draggable,o,!1))&&l.animated||Z===l)){if(J=F(l),et=F(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return W({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),K("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c&&(c=c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return W({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),K("filter",n,{evt:e}),!0})))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;if(n&&!z&&n.parentNode===r){var s=X(n);if(q=r,G=(z=n).parentNode,V=z.nextSibling,Z=n,ot=a.group,rt={target:Rt.dragged=z,clientX:(e||t).clientX,clientY:(e||t).clientY},ct=rt.clientX-s.left,ut=rt.clientY-s.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,z.style["will-change"]="all",o=function(){K("delayEnded",i,{evt:t}),Rt.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!c&&i.nativeDraggable&&(z.draggable=!0),i._triggerDragStart(t,e),W({sortable:i,name:"choose",originalEvent:t}),k(z,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){g(z,t.trim(),Yt)}),d(l,"dragover",Pt),d(l,"mousemove",Pt),d(l,"touchmove",Pt),d(l,"mouseup",i._onDrop),d(l,"touchend",i._onDrop),d(l,"touchcancel",i._onDrop),c&&this.nativeDraggable&&(this.options.touchStartThreshold=4,z.draggable=!0),K("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(E||w))o();else{if(Rt.eventCanceled)return void this._onDrop();d(l,"mouseup",i._disableDelayedDrag),d(l,"touchend",i._disableDelayedDrag),d(l,"touchcancel",i._disableDelayedDrag),d(l,"mousemove",i._delayedDragTouchMoveHandler),d(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&d(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)}}},_delayedDragTouchMoveHandler:function(t){var e=t.touches?t.touches[0]:t;Math.max(Math.abs(e.clientX-this._lastX),Math.abs(e.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){z&&Yt(z),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;s(t,"mouseup",this._disableDelayedDrag),s(t,"touchend",this._disableDelayedDrag),s(t,"touchcancel",this._disableDelayedDrag),s(t,"mousemove",this._delayedDragTouchMoveHandler),s(t,"touchmove",this._delayedDragTouchMoveHandler),s(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?d(document,"pointermove",this._onTouchMove):d(document,e?"touchmove":"mousemove",this._onTouchMove):(d(z,"dragend",this),d(q,"dragstart",this._onDragStart));try{document.selection?Ht(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){if(vt=!1,q&&z){K("dragStarted",this,{evt:e}),this.nativeDraggable&&d(document,"dragover",kt);var n=this.options;t||k(z,n.dragClass,!1),k(z,n.ghostClass,!0),Rt.active=this,t&&this._appendGhost(),W({sortable:this,name:"start",originalEvent:e})}else this._nulling()},_emulateDragOver:function(){if(at){this._lastX=at.clientX,this._lastY=at.clientY,At();for(var t=document.elementFromPoint(at.clientX,at.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(at.clientX,at.clientY))!==e;)e=t;if(z.parentNode[j]._isOutsideThisEl(t),e)do{if(e[j]){if(e[j]._onDragOver({clientX:at.clientX,clientY:at.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}t=e}while(e=e.parentNode);It()}},_onTouchMove:function(t){if(rt){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=U&&v(U,!0),a=U&&r&&r.a,l=U&&r&&r.d,s=Ct&>&&b(gt),c=(i.clientX-rt.clientX+o.x)/(a||1)+(s?s[0]-Et[0]:0)/(a||1),u=(i.clientY-rt.clientY+o.y)/(l||1)+(s?s[1]-Et[1]:0)/(l||1);if(!Rt.active&&!vt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))o.right+10||t.clientX<=o.right&&t.clientY>o.bottom&&t.clientX>=o.left:t.clientX>o.right&&t.clientY>o.top||t.clientX<=o.right&&t.clientY>o.bottom+10}(n,a,this)&&!g.animated){if(g===z)return N(!1);if(g&&l===n.target&&(s=g),s&&(i=X(s)),!1!==Xt(q,l,z,o,s,i,n,!!s))return O(),l.appendChild(z),G=l,A(),N(!0)}else if(s.parentNode===l){i=X(s);var v,m,b,y=z.parentNode!==l,w=!function(t,e,n){var o=n?t.left:t.top,i=n?t.right:t.bottom,r=n?t.width:t.height,a=n?e.left:e.top,l=n?e.right:e.bottom,s=n?e.width:e.height;return o===a||i===l||o+r/2===a+s/2}(z.animated&&z.toRect||o,s.animated&&s.toRect||i,a),E=a?"top":"left",D=Y(s,"top","top")||Y(z,"top","top"),S=D?D.scrollTop:void 0;if(ht!==s&&(m=i[E],yt=!1,wt=!w&&e.invertSwap||y),0!==(v=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,u=o?n.top:n.left,d=o?n.bottom:n.right,h=!1;if(!a)if(l&&ptt.length)&&(e=t.length);for(var n=0,o=new Array(e);n"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}function N(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"!==e[0]||t.parentNode===n)&&p(t,e)||o&&t===n)return t}while(t!==n&&(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode))}var i;return null}var g,m=/\s+/g;function I(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(m," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(m," ")))}function P(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=!(e in o||-1!==e.indexOf("webkit"))?"-webkit-"+e:e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=P(t,"transform")}while(o&&"none"!==o&&(n=o+" "+n),!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function b(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i=n.left-e&&i<=n.right+e,e=r>=n.top-e&&r<=n.bottom+e;return o&&e?a=t:void 0}}),a);if(e){var n,o={};for(n in t)t.hasOwnProperty(n)&&(o[n]=t[n]);o.target=o.rootEl=e,o.preventDefault=void 0,o.stopPropagation=void 0,e[j]._onDragOver(o)}}var i,r,a}function Yt(t){q&&q.parentNode[j]._isOutsideThisEl(t.target)}function Bt(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[j]=this;var n,o,i={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return It(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Bt.supportPointer&&"PointerEvent"in window&&!u,emptyInsertThreshold:5};for(n in K.initializePlugins(this,t,i),i)n in e||(e[n]=i[n]);for(o in Pt(e),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&Mt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?h(t,"pointerdown",this._onTapStart):(h(t,"mousedown",this._onTapStart),h(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(h(t,"dragover",this),h(t,"dragenter",this)),Et.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,x())}function Ft(t,e,n,o,i,r,a,l){var s,c,u=t[j],d=u.options.onMove;return!window.CustomEvent||y||w?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||k(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),c=d?d.call(u,s,a):c}function jt(t){t.draggable=!1}function Ht(){Ct=!1}function Lt(t){return setTimeout(t,0)}function Kt(t){return clearTimeout(t)}Bt.prototype={constructor:Bt,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(gt=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,q):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(!function(t){Tt.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&Tt.push(o)}}(o),!q&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled)&&!s.isContentEditable&&(this.nativeDraggable||!u||!l||"SELECT"!==l.tagName.toUpperCase())&&!((l=N(l,t.draggable,o,!1))&&l.animated||J===l)){if(nt=B(l),it=B(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return U({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),z("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c=c&&c.split(",").some(function(t){if(t=N(s,t.trim(),o,!1))return U({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),z("filter",n,{evt:e}),!0}))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!N(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;n&&!q&&n.parentNode===r&&(o=k(n),$=r,V=(q=n).parentNode,Q=q.nextSibling,J=n,at=a.group,st={target:Bt.dragged=q,clientX:(e||t).clientX,clientY:(e||t).clientY},ht=st.clientX-o.left,ft=st.clientY-o.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,q.style["will-change"]="all",o=function(){z("delayEnded",i,{evt:t}),Bt.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!s&&i.nativeDraggable&&(q.draggable=!0),i._triggerDragStart(t,e),U({sortable:i,name:"choose",originalEvent:t}),I(q,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){b(q,t.trim(),jt)}),h(l,"dragover",Xt),h(l,"mousemove",Xt),h(l,"touchmove",Xt),h(l,"mouseup",i._onDrop),h(l,"touchend",i._onDrop),h(l,"touchcancel",i._onDrop),s&&this.nativeDraggable&&(this.options.touchStartThreshold=4,q.draggable=!0),z("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(w||y)?o():Bt.eventCanceled?this._onDrop():(h(l,"mouseup",i._disableDelayedDrag),h(l,"touchend",i._disableDelayedDrag),h(l,"touchcancel",i._disableDelayedDrag),h(l,"mousemove",i._delayedDragTouchMoveHandler),h(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&h(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)))},_delayedDragTouchMoveHandler:function(t){t=t.touches?t.touches[0]:t;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){q&&jt(q),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;f(t,"mouseup",this._disableDelayedDrag),f(t,"touchend",this._disableDelayedDrag),f(t,"touchcancel",this._disableDelayedDrag),f(t,"mousemove",this._delayedDragTouchMoveHandler),f(t,"touchmove",this._delayedDragTouchMoveHandler),f(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?h(document,"pointermove",this._onTouchMove):h(document,e?"touchmove":"mousemove",this._onTouchMove):(h(q,"dragend",this),h($,"dragstart",this._onDragStart));try{document.selection?Lt(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){var n;yt=!1,$&&q?(z("dragStarted",this,{evt:e}),this.nativeDraggable&&h(document,"dragover",Yt),n=this.options,t||I(q,n.dragClass,!1),I(q,n.ghostClass,!0),Bt.active=this,t&&this._appendGhost(),U({sortable:this,name:"start",originalEvent:e})):this._nulling()},_emulateDragOver:function(){if(ct){this._lastX=ct.clientX,this._lastY=ct.clientY,kt();for(var t=document.elementFromPoint(ct.clientX,ct.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(ct.clientX,ct.clientY))!==e;)e=t;if(q.parentNode[j]._isOutsideThisEl(t),e)do{if(e[j])if(e[j]._onDragOver({clientX:ct.clientX,clientY:ct.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}while(e=(t=e).parentNode);Rt()}},_onTouchMove:function(t){if(st){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=Z&&v(Z,!0),a=Z&&r&&r.a,l=Z&&r&&r.d,e=Ot&&bt&&E(bt),a=(i.clientX-st.clientX+o.x)/(a||1)+(e?e[0]-_t[0]:0)/(a||1),l=(i.clientY-st.clientY+o.y)/(l||1)+(e?e[1]-_t[1]:0)/(l||1);if(!Bt.active&&!yt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))n.right+10||t.clientX<=n.right&&t.clientY>n.bottom&&t.clientX>=n.left:t.clientX>n.right&&t.clientY>n.top||t.clientX<=n.right&&t.clientY>n.bottom+10}(n,r,this)&&!g.animated){if(g===q)return O(!1);if((l=g&&a===n.target?g:l)&&(w=k(l)),!1!==Ft($,a,q,o,l,w,n,!!l))return x(),g&&g.nextSibling?a.insertBefore(q,g.nextSibling):a.appendChild(q),V=a,A(),O(!0)}else if(g&&function(t,e,n){n=k(X(n.el,0,n.options,!0));return e?t.clientX-1||Math.floor(e)!==e)}function u(t){var e=["-webkit-","-webkit-","-moz-","-o-","-ms-"],i=t.toLowerCase(),n=["Webkit","webkit","Moz","O","ms"].length;if("undefined"==typeof document||void 0!==document.body.style[i])return t;for(var r=0;re?1:t=0?h:h+1:0===s?h:-1===s?g(t,e,i,h,a):g(t,e,i,o,h))}function v(t,e,i,n,r){var s,o=n||0,a=r||e.length,h=parseInt(o+(a-o)/2);return i||(i=function(t,e){return t>e?1:t-1}function O(t,e){return new Blob([t],{type:e})}function C(t,e){var i=O(t,e);return s.createObjectURL(i)}function T(t){return s.revokeObjectURL(t)}function k(t,e){if("string"==typeof t)return"data:"+e+";base64,"+btoa(encodeURIComponent(t))}function R(t){return Object.prototype.toString.call(t).slice(8,-1)}function L(t,e,i){var r;return r="undefined"==typeof DOMParser||i?n.DOMParser:DOMParser,65279===t.charCodeAt(0)&&(t=t.slice(1)),(new r).parseFromString(t,e)}function I(t,e){var i;if(!t)throw new Error("No Element Provided");return void 0!==t.querySelector?t.querySelector(e):(i=t.getElementsByTagName(e)).length?i[0]:void 0}function j(t,e){return void 0!==t.querySelector?t.querySelectorAll(e):t.getElementsByTagName(e)}function N(t,e,i){var n,r;if(void 0!==t.querySelector){for(var s in e+="[",i)e+=s+"~='"+i[s]+"'";return e+="]",t.querySelector(e)}if(n=t.getElementsByTagName(e),r=Array.prototype.slice.call(n,0).filter((function(t){for(var e in i)if(t.getAttribute(e)===i[e])return!0;return!1})))return r[0]}function A(t,e){void 0!==(t.ownerDocument||t).createTreeWalker?P(t,e,NodeFilter.SHOW_TEXT):D(t,(function(t){t&&3===t.nodeType&&e(t)}))}function P(t,e,i){var n=document.createTreeWalker(t,i,null,!1);let r;for(;r=n.nextNode();)e(r)}function D(t,e){if(e(t))return!0;if(t=t.firstChild)do{if(D(t,e))return!0;t=t.nextSibling}while(t)}function z(t){return new Promise((function(e,i){var n=new FileReader;n.readAsDataURL(t),n.onloadend=function(){e(n.result)}}))}function B(){this.resolve=null,this.reject=null,this.id=o(),this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e}),Object.freeze(this)}function q(t,e,i){var n;if(void 0!==t.querySelector&&(n=t.querySelector(`${e}[*|type="${i}"]`)),n&&0!==n.length)return n;n=j(t,e);for(var r=0;r1&&(e=n[1],i.terminal=this.parseTerminal(e)),""===r[0]&&r.shift(),i.steps=r.map(function(t){return this.parseStep(t)}.bind(this)),i}parseStep(t){var e,i,n,r,s;if((r=t.match(/\[(.*)\]/))&&r[1]&&(s=r[1]),i=parseInt(t),!isNaN(i))return i%2==0?(e="element",n=i/2-1):(e="text",n=(i-1)/2),{type:e,index:n,id:s||null}}parseTerminal(t){var e,i,r=t.match(/\[(.*)\]/);return r&&r[1]?(e=parseInt(t.split("[")[0]),i=r[1]):e=parseInt(t),Object(n.isNumber)(e)||(e=null),{offset:e,assertion:i}}getChapterComponent(t){return t.split("!")[0]}getPathComponent(t){var e=t.split("!");if(e[1]){return e[1].split(",")[0]}}getRange(t){var e=t.split(",");return 3===e.length&&[e[1],e[2]]}getCharecterOffsetComponent(t){return t.split(":")[1]||""}joinSteps(t){return t?t.map((function(t){var e="";return"element"===t.type&&(e+=2*(t.index+1)),"text"===t.type&&(e+=1+2*t.index),t.id&&(e+="["+t.id+"]"),e})).join("/"):""}segmentString(t){var e="/";return e+=this.joinSteps(t.steps),t.terminal&&null!=t.terminal.offset&&(e+=":"+t.terminal.offset),t.terminal&&null!=t.terminal.assertion&&(e+="["+t.terminal.assertion+"]"),e}toString(){var t="epubcfi(";return t+=this.segmentString(this.base),t+="!",t+=this.segmentString(this.path),this.range&&this.start&&(t+=",",t+=this.segmentString(this.start)),this.range&&this.end&&(t+=",",t+=this.segmentString(this.end)),t+=")"}compare(t,e){var i,n,s,o;if("string"==typeof t&&(t=new r(t)),"string"==typeof e&&(e=new r(e)),t.spinePos>e.spinePos)return 1;if(t.spinePosn[a].index)return 1;if(i[a].indexo.offset?1:s.offset=0&&(r.terminal.offset=e,"text"!=r.steps[r.steps.length-1].type&&r.steps.push({type:"text",index:0})),r}equalStep(t,e){return!(!t||!e)&&(t.index===e.index&&t.id===e.id&&t.type===e.type)}fromRange(t,e,i){var n={range:!1,base:{},path:{},start:null,end:null},r=t.startContainer,s=t.endContainer,o=t.startOffset,a=t.endOffset,h=!1;if(i&&(h=null!=r.ownerDocument.querySelector("."+i)),"string"==typeof e?(n.base=this.parseComponent(e),n.spinePos=n.base.steps[1].index):"object"==typeof e&&(n.base=e),t.collapsed)h&&(o=this.patchOffset(r,o,i)),n.path=this.pathTo(r,o,i);else{n.range=!0,h&&(o=this.patchOffset(r,o,i)),n.start=this.pathTo(r,o,i),h&&(a=this.patchOffset(s,a,i)),n.end=this.pathTo(s,a,i),n.path={steps:[],terminal:null};var l,c=n.start.steps.length;for(l=0;l0&&3===r&&3===s?o[n]=a:e===r&&(a+=1,o[n]=a),s=r;return o}position(t){var e,i;return 1===t.nodeType?((e=t.parentNode.children)||(e=Object(n.findChildren)(t.parentNode)),i=Array.prototype.indexOf.call(e,t)):i=(e=this.textNodes(t.parentNode)).indexOf(t),i}filteredPosition(t,e){var i,n;return 1===t.nodeType?(i=t.parentNode.children,n=this.normalizedMap(i,1,e)):(i=t.parentNode.childNodes,t.parentNode.classList.contains(e)&&(i=(t=t.parentNode).parentNode.childNodes),n=this.normalizedMap(i,3,e)),n[Array.prototype.indexOf.call(i,t)]}stepsToXpath(t){var e=[".","*"];return t.forEach((function(t){var i=t.index+1;t.id?e.push("*[position()="+i+" and @id='"+t.id+"']"):"text"===t.type?e.push("text()["+i+"]"):e.push("*["+i+"]")})),e.join("/")}stepsToQuerySelector(t){var e=["html"];return t.forEach((function(t){var i=t.index+1;t.id?e.push("#"+t.id):"text"===t.type||e.push("*:nth-child("+i+")")})),e.join(">")}textNodes(t,e){return Array.prototype.slice.call(t.childNodes).filter((function(t){return 3===t.nodeType||!(!e||!t.classList.contains(e))}))}walkToNode(t,e,i){var r,s,o=e||document,a=o.documentElement,h=t.length;for(s=0;s(s=(r=a[t]).textContent.length))){o=1===r.nodeType?r.childNodes[0]:r;break}e-=s}}return{container:o,offset:e}}toRange(t,e){var i,r,s,o,a,h,l,c,u=t||document,d=!!e&&null!=u.querySelector("."+e);if(i=void 0!==u.createRange?u.createRange():new n.RangeObject,this.range?(r=this.start,h=this.path.steps.concat(r.steps),o=this.findNode(h,u,d?e:null),s=this.end,l=this.path.steps.concat(s.steps),a=this.findNode(l,u,d?e:null)):(r=this.path,h=this.path.steps,o=this.findNode(this.path.steps,u,d?e:null)),!o)return console.log("No startContainer found for",this.toString()),null;try{null!=r.terminal.offset?i.setStart(o,r.terminal.offset):i.setStart(o,0)}catch(t){c=this.fixMiss(h,r.terminal.offset,u,d?e:null),i.setStart(c.container,c.offset)}if(a)try{null!=s.terminal.offset?i.setEnd(a,s.terminal.offset):i.setEnd(a,0)}catch(t){c=this.fixMiss(l,this.end.terminal.offset,u,d?e:null),i.setEnd(c.container,c.offset)}return i}isCfiString(t){return"string"==typeof t&&0===t.indexOf("epubcfi(")&&")"===t[t.length-1]}generateChapterComponent(t,e,i){var n="/"+2*(t+1)+"/";return n+=2*(parseInt(e)+1),i&&(n+="["+i+"]"),n}collapse(t){this.range&&(this.range=!1,t?(this.path.steps=this.path.steps.concat(this.start.steps),this.path.terminal=this.start.terminal):(this.path.steps=this.path.steps.concat(this.end.steps),this.path.terminal=this.end.terminal))}}e.a=r},function(t,e,i){"use strict";var n,r,s,o,a,h,l,c=i(108),u=i(122),d=Function.prototype.apply,f=Function.prototype.call,p=Object.create,g=Object.defineProperty,v=Object.defineProperties,m=Object.prototype.hasOwnProperty,y={configurable:!0,enumerable:!1,writable:!0};r=function(t,e){var i,r;return u(e),r=this,n.call(this,t,i=function(){s.call(r,t,i),d.call(e,this,arguments)}),i.__eeOnceListener__=e,this},a={on:n=function(t,e){var i;return u(e),m.call(this,"__ee__")?i=this.__ee__:(i=y.value=p(null),g(this,"__ee__",y),y.value=null),i[t]?"object"==typeof i[t]?i[t].push(e):i[t]=[i[t],e]:i[t]=e,this},once:r,off:s=function(t,e){var i,n,r,s;if(u(e),!m.call(this,"__ee__"))return this;if(!(i=this.__ee__)[t])return this;if("object"==typeof(n=i[t]))for(s=0;r=n[s];++s)r!==e&&r.__eeOnceListener__!==e||(2===n.length?i[t]=n[s?0:1]:n.splice(s,1));else n!==e&&n.__eeOnceListener__!==e||delete i[t];return this},emit:o=function(t){var e,i,n,r,s;if(m.call(this,"__ee__")&&(r=this.__ee__[t]))if("object"==typeof r){for(i=arguments.length,s=new Array(i-1),e=1;e-1&&(t=new URL(t).pathname),e=this.parse(t),this.path=t,this.isDirectory(t)?this.directory=t:this.directory=e.dir+"/",this.filename=e.base,this.extension=e.ext.slice(1)}parse(t){return r.a.parse(t)}isAbsolute(t){return r.a.isAbsolute(t||this.path)}isDirectory(t){return"/"===t.charAt(t.length-1)}resolve(t){return r.a.resolve(this.directory,t)}relative(t){return t&&t.indexOf("://")>-1?t:r.a.relative(this.directory,t)}splitPath(t){return this.splitPathRe.exec(t).slice(1)}toString(){return this.path}}},function(t,e,i){"use strict";i(14),i(20);var n=i(4),r=i(9),s=i.n(r);e.a=class{constructor(t,e){var i=t.indexOf("://")>-1,r=t;if(this.Url=void 0,this.href=t,this.protocol="",this.origin="",this.hash="",this.hash="",this.search="",this.base=e,!i&&!1!==e&&"string"!=typeof e&&window&&window.location&&(this.base=window.location.href),i||this.base)try{this.base?this.Url=new URL(t,this.base):this.Url=new URL(t),this.href=this.Url.href,this.protocol=this.Url.protocol,this.origin=this.Url.origin,this.hash=this.Url.hash,this.search=this.Url.search,r=this.Url.pathname+(this.Url.search?this.Url.search:"")}catch(t){this.Url=void 0,this.base&&(r=new n.a(this.base).resolve(r))}this.Path=new n.a(r),this.directory=this.Path.directory,this.filename=this.Path.filename,this.extension=this.Path.extension}path(){return this.Path}resolve(t){var e;return t.indexOf("://")>-1?t:(e=s.a.resolve(this.directory,t),this.origin+e)}relative(t){return s.a.relative(t,this.directory)}toString(){return this.href}}},function(t,e,i){"use strict";i(14);e.a=class{constructor(t){this.context=t||this,this.hooks=[]}register(){for(var t=0;t2){for(var a=n.length-1,h=a;h>=0&&47!==n.charCodeAt(h);--h);if(h!==a){n=-1===h?"":n.slice(0,h),r=o,s=0;continue}}else if(2===n.length||1===n.length){n="",r=o,s=0;continue}e&&(n.length>0?n+="/..":n="..")}else n.length>0?n+="/"+t.slice(r+1,o):n=t.slice(r+1,o);r=o,s=0}else 46===i&&-1!==s?++s:s=-1}return n}var o={resolve:function(){for(var t,e="",i=!1,o=arguments.length-1;o>=-1&&!i;o--){var a;o>=0?a=arguments[o]:(void 0===t&&(t=n.cwd()),a=t),r(a),0!==a.length&&(e=a+"/"+e,i=47===a.charCodeAt(0))}return e=s(e,!i),i?e.length>0?"/"+e:"/":e.length>0?e:"."},normalize:function(t){if(r(t),0===t.length)return".";var e=47===t.charCodeAt(0),i=47===t.charCodeAt(t.length-1);return 0!==(t=s(t,!e)).length||e||(t="."),t.length>0&&i&&(t+="/"),e?"/"+t:t},isAbsolute:function(t){return r(t),t.length>0&&47===t.charCodeAt(0)},join:function(){if(0===arguments.length)return".";for(var t,e=0;e0&&(void 0===t?t=i:t+="/"+i)}return void 0===t?".":o.normalize(t)},relative:function(t,e){if(r(t),r(e),t===e)return"";if((t=o.resolve(t))===(e=o.resolve(e)))return"";for(var i=1;il){if(47===e.charCodeAt(a+u))return e.slice(a+u+1);if(0===u)return e.slice(a+u)}else s>l&&(47===t.charCodeAt(i+u)?c=u:0===u&&(c=0));break}var d=t.charCodeAt(i+u);if(d!==e.charCodeAt(a+u))break;47===d&&(c=u)}var f="";for(u=i+c+1;u<=n;++u)u!==n&&47!==t.charCodeAt(u)||(0===f.length?f+="..":f+="/..");return f.length>0?f+e.slice(a+c):(a+=c,47===e.charCodeAt(a)&&++a,e.slice(a))},_makeLong:function(t){return t},dirname:function(t){if(r(t),0===t.length)return".";for(var e=t.charCodeAt(0),i=47===e,n=-1,s=!0,o=t.length-1;o>=1;--o)if(47===(e=t.charCodeAt(o))){if(!s){n=o;break}}else s=!1;return-1===n?i?"/":".":i&&1===n?"//":t.slice(0,n)},basename:function(t,e){if(void 0!==e&&"string"!=typeof e)throw new TypeError('"ext" argument must be a string');r(t);var i,n=0,s=-1,o=!0;if(void 0!==e&&e.length>0&&e.length<=t.length){if(e.length===t.length&&e===t)return"";var a=e.length-1,h=-1;for(i=t.length-1;i>=0;--i){var l=t.charCodeAt(i);if(47===l){if(!o){n=i+1;break}}else-1===h&&(o=!1,h=i+1),a>=0&&(l===e.charCodeAt(a)?-1==--a&&(s=i):(a=-1,s=h))}return n===s?s=h:-1===s&&(s=t.length),t.slice(n,s)}for(i=t.length-1;i>=0;--i)if(47===t.charCodeAt(i)){if(!o){n=i+1;break}}else-1===s&&(o=!1,s=i+1);return-1===s?"":t.slice(n,s)},extname:function(t){r(t);for(var e=-1,i=0,n=-1,s=!0,o=0,a=t.length-1;a>=0;--a){var h=t.charCodeAt(a);if(47!==h)-1===n&&(s=!1,n=a+1),46===h?-1===e?e=a:1!==o&&(o=1):-1!==e&&(o=-1);else if(!s){i=a+1;break}}return-1===e||-1===n||0===o||1===o&&e===n-1&&e===i+1?"":t.slice(e,n)},format:function(t){if(null===t||"object"!=typeof t)throw new TypeError('Parameter "pathObject" must be an object, not '+typeof t);return function(t,e){var i=e.dir||e.root,n=e.base||(e.name||"")+(e.ext||"");return i?i===e.root?i+n:i+t+n:n}("/",t)},parse:function(t){r(t);var e={root:"",dir:"",base:"",ext:"",name:""};if(0===t.length)return e;var i,n=t.charCodeAt(0),s=47===n;s?(e.root="/",i=1):i=0;for(var o=-1,a=0,h=-1,l=!0,c=t.length-1,u=0;c>=i;--c)if(47!==(n=t.charCodeAt(c)))-1===h&&(l=!1,h=c+1),46===n?-1===o?o=c:1!==u&&(u=1):-1!==o&&(u=-1);else if(!l){a=c+1;break}return-1===o||-1===h||0===u||1===u&&o===h-1&&o===a+1?-1!==h&&(e.base=e.name=0===a&&s?t.slice(1,h):t.slice(a,h)):(0===a&&s?(e.name=t.slice(1,o),e.base=t.slice(1,h)):(e.name=t.slice(a,o),e.base=t.slice(a,h)),e.ext=t.slice(o,h)),a>0?e.dir=t.slice(0,a-1):s&&(e.dir="/"),e},sep:"/",delimiter:":",posix:null};t.exports=o},function(t,e){var i={}.hasOwnProperty;t.exports=function(t,e){return i.call(t,e)}},function(t,e,i){"use strict";i.d(e,"a",(function(){return s})),i.d(e,"b",(function(){return o})),i.d(e,"d",(function(){return a})),i.d(e,"c",(function(){return h})),i.d(e,"e",(function(){return l}));i(24);var n=i(0),r=i(5);i(4);function s(t,e){var i,r,s=e.url,o=s.indexOf("://")>-1;t&&(r=Object(n.qs)(t,"head"),(i=Object(n.qs)(r,"base"))||(i=t.createElement("base"),r.insertBefore(i,r.firstChild)),!o&&window&&window.location&&(s=window.location.origin+s),i.setAttribute("href",s))}function o(t,e){var i,r,s=e.canonical;t&&(i=Object(n.qs)(t,"head"),(r=Object(n.qs)(i,"link[rel='canonical']"))?r.setAttribute("href",s):((r=t.createElement("link")).setAttribute("rel","canonical"),r.setAttribute("href",s),i.appendChild(r)))}function a(t,e){var i,r,s=e.idref;t&&(i=Object(n.qs)(t,"head"),(r=Object(n.qs)(i,"link[property='dc.identifier']"))?r.setAttribute("content",s):((r=t.createElement("meta")).setAttribute("name","dc.identifier"),r.setAttribute("content",s),i.appendChild(r)))}function h(t,e){var i=t.querySelectorAll("a[href]");if(i.length)for(var s=Object(n.qs)(t.ownerDocument,"base"),o=s?s.getAttribute("href"):void 0,a=function(t){var i=t.getAttribute("href");if(0!==i.indexOf("mailto:"))if(i.indexOf("://")>-1)t.setAttribute("target","_blank");else{var n;try{n=new r.a(i,o)}catch(t){}t.onclick=function(){return n&&n.hash?e(n.Path.path+n.hash):e(n?n.Path.path:i),!1}}}.bind(this),h=0;h4)return t;for(i=[],n=0;n1&&"0"==r.charAt(0)&&(s=R.test(r)?16:8,r=r.slice(8==s?1:2)),""===r)o=0;else{if(!(10==s?I:8==s?L:j).test(r))return t;o=parseInt(r,s)}i.push(o)}for(n=0;n=O(256,5-e))return null}else if(o>255)return null;for(a=i.pop(),n=0;n6)return;for(n=0;d();){if(r=null,n>0){if(!("."==d()&&n<4))return;u++}if(!k.test(d()))return;for(;k.test(d());){if(s=parseInt(d(),10),null===r)r=s;else{if(0==r)return;r=10*r+s}if(r>255)return;u++}h[l]=256*h[l]+r,2!=++n&&4!=n||l++}if(4!=n)return;break}if(":"==d()){if(u++,!d())return}else if(d())return;h[l++]=e}else{if(null!==c)return;u++,c=++l}}if(null!==c)for(o=l-c,l=7;0!=l&&o>0;)a=h[l],h[l--]=h[c+o-1],h[c+--o]=a;else if(8!=l)return;return h},M=function(t){var e,i,n,r;if("number"==typeof t){for(e=[],i=0;i<4;i++)e.unshift(t%256),t=_(t/256);return e.join(".")}if("object"==typeof t){for(e="",n=function(t){for(var e=null,i=1,n=null,r=0,s=0;s<8;s++)0!==t[s]?(r>i&&(e=n,i=r),n=null,r=0):(null===n&&(n=s),++r);return r>i&&(e=n,i=r),e}(t),i=0;i<8;i++)r&&0===t[i]||(r&&(r=!1),n===i?(e+=i?":":"::",r=!0):(e+=t[i].toString(16),i<7&&(e+=":")));return"["+e+"]"}return t},U={},F=d({},U,{" ":1,'"':1,"<":1,">":1,"`":1}),W=d({},F,{"#":1,"?":1,"{":1,"}":1}),H=d({},W,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),V=function(t,e){var i=p(t,0);return i>32&&i<127&&!u(e,t)?t:encodeURIComponent(t)},X={ftp:21,file:null,http:80,https:443,ws:80,wss:443},G=function(t){return u(X,t.scheme)},Y=function(t){return""!=t.username||""!=t.password},$=function(t){return!t.host||t.cannotBeABaseURL||"file"==t.scheme},K=function(t,e){var i;return 2==t.length&&C.test(t.charAt(0))&&(":"==(i=t.charAt(1))||!e&&"|"==i)},Z=function(t){var e;return t.length>1&&K(t.slice(0,2))&&(2==t.length||"/"===(e=t.charAt(2))||"\\"===e||"?"===e||"#"===e)},J=function(t){var e=t.path,i=e.length;!i||"file"==t.scheme&&1==i&&K(e[0],!0)||e.pop()},Q=function(t){return"."===t||"%2e"===t.toLowerCase()},tt={},et={},it={},nt={},rt={},st={},ot={},at={},ht={},lt={},ct={},ut={},dt={},ft={},pt={},gt={},vt={},mt={},yt={},bt={},wt={},xt=function(t,e,i,r){var s,o,a,h,l,c=i||tt,d=0,p="",g=!1,v=!1,m=!1;for(i||(t.scheme="",t.username="",t.password="",t.host=null,t.port=null,t.path=[],t.query=null,t.fragment=null,t.cannotBeABaseURL=!1,e=e.replace(P,"")),e=e.replace(D,""),s=f(e);d<=s.length;){switch(o=s[d],c){case tt:if(!o||!C.test(o)){if(i)return"Invalid scheme";c=it;continue}p+=o.toLowerCase(),c=et;break;case et:if(o&&(T.test(o)||"+"==o||"-"==o||"."==o))p+=o.toLowerCase();else{if(":"!=o){if(i)return"Invalid scheme";p="",c=it,d=0;continue}if(i&&(G(t)!=u(X,p)||"file"==p&&(Y(t)||null!==t.port)||"file"==t.scheme&&!t.host))return;if(t.scheme=p,i)return void(G(t)&&X[t.scheme]==t.port&&(t.port=null));p="","file"==t.scheme?c=ft:G(t)&&r&&r.scheme==t.scheme?c=nt:G(t)?c=at:"/"==s[d+1]?(c=rt,d++):(t.cannotBeABaseURL=!0,t.path.push(""),c=yt)}break;case it:if(!r||r.cannotBeABaseURL&&"#"!=o)return"Invalid scheme";if(r.cannotBeABaseURL&&"#"==o){t.scheme=r.scheme,t.path=r.path.slice(),t.query=r.query,t.fragment="",t.cannotBeABaseURL=!0,c=wt;break}c="file"==r.scheme?ft:st;continue;case nt:if("/"!=o||"/"!=s[d+1]){c=st;continue}c=ht,d++;break;case rt:if("/"==o){c=lt;break}c=mt;continue;case st:if(t.scheme=r.scheme,o==n)t.username=r.username,t.password=r.password,t.host=r.host,t.port=r.port,t.path=r.path.slice(),t.query=r.query;else if("/"==o||"\\"==o&&G(t))c=ot;else if("?"==o)t.username=r.username,t.password=r.password,t.host=r.host,t.port=r.port,t.path=r.path.slice(),t.query="",c=bt;else{if("#"!=o){t.username=r.username,t.password=r.password,t.host=r.host,t.port=r.port,t.path=r.path.slice(),t.path.pop(),c=mt;continue}t.username=r.username,t.password=r.password,t.host=r.host,t.port=r.port,t.path=r.path.slice(),t.query=r.query,t.fragment="",c=wt}break;case ot:if(!G(t)||"/"!=o&&"\\"!=o){if("/"!=o){t.username=r.username,t.password=r.password,t.host=r.host,t.port=r.port,c=mt;continue}c=lt}else c=ht;break;case at:if(c=ht,"/"!=o||"/"!=p.charAt(d+1))continue;d++;break;case ht:if("/"!=o&&"\\"!=o){c=lt;continue}break;case lt:if("@"==o){g&&(p="%40"+p),g=!0,a=f(p);for(var y=0;y65535)return"Invalid port";t.port=G(t)&&x===X[t.scheme]?null:x,p=""}if(i)return;c=vt;continue}return"Invalid port"}p+=o;break;case ft:if(t.scheme="file","/"==o||"\\"==o)c=pt;else{if(!r||"file"!=r.scheme){c=mt;continue}if(o==n)t.host=r.host,t.path=r.path.slice(),t.query=r.query;else if("?"==o)t.host=r.host,t.path=r.path.slice(),t.query="",c=bt;else{if("#"!=o){Z(s.slice(d).join(""))||(t.host=r.host,t.path=r.path.slice(),J(t)),c=mt;continue}t.host=r.host,t.path=r.path.slice(),t.query=r.query,t.fragment="",c=wt}}break;case pt:if("/"==o||"\\"==o){c=gt;break}r&&"file"==r.scheme&&!Z(s.slice(d).join(""))&&(K(r.path[0],!0)?t.path.push(r.path[0]):t.host=r.host),c=mt;continue;case gt:if(o==n||"/"==o||"\\"==o||"?"==o||"#"==o){if(!i&&K(p))c=mt;else if(""==p){if(t.host="",i)return;c=vt}else{if(h=z(t,p))return h;if("localhost"==t.host&&(t.host=""),i)return;p="",c=vt}continue}p+=o;break;case vt:if(G(t)){if(c=mt,"/"!=o&&"\\"!=o)continue}else if(i||"?"!=o)if(i||"#"!=o){if(o!=n&&(c=mt,"/"!=o))continue}else t.fragment="",c=wt;else t.query="",c=bt;break;case mt:if(o==n||"/"==o||"\\"==o&&G(t)||!i&&("?"==o||"#"==o)){if(".."===(l=(l=p).toLowerCase())||"%2e."===l||".%2e"===l||"%2e%2e"===l?(J(t),"/"==o||"\\"==o&&G(t)||t.path.push("")):Q(p)?"/"==o||"\\"==o&&G(t)||t.path.push(""):("file"==t.scheme&&!t.path.length&&K(p)&&(t.host&&(t.host=""),p=p.charAt(0)+":"),t.path.push(p)),p="","file"==t.scheme&&(o==n||"?"==o||"#"==o))for(;t.path.length>1&&""===t.path[0];)t.path.shift();"?"==o?(t.query="",c=bt):"#"==o&&(t.fragment="",c=wt)}else p+=V(o,W);break;case yt:"?"==o?(t.query="",c=bt):"#"==o?(t.fragment="",c=wt):o!=n&&(t.path[0]+=V(o,U));break;case bt:i||"#"!=o?o!=n&&("'"==o&&G(t)?t.query+="%27":t.query+="#"==o?"%23":V(o,U)):(t.fragment="",c=wt);break;case wt:o!=n&&(t.fragment+=V(o,F))}d++}},Et=function(t){var e,i,n=c(this,Et,"URL"),r=arguments.length>1?arguments[1]:void 0,o=String(t),a=E(n,{type:"URL"});if(void 0!==r)if(r instanceof Et)e=S(r);else if(i=xt(e={},String(r)))throw TypeError(i);if(i=xt(a,o,null,e))throw TypeError(i);var h=a.searchParams=new w,l=x(h);l.updateSearchParams(a.query),l.updateURL=function(){a.query=String(h)||null},s||(n.href=_t.call(n),n.origin=Ot.call(n),n.protocol=Ct.call(n),n.username=Tt.call(n),n.password=kt.call(n),n.host=Rt.call(n),n.hostname=Lt.call(n),n.port=It.call(n),n.pathname=jt.call(n),n.search=Nt.call(n),n.searchParams=At.call(n),n.hash=Pt.call(n))},St=Et.prototype,_t=function(){var t=S(this),e=t.scheme,i=t.username,n=t.password,r=t.host,s=t.port,o=t.path,a=t.query,h=t.fragment,l=e+":";return null!==r?(l+="//",Y(t)&&(l+=i+(n?":"+n:"")+"@"),l+=M(r),null!==s&&(l+=":"+s)):"file"==e&&(l+="//"),l+=t.cannotBeABaseURL?o[0]:o.length?"/"+o.join("/"):"",null!==a&&(l+="?"+a),null!==h&&(l+="#"+h),l},Ot=function(){var t=S(this),e=t.scheme,i=t.port;if("blob"==e)try{return new URL(e.path[0]).origin}catch(t){return"null"}return"file"!=e&&G(t)?e+"://"+M(t.host)+(null!==i?":"+i:""):"null"},Ct=function(){return S(this).scheme+":"},Tt=function(){return S(this).username},kt=function(){return S(this).password},Rt=function(){var t=S(this),e=t.host,i=t.port;return null===e?"":null===i?M(e):M(e)+":"+i},Lt=function(){var t=S(this).host;return null===t?"":M(t)},It=function(){var t=S(this).port;return null===t?"":String(t)},jt=function(){var t=S(this),e=t.path;return t.cannotBeABaseURL?e[0]:e.length?"/"+e.join("/"):""},Nt=function(){var t=S(this).query;return t?"?"+t:""},At=function(){return S(this).searchParams},Pt=function(){var t=S(this).fragment;return t?"#"+t:""},Dt=function(t,e){return{get:t,set:e,configurable:!0,enumerable:!0}};if(s&&h(St,{href:Dt(_t,(function(t){var e=S(this),i=String(t),n=xt(e,i);if(n)throw TypeError(n);x(e.searchParams).updateSearchParams(e.query)})),origin:Dt(Ot),protocol:Dt(Ct,(function(t){var e=S(this);xt(e,String(t)+":",tt)})),username:Dt(Tt,(function(t){var e=S(this),i=f(String(t));if(!$(e)){e.username="";for(var n=0;n{this._q.length?this.dequeue().then(function(){this.run()}.bind(this)):(this.defered.resolve(),this.running=void 0)}),1==this.paused&&(this.paused=!1),this.defered.promise}flush(){return this.running?this.running:this._q.length?(this.running=this.dequeue().then(function(){return this.running=void 0,this.flush()}.bind(this)),this.running):void 0}clear(){this._q=[]}length(){return this._q.length}pause(){this.paused=!0}stop(){this._q=[],this.running=!1,this.paused=!0}}},function(t,e,i){"use strict";var n=i(3),r=i.n(n),s=i(0);function o(){var t="reverse",e=function(){var t=document.createElement("div");t.dir="rtl",t.style.position="fixed",t.style.width="1px",t.style.height="1px",t.style.top="0px",t.style.left="0px",t.style.overflow="hidden";var e=document.createElement("div");e.style.width="2px";var i=document.createElement("span");i.style.width="1px",i.style.display="inline-block";var n=document.createElement("span");return n.style.width="1px",n.style.display="inline-block",e.appendChild(i),e.appendChild(n),t.appendChild(e),t}();return document.body.appendChild(e),e.scrollLeft>0?t="default":"undefined"!=typeof Element&&Element.prototype.scrollIntoView?(e.children[0].children[1].scrollIntoView(),e.scrollLeft<0&&(t="negative")):(e.scrollLeft=1,0===e.scrollLeft&&(t="negative")),document.body.removeChild(e),t}var a=i(23),h=i(21),l=i(84),c=i.n(l);var u=class{constructor(t){this.settings=t||{},this.id="epubjs-container-"+Object(s.uuid)(),this.container=this.create(this.settings),this.settings.hidden&&(this.wrapper=this.wrap(this.container))}create(t){let e=t.height,i=t.width,n=t.overflow||!1,r=t.axis||"vertical",o=t.direction;Object(s.extend)(this.settings,t),t.height&&Object(s.isNumber)(t.height)&&(e=t.height+"px"),t.width&&Object(s.isNumber)(t.width)&&(i=t.width+"px");let a=document.createElement("div");return a.id=this.id,a.classList.add("epub-container"),a.style.wordSpacing="0",a.style.lineHeight="0",a.style.verticalAlign="top",a.style.position="relative","horizontal"===r&&(a.style.display="flex",a.style.flexDirection="row",a.style.flexWrap="nowrap"),i&&(a.style.width=i),e&&(a.style.height=e),n&&("scroll"===n&&"vertical"===r?(a.style["overflow-y"]=n,a.style["overflow-x"]="hidden"):"scroll"===n&&"horizontal"===r?(a.style["overflow-y"]="hidden",a.style["overflow-x"]=n):a.style.overflow=n),o&&(a.dir=o,a.style.direction=o),o&&this.settings.fullsize&&(document.body.style.direction=o),a}wrap(t){var e=document.createElement("div");return e.style.visibility="hidden",e.style.overflow="hidden",e.style.width="0",e.style.height="0",e.appendChild(t),e}getElement(t){var e;if(Object(s.isElement)(t)?e=t:"string"==typeof t&&(e=document.getElementById(t)),!e)throw new Error("Not an Element");return e}attachTo(t){var e,i=this.getElement(t);if(i)return e=this.settings.hidden?this.wrapper:this.container,i.appendChild(e),this.element=i,i}getContainer(){return this.container}onResize(t){Object(s.isNumber)(this.settings.width)&&Object(s.isNumber)(this.settings.height)||(this.resizeFunc=c()(t,50),window.addEventListener("resize",this.resizeFunc,!1))}onOrientationChange(t){this.orientationChangeFunc=t,window.addEventListener("orientationchange",this.orientationChangeFunc,!1)}size(t,e){var i;let n=t||this.settings.width,r=e||this.settings.height;null===t?(i=this.element.getBoundingClientRect()).width&&(t=Math.floor(i.width),this.container.style.width=t+"px"):Object(s.isNumber)(t)?this.container.style.width=t+"px":this.container.style.width=t,null===e?(i=i||this.element.getBoundingClientRect()).height&&(e=i.height,this.container.style.height=e+"px"):Object(s.isNumber)(e)?this.container.style.height=e+"px":this.container.style.height=e,Object(s.isNumber)(t)||(t=this.container.clientWidth),Object(s.isNumber)(e)||(e=this.container.clientHeight),this.containerStyles=window.getComputedStyle(this.container),this.containerPadding={left:parseFloat(this.containerStyles["padding-left"])||0,right:parseFloat(this.containerStyles["padding-right"])||0,top:parseFloat(this.containerStyles["padding-top"])||0,bottom:parseFloat(this.containerStyles["padding-bottom"])||0};let o=Object(s.windowBounds)(),a=window.getComputedStyle(document.body),h=parseFloat(a["padding-left"])||0,l=parseFloat(a["padding-right"])||0,c=parseFloat(a["padding-top"])||0,u=parseFloat(a["padding-bottom"])||0;return n||(t=o.width-h-l),(this.settings.fullsize&&!r||!r)&&(e=o.height-c-u),{width:t-this.containerPadding.left-this.containerPadding.right,height:e-this.containerPadding.top-this.containerPadding.bottom}}bounds(){let t;return"visible"!==this.container.style.overflow&&(t=this.container&&this.container.getBoundingClientRect()),t&&t.width&&t.height?t:Object(s.windowBounds)()}getSheet(){var t=document.createElement("style");return t.appendChild(document.createTextNode("")),document.head.appendChild(t),t.sheet}addStyleRules(t,e){var i="#"+this.id+" ",n="";this.sheet||(this.sheet=this.getSheet()),e.forEach((function(t){for(var e in t)t.hasOwnProperty(e)&&(n+=e+":"+t[e]+";")})),this.sheet.insertRule(i+t+" {"+n+"}",0)}axis(t){"horizontal"===t?(this.container.style.display="flex",this.container.style.flexDirection="row",this.container.style.flexWrap="nowrap"):this.container.style.display="block",this.settings.axis=t}direction(t){this.container&&(this.container.dir=t,this.container.style.direction=t),this.settings.fullsize&&(document.body.style.direction=t),this.settings.dir=t}overflow(t){this.container&&("scroll"===t&&"vertical"===this.settings.axis?(this.container.style["overflow-y"]=t,this.container.style["overflow-x"]="hidden"):"scroll"===t&&"horizontal"===this.settings.axis?(this.container.style["overflow-y"]="hidden",this.container.style["overflow-x"]=t):this.container.style.overflow=t),this.settings.overflow=t}destroy(){this.element&&(this.settings.hidden?this.wrapper:this.container,this.element.contains(this.container)&&this.element.removeChild(this.container),window.removeEventListener("resize",this.resizeFunc),window.removeEventListener("orientationChange",this.orientationChangeFunc))}};var d=class{constructor(t){this.container=t,this._views=[],this.length=0,this.hidden=!1}all(){return this._views}first(){return this._views[0]}last(){return this._views[this._views.length-1]}indexOf(t){return this._views.indexOf(t)}slice(){return this._views.slice.apply(this._views,arguments)}get(t){return this._views[t]}append(t){return this._views.push(t),this.container&&this.container.appendChild(t.element),this.length++,t}prepend(t){return this._views.unshift(t),this.container&&this.container.insertBefore(t.element,this.container.firstChild),this.length++,t}insert(t,e){return this._views.splice(e,0,t),this.container&&(e-1&&this._views.splice(e,1),this.destroy(t),this.length--}destroy(t){t.displayed&&t.destroy(),this.container&&this.container.removeChild(t.element),t=null}forEach(){return this._views.forEach.apply(this._views,arguments)}clear(){var t,e=this.length;if(this.length){for(var i=0;i1){if(t||0===e.index)return;if(n=e.next(),n&&!n.properties.includes("page-spread-left"))return i.call(this,n)}}display(t,e){var i=new s.defer,n=i.promise;(e===t.href||Object(s.isNumber)(e))&&(e=void 0);var r=this.views.find(t);if(r&&t&&"pre-paginated"!==this.layout.name){let t=r.offset();if("ltr"===this.settings.direction)this.scrollTo(t.left,t.top,!0);else{let e=r.width();this.scrollTo(t.left+e,t.top,!0)}if(e){let t=r.locationOf(e);this.moveTo(t)}return i.resolve(),n}this.clear();let o=!1;return"pre-paginated"===this.layout.name&&2===this.layout.divisor&&t.properties.includes("page-spread-right")&&(o=!0),this.add(t,o).then(function(t){if(e){let i=t.locationOf(e);this.moveTo(i)}}.bind(this),t=>{i.reject(t)}).then(function(){return this.handleNextPrePaginated(o,t,this.add)}.bind(this)).then(function(){this.views.show(),i.resolve()}.bind(this)),n}afterDisplayed(t){this.emit(f.c.MANAGERS.ADDED,t)}afterResized(t){this.emit(f.c.MANAGERS.RESIZE,t.section)}moveTo(t){var e=0,i=0;this.isPaginated?(e=Math.floor(t.left/this.layout.delta)*this.layout.delta)+this.layout.delta>this.container.scrollWidth&&(e=this.container.scrollWidth-this.layout.delta):i=t.top,this.scrollTo(e,i,!0)}add(t,e){var i=this.createView(t,e);return this.views.append(i),i.onDisplayed=this.afterDisplayed.bind(this),i.onResize=this.afterResized.bind(this),i.on(f.c.VIEWS.AXIS,t=>{this.updateAxis(t)}),i.on(f.c.VIEWS.WRITING_MODE,t=>{this.updateWritingMode(t)}),i.display(this.request)}append(t,e){var i=this.createView(t,e);return this.views.append(i),i.onDisplayed=this.afterDisplayed.bind(this),i.onResize=this.afterResized.bind(this),i.on(f.c.VIEWS.AXIS,t=>{this.updateAxis(t)}),i.on(f.c.VIEWS.WRITING_MODE,t=>{this.updateWritingMode(t)}),i.display(this.request)}prepend(t,e){var i=this.createView(t,e);return i.on(f.c.VIEWS.RESIZED,t=>{this.counter(t)}),this.views.prepend(i),i.onDisplayed=this.afterDisplayed.bind(this),i.onResize=this.afterResized.bind(this),i.on(f.c.VIEWS.AXIS,t=>{this.updateAxis(t)}),i.on(f.c.VIEWS.WRITING_MODE,t=>{this.updateWritingMode(t)}),i.display(this.request)}counter(t){"vertical"===this.settings.axis?this.scrollBy(0,t.heightDelta,!0):this.scrollBy(t.widthDelta,0,!0)}next(){var t;let e=this.settings.direction;if(this.views.length){if(!this.isPaginated||"horizontal"!==this.settings.axis||e&&"ltr"!==e)if(this.isPaginated&&"horizontal"===this.settings.axis&&"rtl"===e)this.scrollLeft=this.container.scrollLeft,"default"===this.settings.rtlScrollType?this.container.scrollLeft>0?this.scrollBy(this.layout.delta,0,!0):t=this.views.last().section.next():this.container.scrollLeft+-1*this.layout.delta>-1*this.container.scrollWidth?this.scrollBy(this.layout.delta,0,!0):t=this.views.last().section.next();else if(this.isPaginated&&"vertical"===this.settings.axis){this.scrollTop=this.container.scrollTop,this.container.scrollTop+this.container.offsetHeightt).then(function(){this.isPaginated||"horizontal"!==this.settings.axis||"rtl"!==this.settings.direction||"default"!==this.settings.rtlScrollType||this.scrollTo(this.container.scrollWidth,0,!0),this.views.show()}.bind(this))}}}prev(){var t;let e=this.settings.direction;if(this.views.length){if(!this.isPaginated||"horizontal"!==this.settings.axis||e&&"ltr"!==e)if(this.isPaginated&&"horizontal"===this.settings.axis&&"rtl"===e)this.scrollLeft=this.container.scrollLeft,"default"===this.settings.rtlScrollType?this.container.scrollLeft+this.container.offsetWidth0?this.scrollBy(0,-this.layout.height,!0):t=this.views.first().section.prev()}else t=this.views.first().section.prev();else this.scrollLeft=this.container.scrollLeft,this.container.scrollLeft>0?this.scrollBy(-this.layout.delta,0,!0):t=this.views.first().section.prev();if(t){this.clear();let e=!1;return"pre-paginated"===this.layout.name&&2===this.layout.divisor&&"object"!=typeof t.prev()&&(e=!0),this.prepend(t,e).then(function(){var e;if("pre-paginated"===this.layout.name&&this.layout.divisor>1&&(e=t.prev()))return this.prepend(e)}.bind(this),t=>t).then(function(){this.isPaginated&&"horizontal"===this.settings.axis&&("rtl"===this.settings.direction?"default"===this.settings.rtlScrollType?this.scrollTo(0,0,!0):this.scrollTo(-1*this.container.scrollWidth+this.layout.delta,0,!0):this.scrollTo(this.container.scrollWidth-this.layout.delta,0,!0)),this.views.show()}.bind(this))}}}current(){var t=this.visible();return t.length?t[t.length-1]:null}clear(){this.views&&(this.views.hide(),this.scrollTo(0,0,!0),this.views.clear())}currentLocation(){return this.isPaginated&&"horizontal"===this.settings.axis?this.location=this.paginatedLocation():this.location=this.scrolledLocation(),this.location}scrolledLocation(){let t=this.visible(),e=this.container.getBoundingClientRect(),i=e.height{let o,a,h,l,{index:c,href:u}=t.section,d=t.position(),f=t.width(),p=t.height();r?(o=s+e.top-d.top+0,a=o+i-0,l=this.layout.count(p,i).pages,h=i):(o=s+e.left-d.left+0,a=o+n-0,l=this.layout.count(f,n).pages,h=n);let g=Math.ceil(o/h),v=[],m=Math.ceil(a/h);if("rtl"===this.settings.direction&&!r){let t=g;g=l-m,m=l-t}v=[];for(var y=g;y<=m;y++){let t=y+1;v.push(t)}return{index:c,href:u,pages:v,totalPages:l,mapping:this.mapping.page(t.contents,t.section.cfiBase,o,a)}})}paginatedLocation(){let t=this.visible(),e=this.container.getBoundingClientRect(),i=0,n=0;return this.settings.fullsize&&(i=window.scrollX),t.map(t=>{let r,s,o,a,{index:h,href:l}=t.section,c=t.position(),u=t.width();"rtl"===this.settings.direction?(r=e.right-i,a=Math.min(Math.abs(r-c.left),this.layout.width)-n,o=c.width-(c.right-r)-n,s=o-a):(r=e.left+i,a=Math.min(c.right-r,this.layout.width)-n,s=r-c.left+n,o=s+a),n+=a;let d=this.mapping.page(t.contents,t.section.cfiBase,s,o),f=this.layout.count(u).pages,p=Math.floor(s/this.layout.pageWidth),g=[],v=Math.floor(o/this.layout.pageWidth);if(p<0&&(p=0,v+=1),"rtl"===this.settings.direction){let t=p;p=f-v,v=f-t}for(var m=p+1;m<=v;m++){let t=m;g.push(t)}return{index:h,href:l,pages:g,totalPages:f,mapping:d}})}isVisible(t,e,i,n){var r=t.position(),s=n||this.bounds();return"horizontal"===this.settings.axis&&r.right>s.left-e&&r.lefts.top-e&&r.top0&&"pre-paginated"===this.layout.name&&this.display(this.views.first().section)}updateLayout(){this.stage&&(this._stageSize=this.stage.size(),this.isPaginated?(this.layout.calculate(this._stageSize.width,this._stageSize.height,this.settings.gap),this.settings.offset=this.layout.delta/this.layout.divisor):this.layout.calculate(this._stageSize.width,this._stageSize.height),this.viewSettings.width=this.layout.width,this.viewSettings.height=this.layout.height,this.setLayout(this.layout))}setLayout(t){this.viewSettings.layout=t,this.mapping=new a.a(t.props,this.settings.direction,this.settings.axis),this.views&&this.views.forEach((function(e){e&&e.setLayout(t)}))}updateWritingMode(t){this.writingMode=t}updateAxis(t,e){(e||t!==this.settings.axis)&&(this.settings.axis=t,this.stage&&this.stage.axis(t),this.viewSettings.axis=t,this.mapping&&(this.mapping=new a.a(this.layout.props,this.settings.direction,this.settings.axis)),this.layout&&("vertical"===t?this.layout.spread("none"):this.layout.spread(this.layout.settings.spread)))}updateFlow(t,e="auto"){let i="paginated"===t||"auto"===t;this.isPaginated=i,"scrolled-doc"===t||"scrolled-continuous"===t||"scrolled"===t?this.updateAxis("vertical"):this.updateAxis("horizontal"),this.viewSettings.flow=t,this.settings.overflow?this.overflow=this.settings.overflow:this.overflow=i?"hidden":e,this.stage&&this.stage.overflow(this.overflow),this.updateLayout()}getContents(){var t=[];return this.views?(this.views.forEach((function(e){const i=e&&e.contents;i&&t.push(i)})),t):t}direction(t="ltr"){this.settings.direction=t,this.stage&&this.stage.direction(t),this.viewSettings.direction=t,this.updateLayout()}isRendered(){return this.rendered}}r()(p.prototype);e.a=p},function(t,e,i){"use strict";var n=i(2),r=i(0);e.a=class{constructor(t,e,i,n=!1){this.layout=t,this.horizontal="horizontal"===i,this.direction=e||"ltr",this._dev=n}section(t){var e=this.findRanges(t);return this.rangeListToCfiList(t.section.cfiBase,e)}page(t,e,i,r){var s,o=!(!t||!t.document)&&t.document.body;if(o){if(s=this.rangePairToCfiPair(e,{start:this.findStart(o,i,r),end:this.findEnd(o,i,r)}),!0===this._dev){let e=t.document,i=new n.a(s.start).toRange(e),r=new n.a(s.end).toRange(e),o=e.defaultView.getSelection(),a=e.createRange();o.removeAllRanges(),a.setStart(i.startContainer,i.startOffset),a.setEnd(r.endContainer,r.endOffset),o.addRange(a)}return s}}walk(t,e){if(!t||t.nodeType!==Node.TEXT_NODE){var i=function(t){return t.data.trim().length>0?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT},n=i;n.acceptNode=i;for(var r,s,o=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,n,!1);(r=o.nextNode())&&!(s=e(r)););return s}}findRanges(t){for(var e,i,n=[],r=t.contents.scrollWidth(),s=Math.ceil(r/this.layout.spreadWidth)*this.layout.divisor,o=this.layout.columnWidth,a=this.layout.gap,h=0;h{var n,s,h,l,c;if(c=Object(r.nodeBounds)(t),this.horizontal&&"ltr"===this.direction){if(n=this.horizontal?c.left:c.top,s=this.horizontal?c.right:c.bottom,n>=e&&n<=i)return t;if(s>e)return t;a=t,o.push(t)}else if(this.horizontal&&"rtl"===this.direction){if(n=c.left,(s=c.right)<=i&&s>=e)return t;if(n=e&&h<=i)return t;if(l>e)return t;a=t,o.push(t)}}))return this.findTextStartRange(s,e,i);return this.findTextStartRange(a,e,i)}findEnd(t,e,i){for(var n,s,o=[t],a=t;o.length;)if(n=o.shift(),s=this.walk(n,t=>{var n,s,h,l,c;if(c=Object(r.nodeBounds)(t),this.horizontal&&"ltr"===this.direction){if(n=Math.round(c.left),s=Math.round(c.right),n>i&&a)return a;if(s>i)return t;a=t,o.push(t)}else if(this.horizontal&&"rtl"===this.direction){if(n=Math.round(this.horizontal?c.left:c.top),(s=Math.round(this.horizontal?c.right:c.bottom))i&&a)return a;if(l>i)return t;a=t,o.push(t)}}))return this.findTextEndRange(s,e,i);return this.findTextEndRange(a,e,i)}findTextStartRange(t,e,i){for(var n,r,s=this.splitTextNodeIntoRanges(t),o=0;o=e)return n}else if(this.horizontal&&"rtl"===this.direction){if(r.right<=i)return n}else if(r.top>=e)return n;return s[0]}findTextEndRange(t,e,i){for(var n,r,s,o,a,h,l,c=this.splitTextNodeIntoRanges(t),u=0;ui&&n)return n;if(a>i)return r}else if(this.horizontal&&"rtl"===this.direction){if(o=s.left,(a=s.right)i&&n)return n;if(l>i)return r}n=r}return c[c.length-1]}splitTextNodeIntoRanges(t,e){var i,n=[],r=(t.textContent||"").trim(),s=t.ownerDocument,o=e||" ",a=r.indexOf(o);if(-1===a||t.nodeType!=Node.TEXT_NODE)return(i=s.createRange()).selectNodeContents(t),[i];for((i=s.createRange()).setStart(t,0),i.setEnd(t,a),n.push(i),i=!1;-1!=a;)(a=r.indexOf(o,a+1))>0&&(i&&(i.setEnd(t,a),n.push(i)),(i=s.createRange()).setStart(t,a+1));return i&&(i.setEnd(t,r.length),n.push(i)),n}rangePairToCfiPair(t,e){var i=e.start,r=e.end;return i.collapse(!0),r.collapse(!1),{start:new n.a(i,t).toString(),end:new n.a(r,t).toString()}}rangeListToCfiList(t,e){for(var i,n=[],r=0;r]*>)/g,g=/\$([$&'`]|\d\d?)/g;n("replace",2,(function(t,e,i,n){var v=n.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,m=n.REPLACE_KEEPS_$0,y=v?"$":"$0";return[function(i,n){var r=h(this),s=null==i?void 0:i[t];return void 0!==s?s.call(i,r,n):e.call(String(r),i,n)},function(t,n){if(!v&&m||"string"==typeof n&&-1===n.indexOf(y)){var s=i(e,t,this,n);if(s.done)return s.value}var h=r(t),f=String(this),p="function"==typeof n;p||(n=String(n));var g=h.global;if(g){var w=h.unicode;h.lastIndex=0}for(var x=[];;){var E=c(h,f);if(null===E)break;if(x.push(E),!g)break;""===String(E[0])&&(h.lastIndex=l(f,o(h.lastIndex),w))}for(var S,_="",O=0,C=0;C=O&&(_+=f.slice(O,k)+N,O=k+T.length)}return _+f.slice(O)}];function b(t,i,n,r,o,a){var h=n+t.length,l=r.length,c=g;return void 0!==o&&(o=s(o),c=p),e.call(a,c,(function(e,s){var a;switch(s.charAt(0)){case"$":return"$";case"&":return t;case"`":return i.slice(0,n);case"'":return i.slice(h);case"<":a=o[s.slice(1,-1)];break;default:var c=+s;if(0===c)return e;if(c>l){var u=f(c/10);return 0===u?e:u<=l?void 0===r[u-1]?s.charAt(1):r[u-1]+s.charAt(1):e}a=r[c-1]}return void 0===a?"":a}))}}))},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,i){var n,r,s,o=i(89),a=i(7),h=i(17),l=i(15),c=i(10),u=i(43),d=i(44),f=a.WeakMap;if(o){var p=new f,g=p.get,v=p.has,m=p.set;n=function(t,e){return m.call(p,t,e),e},r=function(t){return g.call(p,t)||{}},s=function(t){return v.call(p,t)}}else{var y=u("state");d[y]=!0,n=function(t,e){return l(t,y,e),e},r=function(t){return c(t,y)?t[y]:{}},s=function(t){return c(t,y)}}t.exports={set:n,get:r,has:s,enforce:function(t){return s(t)?r(t):n(t,{})},getterFor:function(t){return function(e){var i;if(!h(e)||(i=r(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return i}}}},function(t,e){t.exports={}},function(t,e,i){"use strict";var n=i(3),r=i.n(n),s=i(0),o=i(2),a=i(23),h=i(11),l=i(1);const c="undefined"!=typeof navigator,u=c&&/Chrome/.test(navigator.userAgent),d=c&&!u&&/AppleWebKit/.test(navigator.userAgent);class f{constructor(t,e,i,n){this.epubcfi=new o.a,this.document=t,this.documentElement=this.document.documentElement,this.content=e||this.document.body,this.window=this.document.defaultView,this._size={width:0,height:0},this.sectionIndex=n||0,this.cfiBase=i||"",this.epubReadingSystem("epub.js",l.b),this.called=0,this.active=!0,this.listeners()}static get listenedEvents(){return l.a}width(t){var e=this.content;return t&&Object(s.isNumber)(t)&&(t+="px"),t&&(e.style.width=t),parseInt(this.window.getComputedStyle(e).width)}height(t){var e=this.content;return t&&Object(s.isNumber)(t)&&(t+="px"),t&&(e.style.height=t),parseInt(this.window.getComputedStyle(e).height)}contentWidth(t){var e=this.content||this.document.body;return t&&Object(s.isNumber)(t)&&(t+="px"),t&&(e.style.width=t),parseInt(this.window.getComputedStyle(e).width)}contentHeight(t){var e=this.content||this.document.body;return t&&Object(s.isNumber)(t)&&(t+="px"),t&&(e.style.height=t),parseInt(this.window.getComputedStyle(e).height)}textWidth(){let t,e,i=this.document.createRange(),n=this.content||this.document.body,r=Object(s.borders)(n);return i.selectNodeContents(n),t=i.getBoundingClientRect(),e=t.width,r&&r.width&&(e+=r.width),Math.round(e)}textHeight(){let t,e,i=this.document.createRange(),n=this.content||this.document.body;return i.selectNodeContents(n),t=i.getBoundingClientRect(),e=t.bottom,Math.round(e)}scrollWidth(){return this.documentElement.scrollWidth}scrollHeight(){return this.documentElement.scrollHeight}overflow(t){return t&&(this.documentElement.style.overflow=t),this.window.getComputedStyle(this.documentElement).overflow}overflowX(t){return t&&(this.documentElement.style.overflowX=t),this.window.getComputedStyle(this.documentElement).overflowX}overflowY(t){return t&&(this.documentElement.style.overflowY=t),this.window.getComputedStyle(this.documentElement).overflowY}css(t,e,i){var n=this.content||this.document.body;return e?n.style.setProperty(t,e,i?"important":""):n.style.removeProperty(t),this.window.getComputedStyle(n)[t]}viewport(t){var e,i=this.document.querySelector("meta[name='viewport']"),n={width:void 0,height:void 0,scale:void 0,minimum:void 0,maximum:void 0,scalable:void 0},r=[];if(i&&i.hasAttribute("content")){let t=i.getAttribute("content"),e=t.match(/width\s*=\s*([^,]*)/),r=t.match(/height\s*=\s*([^,]*)/),s=t.match(/initial-scale\s*=\s*([^,]*)/),o=t.match(/minimum-scale\s*=\s*([^,]*)/),a=t.match(/maximum-scale\s*=\s*([^,]*)/),h=t.match(/user-scalable\s*=\s*([^,]*)/);e&&e.length&&void 0!==e[1]&&(n.width=e[1]),r&&r.length&&void 0!==r[1]&&(n.height=r[1]),s&&s.length&&void 0!==s[1]&&(n.scale=s[1]),o&&o.length&&void 0!==o[1]&&(n.minimum=o[1]),a&&a.length&&void 0!==a[1]&&(n.maximum=a[1]),h&&h.length&&void 0!==h[1]&&(n.scalable=h[1])}return e=Object(s.defaults)(t||{},n),t&&(e.width&&r.push("width="+e.width),e.height&&r.push("height="+e.height),e.scale&&r.push("initial-scale="+e.scale),"no"===e.scalable?(r.push("minimum-scale="+e.scale),r.push("maximum-scale="+e.scale),r.push("user-scalable="+e.scalable)):(e.scalable&&r.push("user-scalable="+e.scalable),e.minimum&&r.push("minimum-scale="+e.minimum),e.maximum&&r.push("minimum-scale="+e.maximum)),i||((i=this.document.createElement("meta")).setAttribute("name","viewport"),this.document.querySelector("head").appendChild(i)),i.setAttribute("content",r.join(", ")),this.window.scrollTo(0,0)),e}expand(){this.emit(l.c.CONTENTS.EXPAND)}listeners(){this.imageLoadListeners(),this.mediaQueryListeners(),this.addEventListeners(),this.addSelectionListeners(),"undefined"==typeof ResizeObserver?(this.resizeListeners(),this.visibilityListeners()):this.resizeObservers(),this.linksHandler()}removeListeners(){this.removeEventListeners(),this.removeSelectionListeners(),this.observer&&this.observer.disconnect(),clearTimeout(this.expanding)}resizeCheck(){let t=this.textWidth(),e=this.textHeight();t==this._size.width&&e==this._size.height||(this._size={width:t,height:e},this.onResize&&this.onResize(this._size),this.emit(l.c.CONTENTS.RESIZE,this._size))}resizeListeners(){clearTimeout(this.expanding),requestAnimationFrame(this.resizeCheck.bind(this)),this.expanding=setTimeout(this.resizeListeners.bind(this),350)}visibilityListeners(){document.addEventListener("visibilitychange",()=>{"visible"===document.visibilityState&&!1===this.active?(this.active=!0,this.resizeListeners()):(this.active=!1,clearTimeout(this.expanding))})}transitionListeners(){let t=this.content;t.style.transitionProperty="font, font-size, font-size-adjust, font-stretch, font-variation-settings, font-weight, width, height",t.style.transitionDuration="0.001ms",t.style.transitionTimingFunction="linear",t.style.transitionDelay="0",this._resizeCheck=this.resizeCheck.bind(this),this.document.addEventListener("transitionend",this._resizeCheck)}mediaQueryListeners(){for(var t=this.document.styleSheets,e=function(t){t.matches&&!this._expanding&&setTimeout(this.expand.bind(this),1)}.bind(this),i=0;i{requestAnimationFrame(this.resizeCheck.bind(this))}),this.observer.observe(this.document.documentElement)}mutationObservers(){this.observer=new MutationObserver(t=>{this.resizeCheck()});this.observer.observe(this.document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})}imageLoadListeners(){for(var t,e=this.document.querySelectorAll("img"),i=0;i0?(e.setStart(t,r.startOffset-2),e.setEnd(t,r.startOffset),i=e.getBoundingClientRect()):i=t.parentNode.getBoundingClientRect()}catch(t){console.error(t,t.stack)}}else i=r.getBoundingClientRect()}}else if("string"==typeof t&&t.indexOf("#")>-1){let e=t.substring(t.indexOf("#")+1),n=this.document.getElementById(e);if(n)if(d){let t=new Range;t.selectNode(n),i=t.getBoundingClientRect()}else i=n.getBoundingClientRect()}return i&&(n.left=i.left,n.top=i.top),n}addStylesheet(t){return new Promise(function(e,i){var n,r=!1;this.document?(n=this.document.querySelector("link[href='"+t+"']"))?e(!0):((n=this.document.createElement("link")).type="text/css",n.rel="stylesheet",n.href=t,n.onload=n.onreadystatechange=function(){r||this.readyState&&"complete"!=this.readyState||(r=!0,setTimeout(()=>{e(!0)},1))},this.document.head.appendChild(n)):e(!1)}.bind(this))}_getStylesheetNode(t){var e;return t="epubjs-inserted-css-"+(t||""),!!this.document&&((e=this.document.getElementById(t))||((e=this.document.createElement("style")).id=t,this.document.head.appendChild(e)),e)}addStylesheetCss(t,e){return!(!this.document||!t)&&(this._getStylesheetNode(e).innerHTML=t,!0)}addStylesheetRules(t,e){var i;if(this.document&&t&&0!==t.length)if(i=this._getStylesheetNode(e).sheet,"[object Array]"===Object.prototype.toString.call(t))for(var n=0,r=t.length;n{const n=t[e];if(Array.isArray(n))n.forEach(t=>{const n=Object.keys(t).map(e=>`${e}:${t[e]}`).join(";");i.insertRule(`${e}{${n}}`,i.cssRules.length)});else{const t=Object.keys(n).map(t=>`${t}:${n[t]}`).join(";");i.insertRule(`${e}{${t}}`,i.cssRules.length)}})}}addScript(t){return new Promise(function(e,i){var n,r=!1;this.document?((n=this.document.createElement("script")).type="text/javascript",n.async=!0,n.src=t,n.onload=n.onreadystatechange=function(){r||this.readyState&&"complete"!=this.readyState||(r=!0,setTimeout((function(){e(!0)}),1))},this.document.head.appendChild(n)):e(!1)}.bind(this))}addClass(t){var e;this.document&&(e=this.content||this.document.body)&&e.classList.add(t)}removeClass(t){var e;this.document&&(e=this.content||this.document.body)&&e.classList.remove(t)}addEventListeners(){this.document&&(this._triggerEvent=this.triggerEvent.bind(this),l.a.forEach((function(t){this.document.addEventListener(t,this._triggerEvent,{passive:!0})}),this))}removeEventListeners(){this.document&&(l.a.forEach((function(t){this.document.removeEventListener(t,this._triggerEvent,{passive:!0})}),this),this._triggerEvent=void 0)}triggerEvent(t){this.emit(t.type,t)}addSelectionListeners(){this.document&&(this._onSelectionChange=this.onSelectionChange.bind(this),this.document.addEventListener("selectionchange",this._onSelectionChange,{passive:!0}))}removeSelectionListeners(){this.document&&(this.document.removeEventListener("selectionchange",this._onSelectionChange,{passive:!0}),this._onSelectionChange=void 0)}onSelectionChange(t){this.selectionEndTimeout&&clearTimeout(this.selectionEndTimeout),this.selectionEndTimeout=setTimeout(function(){var t=this.window.getSelection();this.triggerSelectedEvent(t)}.bind(this),250)}triggerSelectedEvent(t){var e,i;t&&t.rangeCount>0&&((e=t.getRangeAt(0)).collapsed||(i=new o.a(e,this.cfiBase).toString(),this.emit(l.c.CONTENTS.SELECTED,i),this.emit(l.c.CONTENTS.SELECTED_RANGE,e)))}range(t,e){return new o.a(t).toRange(this.document,e)}cfiFromRange(t,e){return new o.a(t,this.cfiBase,e).toString()}cfiFromNode(t,e){return new o.a(t,this.cfiBase,e).toString()}map(t){return new a.a(t).section()}size(t,e){var i={scale:1,scalable:"no"};this.layoutStyle("scrolling"),t>=0&&(this.width(t),i.width=t,this.css("padding","0 "+t/12+"px")),e>=0&&(this.height(e),i.height=e),this.css("margin","0"),this.css("box-sizing","border-box"),this.viewport(i)}columns(t,e,i,n,r){let o=Object(s.prefixed)("column-axis"),a=Object(s.prefixed)("column-gap"),h=Object(s.prefixed)("column-width"),l=Object(s.prefixed)("column-fill"),c=0===this.writingMode().indexOf("vertical")?"vertical":"horizontal";this.layoutStyle("paginated"),"rtl"===r&&"horizontal"===c&&this.direction(r),this.width(t),this.height(e),this.viewport({width:t,height:e,scale:1,scalable:"no"}),this.css("overflow-y","hidden"),this.css("margin","0",!0),"vertical"===c?(this.css("padding-top",n/2+"px",!0),this.css("padding-bottom",n/2+"px",!0),this.css("padding-left","20px"),this.css("padding-right","20px"),this.css(o,"vertical")):(this.css("padding-top","20px"),this.css("padding-bottom","20px"),this.css("padding-left",n/2+"px",!0),this.css("padding-right",n/2+"px",!0),this.css(o,"horizontal")),this.css("box-sizing","border-box"),this.css("max-width","inherit"),this.css(l,"auto"),this.css(a,n+"px"),this.css(h,i+"px"),this.css("-webkit-line-box-contain","block glyphs replaced")}scaler(t,e,i){var n="scale("+t+")",r="";this.css("transform-origin","top left"),(e>=0||i>=0)&&(r=" translate("+(e||0)+"px, "+(i||0)+"px )"),this.css("transform",n+r)}fit(t,e,i){var n=this.viewport(),r=parseInt(n.width),s=parseInt(n.height),o=t/r,a=e/s,h=o{this.emit(l.c.CONTENTS.LINK_CLICKED,t)})}writingMode(t){let e=Object(s.prefixed)("writing-mode");return t&&this.documentElement&&(this.documentElement.style[e]=t),this.window.getComputedStyle(this.documentElement)[e]||""}layoutStyle(t){return t&&(this._layoutStyle=t,navigator.epubReadingSystem.layoutStyle=this._layoutStyle),this._layoutStyle||"paginated"}epubReadingSystem(t,e){return navigator.epubReadingSystem={name:t,version:e,layoutStyle:this.layoutStyle(),hasFeature:function(t){switch(t){case"dom-manipulation":case"layout-changes":case"touch-events":case"mouse-events":case"keyboard-events":return!0;case"spine-scripting":default:return!1}}},navigator.epubReadingSystem}destroy(){this.removeListeners()}}r()(f.prototype),e.a=f},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.Underline=e.Highlight=e.Mark=e.Pane=void 0;var n=function(){function t(t,e){for(var i=0;i1&&void 0!==arguments[1]?arguments[1]:document.body;l(this,t),this.target=e,this.element=r.default.createElement("svg"),this.marks=[],this.element.style.position="absolute",this.element.setAttribute("pointer-events","none"),s.default.proxyMouse(this.target,this.marks),this.container=i,this.container.appendChild(this.element),this.render()}return n(t,[{key:"addMark",value:function(t){var e=r.default.createElement("g");return this.element.appendChild(e),t.bind(e,this.container),this.marks.push(t),t.render(),t}},{key:"removeMark",value:function(t){var e=this.marks.indexOf(t);if(-1!==e){var i=t.unbind();this.element.removeChild(i),this.marks.splice(e,1)}}},{key:"render",value:function(){var t,e,i,n;!function(t,e){t.style.setProperty("top",e.top+"px","important"),t.style.setProperty("left",e.left+"px","important"),t.style.setProperty("height",e.height+"px","important"),t.style.setProperty("width",e.width+"px","important")}(this.element,(t=this.target,e=this.container,i=e.getBoundingClientRect(),n=t.getBoundingClientRect(),{top:n.top-i.top,left:n.left-i.left,height:t.scrollHeight,width:t.scrollWidth}));var r=!0,s=!1,o=void 0;try{for(var a,h=this.marks[Symbol.iterator]();!(r=(a=h.next()).done);r=!0){a.value.render()}}catch(t){s=!0,o=t}finally{try{!r&&h.return&&h.return()}finally{if(s)throw o}}}}]),t}();var c=e.Mark=function(){function t(){l(this,t),this.element=null}return n(t,[{key:"bind",value:function(t,e){this.element=t,this.container=e}},{key:"unbind",value:function(){var t=this.element;return this.element=null,t}},{key:"render",value:function(){}},{key:"dispatchEvent",value:function(t){this.element&&this.element.dispatchEvent(t)}},{key:"getBoundingClientRect",value:function(){return this.element.getBoundingClientRect()}},{key:"getClientRects",value:function(){for(var t=[],e=this.element.firstChild;e;)t.push(e.getBoundingClientRect()),e=e.nextSibling;return t}},{key:"filteredRanges",value:function(){var t=Array.from(this.range.getClientRects());return t.filter((function(e){for(var i=0;i=n.left&&r.top>=n.top&&r.bottom<=n.bottom)return!1}var n,r;return!0}))}}]),t}(),u=e.Highlight=function(t){function e(t,i,n,r){l(this,e);var s=a(this,(e.__proto__||Object.getPrototypeOf(e)).call(this));return s.range=t,s.className=i,s.data=n||{},s.attributes=r||{},s}return h(e,t),n(e,[{key:"bind",value:function(t,i){for(var n in function t(e,i,n){null===e&&(e=Function.prototype);var r=Object.getOwnPropertyDescriptor(e,i);if(void 0===r){var s=Object.getPrototypeOf(e);return null===s?void 0:t(s,i,n)}if("value"in r)return r.value;var o=r.get;return void 0!==o?o.call(n):void 0}(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"bind",this).call(this,t,i),this.data)this.data.hasOwnProperty(n)&&(this.element.dataset[n]=this.data[n]);for(var n in this.attributes)this.attributes.hasOwnProperty(n)&&this.element.setAttribute(n,this.attributes[n]);this.className&&this.element.classList.add(this.className)}},{key:"render",value:function(){for(;this.element.firstChild;)this.element.removeChild(this.element.firstChild);for(var t=this.element.ownerDocument.createDocumentFragment(),e=this.filteredRanges(),i=this.element.getBoundingClientRect(),n=this.container.getBoundingClientRect(),s=0,o=e.length;s0?n:i)(t)}},function(t,e,i){var n=i(33);t.exports=function(t){return Object(n(t))}},function(t,e,i){var n=i(18).f,r=i(10),s=i(8)("toStringTag");t.exports=function(t,e,i){t&&!r(t=i?t:t.prototype,s)&&n(t,s,{configurable:!0,value:e})}},function(e,i){e.exports=t},function(t,e,i){"use strict";var n=i(3),r=i.n(n),s=i(0),o=i(6),a=i(2),h=i(21),l=i(1);class c{constructor(t){this.settings=t,this.name=t.layout||"reflowable",this._spread="none"!==t.spread,this._minSpreadWidth=t.minSpreadWidth||800,this._evenSpreads=t.evenSpreads||!1,"scrolled"===t.flow||"scrolled-continuous"===t.flow||"scrolled-doc"===t.flow?this._flow="scrolled":this._flow="paginated",this.width=0,this.height=0,this.spreadWidth=0,this.delta=0,this.columnWidth=0,this.gap=0,this.divisor=1,this.props={name:this.name,spread:this._spread,flow:this._flow,width:0,height:0,spreadWidth:0,delta:0,columnWidth:0,gap:0,divisor:1}}flow(t){return void 0!==t&&(this._flow="scrolled"===t||"scrolled-continuous"===t||"scrolled-doc"===t?"scrolled":"paginated",this.update({flow:this._flow})),this._flow}spread(t,e){return t&&(this._spread="none"!==t,this.update({spread:this._spread})),e>=0&&(this._minSpreadWidth=e),this._spread}calculate(t,e,i){var n,r,s,o,a=1,h=i||0,l=t,c=e,u=Math.floor(l/12);a=this._spread&&l>=this._minSpreadWidth?2:1,"reflowable"!==this.name||"paginated"!==this._flow||i>=0||(h=u%2==0?u:u-1),"pre-paginated"===this.name&&(h=0),a>1?s=(n=l/a-h)+h:(n=l,s=l),"pre-paginated"===this.name&&a>1&&(l=n),r=n*a+h,o=l,this.width=l,this.height=c,this.spreadWidth=r,this.pageWidth=s,this.delta=o,this.columnWidth=n,this.gap=h,this.divisor=a,this.update({width:l,height:c,spreadWidth:r,pageWidth:s,delta:o,columnWidth:n,gap:h,divisor:a})}format(t,e,i){return"pre-paginated"===this.name?t.fit(this.columnWidth,this.height,e):"paginated"===this._flow?t.columns(this.width,this.height,this.columnWidth,this.gap,this.settings.direction):i&&"horizontal"===i?t.size(null,this.height):t.size(this.width,null)}count(t,e){let i,n;return"pre-paginated"===this.name?(i=1,n=1):"paginated"===this._flow?(e=e||this.delta,i=Math.ceil(t/e),n=i*this.divisor):(e=e||this.height,i=Math.ceil(t/e),n=i),{spreads:i,pages:n}}update(t){if(Object.keys(t).forEach(e=>{this.props[e]===t[e]&&delete t[e]}),Object.keys(t).length>0){let e=Object(s.extend)(this.props,t);this.emit(l.c.LAYOUT.UPDATED,e,t)}}}r()(c.prototype);var u=c,d=i(5);var f=class{constructor(t){this.rendition=t,this._themes={default:{rules:{},url:"",serialized:""}},this._overrides={},this._current="default",this._injected=[],this.rendition.hooks.content.register(this.inject.bind(this)),this.rendition.hooks.content.register(this.overrides.bind(this))}register(){if(0!==arguments.length)return 1===arguments.length&&"object"==typeof arguments[0]?this.registerThemes(arguments[0]):1===arguments.length&&"string"==typeof arguments[0]?this.default(arguments[0]):2===arguments.length&&"string"==typeof arguments[1]?this.registerUrl(arguments[0],arguments[1]):2===arguments.length&&"object"==typeof arguments[1]?this.registerRules(arguments[0],arguments[1]):void 0}default(t){if(t)return"string"==typeof t?this.registerUrl("default",t):"object"==typeof t?this.registerRules("default",t):void 0}registerThemes(t){for(var e in t)t.hasOwnProperty(e)&&("string"==typeof t[e]?this.registerUrl(e,t[e]):this.registerRules(e,t[e]))}registerCss(t,e){this._themes[t]={serialized:e},(this._injected[t]||"default"==t)&&this.update(t)}registerUrl(t,e){var i=new d.a(e);this._themes[t]={url:i.toString()},(this._injected[t]||"default"==t)&&this.update(t)}registerRules(t,e){this._themes[t]={rules:e},(this._injected[t]||"default"==t)&&this.update(t)}select(t){var e=this._current;this._current=t,this.update(t),this.rendition.getContents().forEach(i=>{i.removeClass(e),i.addClass(t)})}update(t){this.rendition.getContents().forEach(e=>{this.add(t,e)})}inject(t){var e,i=[],n=this._themes;for(var r in n)!n.hasOwnProperty(r)||r!==this._current&&"default"!==r||(((e=n[r]).rules&&Object.keys(e.rules).length>0||e.url&&-1===i.indexOf(e.url))&&this.add(r,t),this._injected.push(r));"default"!=this._current&&t.addClass(this._current)}add(t,e){var i=this._themes[t];i&&e&&(i.url?e.addStylesheet(i.url):i.serialized?(e.addStylesheetCss(i.serialized,t),i.injected=!0):i.rules&&(e.addStylesheetRules(i.rules,t),i.injected=!0))}override(t,e,i){var n=this.rendition.getContents();this._overrides[t]={value:e,priority:!0===i},n.forEach(e=>{e.css(t,this._overrides[t].value,this._overrides[t].priority)})}removeOverride(t){var e=this.rendition.getContents();delete this._overrides[t],e.forEach(e=>{e.css(t)})}overrides(t){var e=this._overrides;for(var i in e)e.hasOwnProperty(i)&&t.css(i,e[i].value,e[i].priority)}fontSize(t){this.override("font-size",t)}font(t){this.override("font-family",t,!0)}destroy(){this.rendition=void 0,this._themes=void 0,this._overrides=void 0,this._current=void 0,this._injected=void 0}};i(28);class p{constructor({type:t,cfiRange:e,data:i,sectionIndex:n,cb:r,className:s,styles:o}){this.type=t,this.cfiRange=e,this.data=i,this.sectionIndex=n,this.mark=void 0,this.cb=r,this.className=s,this.styles=o}update(t){this.data=t}attach(t){let e,{cfiRange:i,data:n,type:r,mark:s,cb:o,className:a,styles:h}=this;return"highlight"===r?e=t.highlight(i,n,o,a,h):"underline"===r?e=t.underline(i,n,o,a,h):"mark"===r&&(e=t.mark(i,n,o)),this.mark=e,this.emit(l.c.ANNOTATION.ATTACH,e),e}detach(t){let e,{cfiRange:i,type:n}=this;return t&&("highlight"===n?e=t.unhighlight(i):"underline"===n?e=t.ununderline(i):"mark"===n&&(e=t.unmark(i))),this.mark=void 0,this.emit(l.c.ANNOTATION.DETACH,e),e}text(){}}r()(p.prototype);var g=class{constructor(t){this.rendition=t,this.highlights=[],this.underlines=[],this.marks=[],this._annotations={},this._annotationsBySectionIndex={},this.rendition.hooks.render.register(this.inject.bind(this)),this.rendition.hooks.unloaded.register(this.clear.bind(this))}add(t,e,i,n,r,s){let o=encodeURI(e+t),h=new a.a(e).spinePos,l=new p({type:t,cfiRange:e,data:i,sectionIndex:h,cb:n,className:r,styles:s});return this._annotations[o]=l,h in this._annotationsBySectionIndex?this._annotationsBySectionIndex[h].push(o):this._annotationsBySectionIndex[h]=[o],this.rendition.views().forEach(t=>{l.sectionIndex===t.index&&l.attach(t)}),l}remove(t,e){let i=encodeURI(t+e);if(i in this._annotations){let t=this._annotations[i];if(e&&t.type!==e)return;this.rendition.views().forEach(e=>{this._removeFromAnnotationBySectionIndex(t.sectionIndex,i),t.sectionIndex===e.index&&t.detach(e)}),delete this._annotations[i]}}_removeFromAnnotationBySectionIndex(t,e){this._annotationsBySectionIndex[t]=this._annotationsAt(t).filter(t=>t!==e)}_annotationsAt(t){return this._annotationsBySectionIndex[t]}highlight(t,e,i,n,r){return this.add("highlight",t,e,i,n,r)}underline(t,e,i,n,r){return this.add("underline",t,e,i,n,r)}mark(t,e,i){return this.add("mark",t,e,i)}each(){return this._annotations.forEach.apply(this._annotations,arguments)}inject(t){let e=t.index;if(e in this._annotationsBySectionIndex){this._annotationsBySectionIndex[e].forEach(e=>{this._annotations[e].attach(t)})}}clear(t){let e=t.index;if(e in this._annotationsBySectionIndex){this._annotationsBySectionIndex[e].forEach(e=>{this._annotations[e].detach(t)})}}show(){}hide(){}},v=i(54),m=i(22),y=i(56);class b{constructor(t,e){this.settings=Object(s.extend)(this.settings||{},{width:null,height:null,ignoreClass:"",manager:"default",view:"iframe",flow:null,layout:null,spread:null,minSpreadWidth:800,stylesheet:null,resizeOnOrientationChange:!0,script:null,snap:!1,defaultDirection:"ltr"}),Object(s.extend)(this.settings,e),"object"==typeof this.settings.manager&&(this.manager=this.settings.manager),this.book=t,this.hooks={},this.hooks.display=new o.a(this),this.hooks.serialize=new o.a(this),this.hooks.content=new o.a(this),this.hooks.unloaded=new o.a(this),this.hooks.layout=new o.a(this),this.hooks.render=new o.a(this),this.hooks.show=new o.a(this),this.hooks.content.register(this.handleLinks.bind(this)),this.hooks.content.register(this.passEvents.bind(this)),this.hooks.content.register(this.adjustImages.bind(this)),this.book.spine.hooks.content.register(this.injectIdentifier.bind(this)),this.settings.stylesheet&&this.book.spine.hooks.content.register(this.injectStylesheet.bind(this)),this.settings.script&&this.book.spine.hooks.content.register(this.injectScript.bind(this)),this.themes=new f(this),this.annotations=new g(this),this.epubcfi=new a.a,this.q=new h.a(this),this.location=void 0,this.q.enqueue(this.book.opened),this.starting=new s.defer,this.started=this.starting.promise,this.q.enqueue(this.start)}setManager(t){this.manager=t}requireManager(t){return"string"==typeof t&&"default"===t?m.a:"string"==typeof t&&"continuous"===t?y.a:t}requireView(t){return"string"==typeof t&&"iframe"===t?v.a:t}start(){switch(this.settings.layout||"pre-paginated"!==this.book.package.metadata.layout&&"true"!==this.book.displayOptions.fixedLayout||(this.settings.layout="pre-paginated"),this.book.package.metadata.spread){case"none":this.settings.spread="none";break;case"both":this.settings.spread=!0}this.manager||(this.ViewManager=this.requireManager(this.settings.manager),this.View=this.requireView(this.settings.view),this.manager=new this.ViewManager({view:this.View,queue:this.q,request:this.book.load.bind(this.book),settings:this.settings})),this.direction(this.book.package.metadata.direction||this.settings.defaultDirection),this.settings.globalLayoutProperties=this.determineLayoutProperties(this.book.package.metadata),this.flow(this.settings.globalLayoutProperties.flow),this.layout(this.settings.globalLayoutProperties),this.manager.on(l.c.MANAGERS.ADDED,this.afterDisplayed.bind(this)),this.manager.on(l.c.MANAGERS.REMOVED,this.afterRemoved.bind(this)),this.manager.on(l.c.MANAGERS.RESIZED,this.onResized.bind(this)),this.manager.on(l.c.MANAGERS.ORIENTATION_CHANGE,this.onOrientationChange.bind(this)),this.manager.on(l.c.MANAGERS.SCROLLED,this.reportLocation.bind(this)),this.emit(l.c.RENDITION.STARTED),this.starting.resolve()}attachTo(t){return this.q.enqueue(function(){this.manager.render(t,{width:this.settings.width,height:this.settings.height}),this.emit(l.c.RENDITION.ATTACHED)}.bind(this))}display(t){return this.displaying&&this.displaying.resolve(),this.q.enqueue(this._display,t)}_display(t){if(this.book){this.epubcfi.isCfiString(t);var e,i=new s.defer,n=i.promise;return this.displaying=i,this.book.locations.length()&&Object(s.isFloat)(t)&&(t=this.book.locations.cfiFromPercentage(parseFloat(t))),(e=this.book.spine.get(t))?(this.manager.display(e,t).then(()=>{i.resolve(e),this.displaying=void 0,this.emit(l.c.RENDITION.DISPLAYED,e),this.reportLocation()},t=>{this.emit(l.c.RENDITION.DISPLAY_ERROR,t)}),n):(i.reject(new Error("No Section Found")),n)}}afterDisplayed(t){t.on(l.c.VIEWS.MARK_CLICKED,(e,i)=>this.triggerMarkEvent(e,i,t.contents)),this.hooks.render.trigger(t,this).then(()=>{t.contents?this.hooks.content.trigger(t.contents,this).then(()=>{this.emit(l.c.RENDITION.RENDERED,t.section,t)}):this.emit(l.c.RENDITION.RENDERED,t.section,t)})}afterRemoved(t){this.hooks.unloaded.trigger(t,this).then(()=>{this.emit(l.c.RENDITION.REMOVED,t.section,t)})}onResized(t,e){this.emit(l.c.RENDITION.RESIZED,{width:t.width,height:t.height},e),this.location&&this.location.start&&this.display(e||this.location.start.cfi)}onOrientationChange(t){this.emit(l.c.RENDITION.ORIENTATION_CHANGE,t)}moveTo(t){this.manager.moveTo(t)}resize(t,e,i){t&&(this.settings.width=t),e&&(this.settings.height=e),this.manager.resize(t,e,i)}clear(){this.manager.clear()}next(){return this.q.enqueue(this.manager.next.bind(this.manager)).then(this.reportLocation.bind(this))}prev(){return this.q.enqueue(this.manager.prev.bind(this.manager)).then(this.reportLocation.bind(this))}determineLayoutProperties(t){var e=this.settings.layout||t.layout||"reflowable",i=this.settings.spread||t.spread||"auto",n=this.settings.orientation||t.orientation||"auto",r=this.settings.flow||t.flow||"auto",s=t.viewport||"",o=this.settings.minSpreadWidth||t.minSpreadWidth||800,a=this.settings.direction||t.direction||"ltr";return(0===this.settings.width||this.settings.width>0)&&(0===this.settings.height||this.settings.height),{layout:e,spread:i,orientation:n,flow:r,viewport:s,minSpreadWidth:o,direction:a}}flow(t){var e=t;"scrolled"!==t&&"scrolled-doc"!==t&&"scrolled-continuous"!==t||(e="scrolled"),"auto"!==t&&"paginated"!==t||(e="paginated"),this.settings.flow=t,this._layout&&this._layout.flow(e),this.manager&&this._layout&&this.manager.applyLayout(this._layout),this.manager&&this.manager.updateFlow(e),this.manager&&this.manager.isRendered()&&this.location&&(this.manager.clear(),this.display(this.location.start.cfi))}layout(t){return t&&(this._layout=new u(t),this._layout.spread(t.spread,this.settings.minSpreadWidth),this._layout.on(l.c.LAYOUT.UPDATED,(t,e)=>{this.emit(l.c.RENDITION.LAYOUT,t,e)})),this.manager&&this._layout&&this.manager.applyLayout(this._layout),this._layout}spread(t,e){this.settings.spread=t,e&&(this.settings.minSpreadWidth=e),this._layout&&this._layout.spread(t,e),this.manager&&this.manager.isRendered()&&this.manager.updateLayout()}direction(t){this.settings.direction=t||"ltr",this.manager&&this.manager.direction(this.settings.direction),this.manager&&this.manager.isRendered()&&this.location&&(this.manager.clear(),this.display(this.location.start.cfi))}reportLocation(){return this.q.enqueue(function(){requestAnimationFrame(function(){var t=this.manager.currentLocation();if(t&&t.then&&"function"==typeof t.then)t.then(function(t){let e=this.located(t);e&&e.start&&e.end&&(this.location=e,this.emit(l.c.RENDITION.LOCATION_CHANGED,{index:this.location.start.index,href:this.location.start.href,start:this.location.start.cfi,end:this.location.end.cfi,percentage:this.location.start.percentage}),this.emit(l.c.RENDITION.RELOCATED,this.location))}.bind(this));else if(t){let e=this.located(t);if(!e||!e.start||!e.end)return;this.location=e,this.emit(l.c.RENDITION.LOCATION_CHANGED,{index:this.location.start.index,href:this.location.start.href,start:this.location.start.cfi,end:this.location.end.cfi,percentage:this.location.start.percentage}),this.emit(l.c.RENDITION.RELOCATED,this.location)}}.bind(this))}.bind(this))}currentLocation(){var t=this.manager.currentLocation();if(t&&t.then&&"function"==typeof t.then)t.then(function(t){return this.located(t)}.bind(this));else if(t){return this.located(t)}}located(t){if(!t.length)return{};let e=t[0],i=t[t.length-1],n={start:{index:e.index,href:e.href,cfi:e.mapping.start,displayed:{page:e.pages[0]||1,total:e.totalPages}},end:{index:i.index,href:i.href,cfi:i.mapping.end,displayed:{page:i.pages[i.pages.length-1]||1,total:i.totalPages}}},r=this.book.locations.locationFromCfi(e.mapping.start),s=this.book.locations.locationFromCfi(i.mapping.end);null!=r&&(n.start.location=r,n.start.percentage=this.book.locations.percentageFromLocation(r)),null!=s&&(n.end.location=s,n.end.percentage=this.book.locations.percentageFromLocation(s));let o=this.book.pageList.pageFromCfi(e.mapping.start),a=this.book.pageList.pageFromCfi(i.mapping.end);return-1!=o&&(n.start.page=o),-1!=a&&(n.end.page=a),i.index===this.book.spine.last().index&&n.end.displayed.page>=n.end.displayed.total&&(n.atEnd=!0),e.index===this.book.spine.first().index&&1===n.start.displayed.page&&(n.atStart=!0),n}destroy(){this.manager&&this.manager.destroy(),this.book=void 0}passEvents(t){l.a.forEach(e=>{t.on(e,e=>this.triggerViewEvent(e,t))}),t.on(l.c.CONTENTS.SELECTED,e=>this.triggerSelectedEvent(e,t))}triggerViewEvent(t,e){this.emit(t.type,t,e)}triggerSelectedEvent(t,e){this.emit(l.c.RENDITION.SELECTED,t,e)}triggerMarkEvent(t,e,i){this.emit(l.c.RENDITION.MARK_CLICKED,t,e,i)}getRange(t,e){var i=new a.a(t),n=this.manager.visible().filter((function(t){if(i.spinePos===t.index)return!0}));if(n.length)return n[0].contents.range(i,e)}adjustImages(t){if("pre-paginated"===this._layout.name)return new Promise((function(t){t()}));let e=t.window.getComputedStyle(t.content,null),i=.95*(t.content.offsetHeight-(parseFloat(e.paddingTop)+parseFloat(e.paddingBottom))),n=parseFloat(e.paddingLeft)+parseFloat(e.paddingRight);return t.addStylesheetRules({img:{"max-width":(this._layout.columnWidth?this._layout.columnWidth-n+"px":"100%")+"!important","max-height":i+"px!important","object-fit":"contain","page-break-inside":"avoid","break-inside":"avoid","box-sizing":"border-box"},svg:{"max-width":(this._layout.columnWidth?this._layout.columnWidth-n+"px":"100%")+"!important","max-height":i+"px!important","page-break-inside":"avoid","break-inside":"avoid"}}),new Promise((function(t,e){setTimeout((function(){t()}),1)}))}getContents(){return this.manager?this.manager.getContents():[]}views(){return(this.manager?this.manager.views:void 0)||[]}handleLinks(t){t&&t.on(l.c.CONTENTS.LINK_CLICKED,t=>{let e=this.book.path.relative(t);this.display(e)})}injectStylesheet(t,e){let i=t.createElement("link");i.setAttribute("type","text/css"),i.setAttribute("rel","stylesheet"),i.setAttribute("href",this.settings.stylesheet),t.getElementsByTagName("head")[0].appendChild(i)}injectScript(t,e){let i=t.createElement("script");i.setAttribute("type","text/javascript"),i.setAttribute("src",this.settings.script),i.textContent=" ",t.getElementsByTagName("head")[0].appendChild(i)}injectIdentifier(t,e){let i=this.book.packaging.metadata.identifier,n=t.createElement("meta");n.setAttribute("name","dc.relation.ispartof"),i&&n.setAttribute("content",i),t.getElementsByTagName("head")[0].appendChild(n)}}r()(b.prototype);e.a=b},function(t,e){var i={}.toString;t.exports=function(t){return i.call(t).slice(8,-1)}},function(t,e,i){var n=i(17);t.exports=function(t,e){if(!n(t))return t;var i,r;if(e&&"function"==typeof(i=t.toString)&&!n(r=i.call(t)))return r;if("function"==typeof(i=t.valueOf)&&!n(r=i.call(t)))return r;if(!e&&"function"==typeof(i=t.toString)&&!n(r=i.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},function(t,e,i){var n=i(7),r=i(15);t.exports=function(t,e){try{r(n,t,e)}catch(i){n[t]=e}return e}},function(t,e,i){var n=i(66),r=i(67),s=n("keys");t.exports=function(t){return s[t]||(s[t]=r(t))}},function(t,e){t.exports={}},function(t,e,i){var n=i(92),r=i(7),s=function(t){return"function"==typeof t?t:void 0};t.exports=function(t,e){return arguments.length<2?s(n[t])||s(r[t]):n[t]&&n[t][e]||r[t]&&r[t][e]}},function(t,e,i){var n=i(35),r=Math.min;t.exports=function(t){return t>0?r(n(t),9007199254740991):0}},function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(t,e,i){"use strict";var n,r,s=i(97),o=i(98),a=RegExp.prototype.exec,h=String.prototype.replace,l=a,c=(n=/a/,r=/b*/g,a.call(n,"a"),a.call(r,"a"),0!==n.lastIndex||0!==r.lastIndex),u=o.UNSUPPORTED_Y||o.BROKEN_CARET,d=void 0!==/()??/.exec("")[1];(c||d||u)&&(l=function(t){var e,i,n,r,o=this,l=u&&o.sticky,f=s.call(o),p=o.source,g=0,v=t;return l&&(-1===(f=f.replace("y","")).indexOf("g")&&(f+="g"),v=String(t).slice(o.lastIndex),o.lastIndex>0&&(!o.multiline||o.multiline&&"\n"!==t[o.lastIndex-1])&&(p="(?: "+p+")",v=" "+v,g++),i=new RegExp("^(?:"+p+")",f)),d&&(i=new RegExp("^"+p+"$(?!\\s)",f)),c&&(e=o.lastIndex),n=a.call(l?i:o,v),l?n?(n.input=n.input.slice(g),n[0]=n[0].slice(g),n.index=o.lastIndex,o.lastIndex+=n[0].length):o.lastIndex=0:c&&n&&(o.lastIndex=o.global?n.index+n[0].length:e),d&&n&&n.length>1&&h.call(n[0],i,(function(){for(r=1;r=l?t?"":void 0:(s=a.charCodeAt(h))<55296||s>56319||h+1===l||(o=a.charCodeAt(h+1))<56320||o>57343?t?a.charAt(h):s:t?a.slice(h,h+2):o-56320+(s-55296<<10)+65536}};t.exports={codeAt:s(!1),charAt:s(!0)}},function(t,e,i){var n,r=i(13),s=i(72),o=i(47),a=i(44),h=i(104),l=i(63),c=i(43),u=c("IE_PROTO"),d=function(){},f=function(t){return" -{% if not g.user.locale == 'en' %} - +{% if not current_user.locale == 'en' %} + {% endif %} diff --git a/cps/templates/book_table.html b/cps/templates/book_table.html index 518b3227..16836b7b 100644 --- a/cps/templates/book_table.html +++ b/cps/templates/book_table.html @@ -4,7 +4,7 @@ {% if sort %}data-sortable="true" {% endif %} data-visible = "{{visiblility.get(parameter)}}" data-escape="true" - {% if g.user.role_edit() %} + {% if current_user.role_edit() %} data-editable-type="text" data-editable-url="{{ url_for('edit-book.edit_list_book', param=parameter)}}" data-editable-title="{{ edit_text }}" @@ -53,10 +53,10 @@ + data-url="{{url_for('web.list_books')}}" data-locale="{{ current_user.locale }}"> - {% if g.user.role_edit() %} + {% if current_user.role_edit() %} {% endif %} @@ -66,37 +66,37 @@ {{ text_table_row('authors', _('Enter Authors'),_('Authors'), true, true) }} {{ text_table_row('tags', _('Enter Categories'),_('Categories'), false, true) }} {{ text_table_row('series', _('Enter Series'),_('Series'), false, true) }} - + {{ text_table_row('languages', _('Enter Languages'),_('Languages'), false, true) }} {{ text_table_row('publishers', _('Enter Publishers'),_('Publishers'), false, true) }} - - {% if g.user.check_visibility(32768) %} + + {% if current_user.check_visibility(32768) %} {{ book_checkbox_row('is_archived', _('Archive Status'), false)}} {% endif %} {{ book_checkbox_row('read_status', _('Read Status'), false)}} {% for c in cc %} {% if c.datatype == "int" %} - + {% elif c.datatype == "rating" %} - + {% elif c.datatype == "float" %} - + {% elif c.datatype == "enumeration" %} - + {% elif c.datatype in ["datetime"] %} {% elif c.datatype == "text" %} {{ text_table_row('custom_column_' + c.id|string, _('Enter ') + c.name, c.name, false, false) }} {% elif c.datatype == "comments" %} - + {% elif c.datatype == "bool" %} {{ book_checkbox_row('custom_column_' + c.id|string, c.name, false)}} {% else %} {% endif %} {% endfor %} - {% if g.user.role_delete_books() and g.user.role_edit()%} + {% if current_user.role_delete_books() and current_user.role_edit()%} {% endif %} @@ -104,8 +104,8 @@
{{_('Series Index')}}{{_('Series Index')}}{{_('Comments')}}{{_('Comments')}}{{c.name}}{{c.name}}{{c.name}}{{c.name}}{{c.name}}{{c.name}}{{c.name}}{{c.name}}{{c.name}}{{c.name}}{{_('Delete')}}
{% endblock %} {% block modal %} -{{ delete_book() }} -{% if g.user.role_edit() %} +{{ delete_book(current_user.role_delete_books()) }} +{% if current_user.role_edit() %} +
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
diff --git a/cps/templates/detail.html b/cps/templates/detail.html index 50151603..30430663 100755 --- a/cps/templates/detail.html +++ b/cps/templates/detail.html @@ -1,325 +1,369 @@ {% extends is_xhr|yesno("fragment.html", "layout.html") %} {% block body %}
-
-
-
- - -
-
-
- {% endblock %} {% block js %} + + {% endblock %} + diff --git a/cps/templates/email_edit.html b/cps/templates/email_edit.html index 2a844209..eaaecb18 100644 --- a/cps/templates/email_edit.html +++ b/cps/templates/email_edit.html @@ -10,16 +10,16 @@ {% if feature_support['gmail'] %}
- +
{% if content.mail_gmail_token == {} %} - + {% else %} {% endif %} @@ -48,11 +48,11 @@
- - + +
- +
@@ -63,7 +63,7 @@
- + {% if feature_support['gmail'] %}
{% endif %} @@ -80,7 +80,7 @@
- +
@@ -90,7 +90,7 @@

{{_('Denied Domains (Blacklist)')}}

- +
diff --git a/cps/templates/feed.xml b/cps/templates/feed.xml index 940fb0da..fb9166d7 100644 --- a/cps/templates/feed.xml +++ b/cps/templates/feed.xml @@ -1,5 +1,6 @@ + {{ url_for('static', filename='favicon.ico') }} urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2 {{ current_time }} - + {{instance}} {{instance}} @@ -43,16 +44,17 @@ {{entry.Books.title}} urn:uuid:{{entry.Books.uuid}} {{entry.Books.atom_timestamp}} - {% if entry.Books.authors.__len__() > 0 %} + {% for author in entry.Books.authors %} - {{entry.Books.authors[0].name}} + {{author.name}} - {% endif %} + {% endfor %} {% if entry.Books.publishers.__len__() > 0 %} {{entry.Books.publishers[0].name}} {% endif %} + {{entry.Books.pubdate.strftime("%Y-%m-%dT%H:%M:%S+00:00")}} {% for lang in entry.Books.languages %} {{lang.lang_code}} {% endfor %} diff --git a/cps/templates/generate_kobo_auth_url.html b/cps/templates/generate_kobo_auth_url.html index b8b74bda..5364f44a 100644 --- a/cps/templates/generate_kobo_auth_url.html +++ b/cps/templates/generate_kobo_auth_url.html @@ -3,7 +3,7 @@

{% if not warning %} - {{_('Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):')}} + {{_('Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):')}}

api_endpoint={{url_for("kobo.TopLevelEndpoint", auth_token=auth_token, _external=True)}} {% else %} diff --git a/cps/templates/grid.html b/cps/templates/grid.html index 1905d52d..3fa6958f 100644 --- a/cps/templates/grid.html +++ b/cps/templates/grid.html @@ -28,7 +28,7 @@

- {{ image.series(entry[0].series[0], alt=entry[0].series[0].name|shortentitle) }} + {{ image.book_cover(entry[0])}} {{entry.count}} diff --git a/cps/templates/http_error.html b/cps/templates/http_error.html index 103d1085..26c3c379 100644 --- a/cps/templates/http_error.html +++ b/cps/templates/http_error.html @@ -6,6 +6,9 @@ + {% if g.google_site_verification|length > 0 %} + + {% endif %} @@ -17,7 +20,7 @@ {% endif %} -
+

{{instance}}

@@ -38,7 +41,7 @@ {% if issue %}
{% endif %} diff --git a/cps/templates/index.html b/cps/templates/index.html index 0bb3da72..464a1461 100644 --- a/cps/templates/index.html +++ b/cps/templates/index.html @@ -1,7 +1,7 @@ {% import 'image.html' as image %} {% extends "layout.html" %} {% block body %} -{% if g.user.show_detail_random() and page != "discover" %} +{% if current_user.show_detail_random() and page != "discover" %}

{{_('Discover (Random Books)')}}

diff --git a/cps/templates/index.xml b/cps/templates/index.xml index 4ffd4290..cae3f629 100644 --- a/cps/templates/index.xml +++ b/cps/templates/index.xml @@ -1,5 +1,6 @@ + {{ url_for('static', filename='favicon.ico') }} urn:uuid:2853dacf-ed79-42f5-8e8a-a7bb3d1ae6a2 {{ current_time }} @@ -8,7 +9,7 @@ - + {{instance}} {{instance}} diff --git a/cps/templates/layout.html b/cps/templates/layout.html index 7502514a..1bee1c1d 100644 --- a/cps/templates/layout.html +++ b/cps/templates/layout.html @@ -1,14 +1,16 @@ {% from 'modal_dialogs.html' import restrict_modal, delete_book, filechooser_modal, delete_confirm_modal, change_confirm_modal %} {% import 'image.html' as image %} - + {{instance}} | {{title}} - + {% if g.google_site_verification|length > 0 %} + + {% endif %} @@ -20,14 +22,8 @@ {% endif %} - - - - +
- - + + + + @@ -98,26 +86,35 @@ - -
{{_('Keyboard Shortcuts')}}
{{_('Previous Page')}}
{{_('Next Page')}}
S {{_('Single Page Display')}}
O {{_('Long Strip Display')}}
B {{_('Scale to Best')}}
W {{_('Scale to Width')}}
H {{_('Scale to Height')}}
R {{_('Rotate Right')}}
L {{_('Rotate Left')}}
F {{_('Flip Image')}}
-
-
- - - - - - - - - - +
{{_('Settings')}}
{{_('Theme')}}: -
+
+
+
+ + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - + - - + + + + - - -
{{_('Settings')}}
{{_('Theme')}}: +
{{_('Display')}}: +
+ + +
+
{{_('Scale')}}: @@ -126,68 +123,83 @@ - -
{{_('Rotate')}}: -
- - - - -
-
{{_('Flip')}}: -
- - -
-
{{_('Direction')}}: -
+
+
{{_('Rotate')}}: +
+ + + + +
+
{{_('Flip')}}: +
+ + +
+
{{_('Direction')}}: +
{{_('Next Page')}}:
-
-
{{_('Scrollbar')}}:
-
-
+
+ + + + +
+
-
- -
- +
+ + diff --git a/cps/templates/readdjvu.html b/cps/templates/readdjvu.html index 3504e394..bdc3ef95 100644 --- a/cps/templates/readdjvu.html +++ b/cps/templates/readdjvu.html @@ -6,6 +6,10 @@ + {% if g.google_site_verification|length > 0 %} + + {% endif %} + @@ -14,6 +18,6 @@ -
+
diff --git a/cps/templates/readpdf.html b/cps/templates/readpdf.html index ca3f2389..fd6c7570 100644 --- a/cps/templates/readpdf.html +++ b/cps/templates/readpdf.html @@ -26,6 +26,9 @@ See https://github.com/adobe-type-tools/cmap-resources + {% if g.google_site_verification|length > 0 %} + + {% endif %} {{_('PDF Reader')}} | {{title}} @@ -40,7 +43,9 @@ See https://github.com/adobe-type-tools/cmap-resources -{% if not g.user.locale == 'en' %} - +{% if not current_user.locale == 'en' %} + {% endif %} -{% if not g.user.locale == 'en' %} - +{% if not current_user.locale == 'en' %} + {% endif %} {% endblock %} {% block header %} diff --git a/cps/templates/shelf.html b/cps/templates/shelf.html index b4596f79..d47d4d3f 100644 --- a/cps/templates/shelf.html +++ b/cps/templates/shelf.html @@ -4,11 +4,11 @@

{{title}}

- {% if g.user.role_download() %} + {% if current_user.role_download() %} {{ _('Download') }} {% endif %} - {% if g.user.is_authenticated %} - {% if (g.user.role_edit_shelfs() and shelf.is_public ) or not shelf.is_public %} + {% if current_user.is_authenticated %} + {% if (current_user.role_edit_shelfs() and shelf.is_public ) or not shelf.is_public %}
{{ _('Delete this Shelf') }}
{{ _('Edit Shelf Properties') }} diff --git a/cps/templates/shelf_edit.html b/cps/templates/shelf_edit.html index 2882d08a..58521e3d 100644 --- a/cps/templates/shelf_edit.html +++ b/cps/templates/shelf_edit.html @@ -8,7 +8,7 @@
- {% if g.user.role_edit_shelfs() %} + {% if current_user.role_edit_shelfs() %}
-
- {% if g.user.role_download() %} +
+ {% if current_user.role_download() %} {% if entry.Books.data|length %}
{% for format in entry.Books.data %} diff --git a/cps/templates/stats.html b/cps/templates/stats.html index 07219ea6..d41accc7 100644 --- a/cps/templates/stats.html +++ b/cps/templates/stats.html @@ -25,7 +25,7 @@ -{% if g.user.role_admin() %} +{% if current_user.role_admin() %}

{{_('System Statistics')}}

diff --git a/cps/templates/tasks.html b/cps/templates/tasks.html index 5cbc5f8b..4d645aa5 100644 --- a/cps/templates/tasks.html +++ b/cps/templates/tasks.html @@ -5,10 +5,10 @@ {% block body %}

{{_('Tasks')}}

-
+
- {% if g.user.role_admin() %} + {% if current_user.role_admin() %} {% endif %} @@ -16,7 +16,7 @@ - {% if g.user.role_admin() %} + {% if current_user.role_admin() %} {% endif %} @@ -27,8 +27,8 @@ {% endblock %} {% block modal %} -{{ delete_book() }} -{% if g.user.role_admin() %} +{{ delete_book(current_user.role_delete_books()) }} +{% if current_user.role_admin() %}
{{_('User')}}{{_('Task')}}{{_('Progress')}} {{_('Run Time')}} {{_('Start Time')}}{{_('Actions')}}
+ data-url="{{url_for('admin.list_users')}}" data-locale="{{ current_user.locale }}"> {{ user_table_row('name', _('Enter Username'), _('Username'), true) }} - {{ user_table_row('email', _('Enter E-mail Address'), _('E-mail Address'), true) }} - {{ user_table_row('kindle_mail', _('Enter E-Reader E-mail Address'), _('E-Reader E-mail'), false) }} + {{ user_table_row('email', _('Enter Email'), _('Email'), true) }} + {{ user_table_row('kindle_mail', _('Enter eReader Email'), _('eReader Email'), false) }} {{ user_select_translations('locale', url_for('admin.table_get_locale'), _('Locale'), true) }} {{ user_select_languages('default_language', url_for('admin.table_get_default_lang'), _('Visible Book Languages'), true) }} {{ user_table_row('allowed_tags', _("Edit Allowed Tags"), _("Allowed Tags"), false, tags) }} @@ -152,18 +152,18 @@ {{ user_single_checkbox_row("kobo_only_shelves_sync", _('Sync selected Shelves with Kobo'))}} {% endif %} {{ user_checkbox_row("sidebar_view", "detail_random", _('Show Random Books in Detail View'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_language", _('Show language selection'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show read/unread selection'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_series", _('Show series selection'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_category", _('Show category selection'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_random", _('Show random books'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_author", _('Show author selection'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_language", _('Show Language Section'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show Read/Unread Section'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_series", _('Show Series Section'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_category", _('Show Category Section'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_random", _('Show Random Books'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_author", _('Show Author Section'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_best_rated", _('Show Top Rated Books'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show Random Books'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_publisher", _('Show publisher selection'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_rating", _('Show ratings selection'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_format", _('Show file formats selection'), visiblility, sidebar_settings)}} - {{ user_checkbox_row("sidebar_view", "sidebar_archived", _('Show archived books'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_publisher", _('Show Publisher Section'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_rating", _('Show Ratings Section'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_format", _('Show File Formats Section'), visiblility, sidebar_settings)}} + {{ user_checkbox_row("sidebar_view", "sidebar_archived", _('Show Archived Books'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_download", _('Show Downloaded Books'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_list", _('Show Books List'), visiblility, sidebar_settings)}} @@ -185,8 +185,8 @@ -{% if not g.user.locale == 'en' %} - +{% if not current_user.locale == 'en' %} + {% endif %} {% endblock %} diff --git a/cps/tornado_wsgi.py b/cps/tornado_wsgi.py index af93219c..c1571ece 100644 --- a/cps/tornado_wsgi.py +++ b/cps/tornado_wsgi.py @@ -16,12 +16,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . - from tornado.wsgi import WSGIContainer import tornado from tornado import escape from tornado import httputil +from tornado.ioloop import IOLoop from typing import List, Tuple, Optional, Callable, Any, Dict, Text from types import TracebackType @@ -34,61 +34,67 @@ if typing.TYPE_CHECKING: class MyWSGIContainer(WSGIContainer): def __call__(self, request: httputil.HTTPServerRequest) -> None: - data = {} # type: Dict[str, Any] - response = [] # type: List[bytes] + if tornado.version_info < (6, 3, 0, -99): + data = {} # type: Dict[str, Any] + response = [] # type: List[bytes] - def start_response( - status: str, - headers: List[Tuple[str, str]], - exc_info: Optional[ - Tuple[ - "Optional[Type[BaseException]]", - Optional[BaseException], - Optional[TracebackType], - ] - ] = None, - ) -> Callable[[bytes], Any]: - data["status"] = status - data["headers"] = headers - return response.append + def start_response( + status: str, + headers: List[Tuple[str, str]], + exc_info: Optional[ + Tuple[ + "Optional[Type[BaseException]]", + Optional[BaseException], + Optional[TracebackType], + ] + ] = None, + ) -> Callable[[bytes], Any]: + data["status"] = status + data["headers"] = headers + return response.append - app_response = self.wsgi_application( - MyWSGIContainer.environ(request), start_response - ) + app_response = self.wsgi_application( + MyWSGIContainer.environ(self, request), start_response + ) + try: + response.extend(app_response) + body = b"".join(response) + finally: + if hasattr(app_response, "close"): + app_response.close() # type: ignore + if not data: + raise Exception("WSGI app did not call start_response") + + status_code_str, reason = data["status"].split(" ", 1) + status_code = int(status_code_str) + headers = data["headers"] # type: List[Tuple[str, str]] + header_set = set(k.lower() for (k, v) in headers) + body = escape.utf8(body) + if status_code != 304: + if "content-length" not in header_set: + headers.append(("Content-Length", str(len(body)))) + if "content-type" not in header_set: + headers.append(("Content-Type", "text/html; charset=UTF-8")) + if "server" not in header_set: + headers.append(("Server", "TornadoServer/%s" % tornado.version)) + + start_line = httputil.ResponseStartLine("HTTP/1.1", status_code, reason) + header_obj = httputil.HTTPHeaders() + for key, value in headers: + header_obj.add(key, value) + assert request.connection is not None + request.connection.write_headers(start_line, header_obj, chunk=body) + request.connection.finish() + self._log(status_code, request) + else: + IOLoop.current().spawn_callback(self.handle_request, request) + + + def environ(self, request: httputil.HTTPServerRequest) -> Dict[Text, Any]: try: - response.extend(app_response) - body = b"".join(response) - finally: - if hasattr(app_response, "close"): - app_response.close() # type: ignore - if not data: - raise Exception("WSGI app did not call start_response") - - status_code_str, reason = data["status"].split(" ", 1) - status_code = int(status_code_str) - headers = data["headers"] # type: List[Tuple[str, str]] - header_set = set(k.lower() for (k, v) in headers) - body = escape.utf8(body) - if status_code != 304: - if "content-length" not in header_set: - headers.append(("Content-Length", str(len(body)))) - if "content-type" not in header_set: - headers.append(("Content-Type", "text/html; charset=UTF-8")) - if "server" not in header_set: - headers.append(("Server", "TornadoServer/%s" % tornado.version)) - - start_line = httputil.ResponseStartLine("HTTP/1.1", status_code, reason) - header_obj = httputil.HTTPHeaders() - for key, value in headers: - header_obj.add(key, value) - assert request.connection is not None - request.connection.write_headers(start_line, header_obj, chunk=body) - request.connection.finish() - self._log(status_code, request) - - @staticmethod - def environ(request: httputil.HTTPServerRequest) -> Dict[Text, Any]: - environ = WSGIContainer.environ(request) + environ = WSGIContainer.environ(self, request) + except TypeError as e: + environ = WSGIContainer.environ(request) environ['RAW_URI'] = request.path return environ diff --git a/cps/translations/cs/LC_MESSAGES/messages.mo b/cps/translations/cs/LC_MESSAGES/messages.mo index 0f99e2b3..91130635 100644 Binary files a/cps/translations/cs/LC_MESSAGES/messages.mo and b/cps/translations/cs/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/cs/LC_MESSAGES/messages.po b/cps/translations/cs/LC_MESSAGES/messages.po index 6c8258f6..0e02f429 100644 --- a/cps/translations/cs/LC_MESSAGES/messages.po +++ b/cps/translations/cs/LC_MESSAGES/messages.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-06-09 21:11+0100\n" "Last-Translator: Lukas Heroudek \n" "Language: cs_CZ\n" @@ -15,498 +15,508 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statistika" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Server restartován, znovu načtěte stránku" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Vypínám server, zavřete okno" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Úspěšně obnovené připojení" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Neznámý příkaz" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Kniha byla úspěšně zařazena do fronty pro odeslání na %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Kniha byla úspěšně zařazena do fronty pro odeslání na %(eReadermail)s" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Neznámý" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Stránka správce" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Základní konfigurace" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Konfigurace uživatelského rozhraní" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Uživatel admin" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Vše" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Uživatel nenalezen" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Zobrazit vše" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Nezbývá žádný správce, nelze odebrat roli správce" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Konfigurace Calibre-Web aktualizována" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Opravdu chcete odstranit Kobo token?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Jste si jisti, že chcete odstranit tuto polici?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Jste si jisti, že chcete odstranit tuto polici?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Jste si jisti, že chcete odstranit tuto polici?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Jste si jisti, že chcete odstranit tuto polici?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Opravdu chcete vypnout?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Zakázat" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Povolit" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json není nakonfigurováno pro webové aplikace" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Umístění zápisového souboru není platné. Určete prosím platnou polohu" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Umístění zápisového souboru pro přístup není platné. Určete prosím platnou polohu" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Prosím zadejte LDAP poskytovatele, port, DN a Identifikátor objektu uživatele" -#: cps/admin.py:1179 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Zadejte platné uživatelské jméno pro obnovení hesla" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "Filtr objektů skupiny LDAP musí mít jeden “%s” formátový identifikátor" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Filtr objektů skupiny LDAP má nesrovnatelnou závorku" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "Filtr uživatelských objektů LDAP musí mít jeden “%s” formátový identifikátor" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Filtr uživatelských objektů LDAP má nesrovnatelnou závorku" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Přidat nového uživatele" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Změnit SMTP nastavení" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Chyba databáze: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Při odesílání zkušebního e-mailu došlo k chybě: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Prvně nastavte svou e-mailovou adresu..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Nastavení e-mailového serveru aktualizováno" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Neznámá chyba. Opakujte prosím později." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Upravit uživatele %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Heslo pro uživatele %(user)s resetováno" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Nejprve nakonfigurujte nastavení pošty SMTP..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Prohlížeč log souborů" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Požadování balíčku aktualizace" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Stahování balíčku aktualizace" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Rozbalování balíčku aktualizace" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Nahrazování souborů" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Databázová připojení jsou uzavřena" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Zastavuji server" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Aktualizace dokončena, klepněte na tlačítko OK a znovu načtěte stránku" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Aktualizace selhala:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP chyba" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Chyba připojení" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Vypršel časový limit při navazování spojení" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Všeobecná chyba" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Aktualizační soubor nemohl být uložen do Temp Dir" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Nepodařilo se vytvořit nejméně jednoho uživatele LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Nepodařilo se vytvořit nejméně jednoho uživatele LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Chyba: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Chyba: Žádná reakce od uživatele LDAP serveru" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Nejméně jeden uživatel LDAP nenalezen v databázi" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "Umístění databáze není platné, opravte prosím cestu" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "Databáze není zapisovatelná" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "Umístění souboru klíčů není platné, zadejte prosím správnou cestu" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "Umístění certifikátu není platné, zadejte prosím správnou cestu" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Nastavení e-mailového serveru aktualizováno" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Konfigurace funkcí" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Vyplňte všechna pole!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "E-mail není z platné domény" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Přidat nového uživatele" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Uživatel '%(user)s' vytvořen" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Byl nalezen existující účet pro tuto e-mailovou adresu nebo přezdívku." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Uživatel '%(nick)s' smazán" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Nezbývá žádný správce, nemůžete jej odstranit" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Uživatel '%(nick)s' aktualizován" @@ -519,122 +529,122 @@ msgstr "není nainstalováno" msgid "Execution permissions missing" msgstr "Chybí povolení k exekuci" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Vlastní sloupec %(column)d neexistuje v databázi" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Žádné" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Jejda! Vybraná kniha není k dispozici. Soubor neexistuje nebo není přístupný" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadata úspěšně aktualizována" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Soubor %(file)s nahrán" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Chybí zdrojový nebo cílový formát pro převod" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Kniha byla úspěšně zařazena do fronty pro převod do %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Při převodu této knihy došlo k chybě: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Nahraná kniha pravděpodobně existuje v knihovně, zvažte prosím změnu před nahráním nové: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s není platným jazykem" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Soubor s příponou '%(ext)s' nelze odeslat na tento server" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Soubor, který má být odeslán musí mít příponu" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Soubor %(filename)s nemohl být uložen do dočasného adresáře" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Nepodařilo se přesunout soubor obalu %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Formát knihy úspěšně smazán" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Kniha úspěšně smazána" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "upravit metadata" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Nepodařilo se vytvořit cestu %(path)s (oprávnění odepřeno)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Uložení souboru %(file)s se nezdařilo." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Formát souboru %(ext)s přidán do %(book)s" @@ -647,183 +657,188 @@ msgstr "Google Drive nastavení nebylo dokončeno, zkuste znovu deaktivovat a a msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Doména zpětného volání není ověřena, postupujte podle pokynů k ověření domény v konzole pro vývojáře google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s formát pro knihu: %(book)d nenalezen" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s nenalezen na Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s nenalezen: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Poslat do Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Tento e-mail byl odeslán přes Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web zkušební e-mail" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Zkušební e-mail" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Začínáme s Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Registrační e-mail pro uživatele: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Převést %(orig)s do %(format)s a poslat do Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Poslat %(format)s do Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Poslat do Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Požadovaný soubor nelze přečíst. Možná nesprávná oprávnění?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Mazání knihy selhalo %(id)s failed: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, fuzzy, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Mazání knihy %(id)s, cesta ke knize není platná %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Přejmenování názvu z: '%(src)s' na '%(dest)s' selhalo chybou: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Soubor %(file)s nenalezen na Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Přejmenování názvu z: '%(src)s' na '%(dest)s' selhalo chybou: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Cesta ke knize %(path)s nebyla nalezena na Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Byl nalezen existující účet pro tuto e-mailovou adresu." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Zadané uživatelské jméno je již použito" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Chyba stahování obalu" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Chyba formátu obalu" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Vytvoření cesty obalu selhalo" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Soubor obalu není platný, nebo nelze uložit" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Pouze jpg/jpeg jsou podporované soubory pro obal" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar binární soubor nenalezen" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Chyba provádění UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Objevte" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Pro získání platného api_endpoint pro zařízení Kobo, přístupte na calibre-web bez localhost" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo nastavení" @@ -832,9 +847,9 @@ msgstr "Kobo nastavení" msgid "Register with %(provider)s" msgstr "Registrovat s %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "nyní jste přihlášen jako: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -893,12 +908,13 @@ msgstr "Google Oauth chyba, prosím opakujte později." msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Přihlásit" @@ -914,149 +930,158 @@ msgstr "Token vypršel" msgid "Success! Please return to your device" msgstr "Úspěch! Vraťte se prosím do zařízení" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Knihy" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Zobrazit nedávné knihy" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Žhavé knihy" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Zobrazit žhavé knihy" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Nejlépe hodnocené knihy" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Zobrazit nejlépe hodnocené knihy" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Přečtené knihy" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Zobrazit prečtené a nepřečtené" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Nepřečtené knihy" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Zobrazit nepřečtené" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Objevte" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Zobrazit náhodné knihy" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Kategorie" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Zobrazit výběr kategorie" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Série" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Zobrazit výběr sérií" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Autoři" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Zobrazit výběr autora" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Vydavatelé" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Zobrazit výběr vydavatele" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Jazyky" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Zobrazit výběr jazyka" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Hodnocení" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Zobrazit výběr hodnocení" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Formáty souborů" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Zobrazit výběr formátů" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Archivované knihy" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Zobrazit archivované knihy" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Hledat" @@ -1080,14 +1105,14 @@ msgstr "Hodnocení >= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Rozšířené hledání" @@ -1138,7 +1163,7 @@ msgstr "Kniha byla odebrána z police: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Vytvořit polici" @@ -1165,73 +1190,73 @@ msgstr "Kniha úspěšně smazána" msgid "Change order of Shelf: '%(name)s'" msgstr "Změnit pořadí Police: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Police %(title)s vytvořena" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Police %(title)s změněna" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Došlo k chybě" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Veřejná police s názvem '%(title)s' již existuje." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Osobní police s názvem ‘%(title)s’ již existuje." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Police: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Chyba otevírání police. Police neexistuje nebo není přístupná" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Úlohy" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Čekám" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Selhalo" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Spuštěno" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Dokončeno" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Neznámý stav" @@ -1264,146 +1289,186 @@ msgstr "Nová aktualizace k dispozici. Klepnutím na tlačítko níže aktualizu msgid "No release information available" msgstr "Nejsou k dispozici žádné informace o verzi" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Objevte (Náhodné knihy)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Žhavé knihy (Nejstahovanější)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autoři: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Vydavatel: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Série: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Hodnocení: %(rating)s stars" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Soubor formátů: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategorie: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Jazyky: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Stáhnutí" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Seznam hodnocení" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Seznam formátů" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Kniha byla úspěšně zařazena do fronty pro odeslání na %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Nejprve nakonfigurujte nastavení pošty SMTP..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Kniha byla úspěšně zařazena do fronty pro odeslání na %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Při odesílání této knihy došlo k chybě: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Nejprve nakonfigurujte vaši kindle e-mailovou adresu.." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "E-mailový server není nakonfigurován, kontaktujte svého správce!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Registrovat" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "E-mailový server není nakonfigurován, kontaktujte svého správce!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Váš e-mail nemá povolení k registraci" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Potvrzovací e-mail byl odeslán na váš účet." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Nelze aktivovat ověření LDAP" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "nyní jste přihlášen jako: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Záložní přihlášení jako: ‘%(nickname)s’, server LDAP není dosažitelný nebo neznámý uživatel" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Nelze se přihlásit: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Špatné uživatelské jméno nebo heslo" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Nové heslo bylo zasláno na vaši emailovou adresu" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Neznámá chyba. Opakujte prosím později." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Zadejte platné uživatelské jméno pro obnovení hesla" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Nyní jste přihlášeni jako: '%(nickname)s'" +msgstr "nyní jste přihlášen jako: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s profil" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Profil aktualizován" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Byl nalezen existující účet pro tuto e-mailovou adresu." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Poslat do Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1446,35 +1511,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "upravit metadata" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Nahrávat" @@ -1490,15 +1555,15 @@ msgstr "Přezdívka" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "E-mail" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Poslat do Kindle e-mailová adresa" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Správce" @@ -1508,8 +1573,8 @@ msgstr "Správce" msgid "Password" msgstr "Heslo" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Stahovat" @@ -1534,16 +1599,12 @@ msgstr "Smazat" msgid "Public Shelf" msgstr "Veřejná police" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Přidat nového uživatele" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importovat LDAP uživatele" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Nastavení e-mailového serveru SMTP" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1564,11 +1625,11 @@ msgstr "SMTP přihlášení" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Z e-mailu" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1641,102 +1702,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Správa" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Zobrazit log" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Znovupřipojení ke Calibre databázi" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Restartovat" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Vypnout" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Verze" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detaily" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Současná verze" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Zkontrolovat aktualizace" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Provést aktualizaci" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Opravdu chcete restartovat?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Zrušit" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Opravdu chcete vypnout?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Probíhá aktualizace, prosím nenačítejte stránku znovu" @@ -1826,7 +1889,7 @@ msgid "Author" msgstr "Autor" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Popis" @@ -1851,7 +1914,7 @@ msgstr "Odstranit" msgid "Add Identifier" msgstr "Přidat identifikátor" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Štítky" @@ -1876,23 +1939,23 @@ msgid "Published Date" msgstr "Datum vydání" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Vydavatel" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Jazyk" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Ano" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Ne" @@ -1909,8 +1972,8 @@ msgid "Fetch Metadata" msgstr "Získat metadata" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1933,8 +1996,8 @@ msgstr "Kliknutím na obal načtěte metadata do formuláře" msgid "Loading..." msgstr "Načítání..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Zavřít" @@ -2162,7 +2225,7 @@ msgid "Enable Uploads" msgstr "Povolit nahrávání" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2178,7 +2241,7 @@ msgid "Enable Public Registration" msgstr "Povolit veřejnou registraci" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Použít e-mail jako přezdívku" #: cps/templates/config_edit.html:132 @@ -2368,6 +2431,52 @@ msgstr "Cesta k převaděči e-knih Kepubify" msgid "Location of Unrar binary" msgstr "Umístění Unrar binarních souborů" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Nastavení OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Resetovat uživatelské heslo" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Prohlížet konfiguraci" @@ -2380,7 +2489,7 @@ msgstr "Počet náhodných knih k zobrazení" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Počet autorů k zobrazení před skrytím (0 = Zakázat skrytí)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Motiv" @@ -2471,79 +2580,82 @@ msgstr "Přidat povolené/zakázané štítky" msgid "Add Allowed/Denied custom column values" msgstr "Přidat povolené/zakázané hodnoty vlastních sloupců" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Číst v prohližeči" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Poslechnout v prohlížeči" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, fuzzy, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publikováno" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Označit jako nepřečtené" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Označit jako přečtené" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Přečteno" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Obnovit z archivu" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Archívovat" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archivováno" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Popis:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Přidat do police" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Veřejné)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Upravit metadata" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "" +#, fuzzy +msgid "Gmail Account" +msgstr "Účet" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2567,10 +2679,11 @@ msgid "Attachment Size Limit" msgstr "Limit velikosti souboru" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Uložit nastavení a odeslat zkušební e-mail" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Zpět" @@ -2596,13 +2709,13 @@ msgstr "Zadejte jméno domény" msgid "Denied Domains (Blacklist)" msgstr "Zakázané domény pro registraci" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Další" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Otevřte soubor .kobo/Kobo eReader.conf v textovém editoru a vložte (nebo upravte):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Otevřte soubor .kobo/Kobo/Kobo eReader.conf v textovém editoru a vložte (nebo upravte):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2613,20 +2726,20 @@ msgstr "Kobo Sync token" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "E-mailový server není nakonfigurován, kontaktujte svého správce!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Vytvořit problém" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Zpět domů" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2656,80 +2769,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Start" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Oblíbené publikace z tohoto katalogu založené na počtu stažení." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Oblíbené publikace z tohoto katalogu založené na hodnocení." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Nedávno přidané knihy" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Nejnovější knihy" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Náhodné knihy" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Knihy seřazené podle autora" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Knihy seřazené podle vydavatele" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Knihy seřazené podle kategorie" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Knihy seřazené podle série" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Knihy seřazené podle jazyků" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Knihy řazené podle hodnocení" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Knihy seřazené podle souboru formátů" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Police" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Knihy organizované v policích" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Domů" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Přepnout navigaci" @@ -2737,48 +2850,48 @@ msgstr "Přepnout navigaci" msgid "Search Library" msgstr "Hledat v knihovně" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Nahrávání..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Chyba" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Nahrávání hotovo, zpracovávám, čekejte prosím..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Nastavení" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Účet" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Odhlásit se" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Nahrávání..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Chyba" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Nahrávání hotovo, zpracovávám, čekejte prosím..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Nastavení" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Prosím neobnovujte stránku" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Procházet" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "O knihovně" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Předchozí" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Podrobnosti o knize" @@ -2794,7 +2907,7 @@ msgstr "Zapamatovat si" msgid "Forgot Password?" msgstr "Zapomenuté heslo?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Přihlásit se pomocí Magic Link" @@ -2904,137 +3017,162 @@ msgstr "Calibre-Web katalog eknih" msgid "epub Reader" msgstr "Čtečka PDF" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Světlý" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Tmavý" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Zpět" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Po otevření postranních panelů přeformátujte text." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "Čtečka PDF" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Klávesové zkratky" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Předchozí strana" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Následujicí strana" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Změnit měřítko na nejlepší" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Změnit měřítko na šířku" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Změnit měřítko na výšku" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Změnit měřítko na nativní" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Otočit doprava" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Otočit doleva" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Převrátit obrázek" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Stránka správce" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Měřítko" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Nejlepší" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Šířka" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Výška" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Nativní" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Otočit" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Převrátit" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Vodorovně" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Svisle" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Směr" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Zleva doprava" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Zprava doleva" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3043,7 +3181,7 @@ msgstr "" msgid "DJVU Reader" msgstr "Čtečka PDF" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "Čtečka PDF" @@ -3062,7 +3200,7 @@ msgid "Choose a username" msgstr "Zvolte uživatelské jméno" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Vaše e-mailová adresa" #: cps/templates/remote_login.html:5 @@ -3081,10 +3219,6 @@ msgstr "Jakmile tak učiníte, budete automaticky přihlášeni na tomto zaříz msgid "This verification link will expire in 10 minutes." msgstr "Tento ověřovací odkaz vyprší za 10 minut." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3109,44 +3243,52 @@ msgstr "Datum vydání od" msgid "Published Date To" msgstr "Datum vydání do" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Vynechat štítky" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Vynechat série" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Vynechat série" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Vynechat jazyky" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Přípony" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Vynechat přípony" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Hodnoceni více než" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Hodnocení méně než" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3238,10 +3380,6 @@ msgstr "Průběh" msgid "Run Time" msgstr "Doba spuštění" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Čas spuštění" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3318,17 +3456,17 @@ msgstr "Zvolte uživatelské jméno" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Vaše e-mailová adresa" +msgid "Enter Email" +msgstr "Zkušební e-mail" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "Poslat do Kindle e-mailová adresa" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Zkušební e-mail" #: cps/templates/user_table.html:137 @@ -3398,10 +3536,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Zobrazit výběr sérií" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Zobrazit náhodné knihy" - diff --git a/cps/translations/de/LC_MESSAGES/messages.mo b/cps/translations/de/LC_MESSAGES/messages.mo index 14cb5cf5..464db7eb 100644 Binary files a/cps/translations/de/LC_MESSAGES/messages.mo and b/cps/translations/de/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/de/LC_MESSAGES/messages.po b/cps/translations/de/LC_MESSAGES/messages.po index 9a5d9a84..d6d9669d 100644 --- a/cps/translations/de/LC_MESSAGES/messages.po +++ b/cps/translations/de/LC_MESSAGES/messages.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" -"PO-Revision-Date: 2022-08-27 10:00+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" +"PO-Revision-Date: 2023-10-21 15:45+0200\n" "Last-Translator: Ozzie Isaacs\n" "Language: de\n" "Language-Team: \n" @@ -16,487 +16,493 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statistiken" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" -msgstr "Server neu gestartet, Seite bitte neu laden" +#: cps/admin.py:149 +msgid "Server restarted, please reload page." +msgstr "Server neu gestartet, Seite bitte neu laden." -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" -msgstr "Server wird heruntergefahren, Fenster bitte schließen" - -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Erfolgreich neu verbunden" +#: cps/admin.py:151 +msgid "Performing Server shutdown, please close window." +msgstr "Server wird heruntergefahren, Fenster bitte schließen." #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "Datenbank wurde erneut verbunden" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Unbekannter Befehl" -#: cps/admin.py:169 -#, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Buch erfolgreich zum Senden an %(kindlemail)s eingereiht" +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Bücher wurden für Metadaten Backup eingereiht, für das Ergebnis bitte Aufgaben überprüfen" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Unbekannt" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Admin Seite" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Basiskonfiguration" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Benutzeroberflächenkonfiguration" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Benutzer bearbeiten" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Alle" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Benutzer nicht gefunden" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} Benutzer erfolgreich gelöscht" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Zeige alle" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Ungültige Anfrage" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Guest Name kann nicht geändert werden" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Guest Benutzer kann diese Rolle nicht haben" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Kein Admin Benutzer verblieben Admin Berechtigung kann nicht entfernt werden" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "Wert muss true oder false sein" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ungültige Rolle" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Guest Benutzer kann diese Sichtbarkeit nicht haben" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Ungültige Sichtbarkeit" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Guest Sprache wird automatisch bestimmt und kann nicht eingestellt werden" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Keine gültige Sprache gewählt" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Keine gültige Buchsprache gewählt" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parameter wurde nicht gefunden" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Ungültige Lese Spalte" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Ungültiger Spaltenname für Einschränkung" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Konfiguration von Calibre-Web wurde aktualisiert" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Möchten Sie wirklich den Kobo Token löschen?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Möchten Sie wirklich diese Domain löschen?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Möchten Sie wirklich diesen Benutzer löschen?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Möchten Sie wirklich dieses Bücherregal löschen?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Möchten Sie wirklich die Anzeigesprache der ausgewählten Benutzer ändern?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "Möchten Sie wirklich die Büchersprachen für die ausgewählten Benutzer ändern?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Möchten Sie wirklich die ausgewählte Rolle für die ausgewählten Benutzer verändern?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Möchten Sie wirklich die ausgewählten Sichtbarkeitsbeschränkungen der ausgewählten Benutzer ändern?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "Möchten Sie wirklich die Sichtbarkeiten für die ausgewählten Benutzer verändern?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Möchten Sie wirklich die Synchronisation von Bücherregalen für die ausgewählten Benutzer verändern?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "Ort der Calibre Datenbank editieren?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "Calibre-Web wird nach neuen Covern suchen und Cover Miniaturansichten aktualisieren, dies kann eine Weile dauern?" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "Möchten Sie wirklich die Synchronisationsdatenbank von Calibre-Web löschen, um eine komplette Synchronisation zu erzwingen?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Verbieten" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Erlauben" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} Synchronisationseinträge gelöscht" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Tag nicht gefunden" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Ungültige Aktion" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json ist nicht für Web Anwendungen konfiguriert" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Logdatei Pfad ist ungültig, bitte einen gültigen Pfad angeben" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Zugriffs Logdatei Pfad ist ungültig, bitte einen gültigen Pfad angeben" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Bitte einen LDAP Server, Port, DN und Benutzer Objekt angeben" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "Bitte einen LDAP Service Account und Password eingeben" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Bitte einen LDAP Service Account eingeben" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP Gruppen Objekt Filter benötigt genau eine \"%s\" Format Kennung" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP Gruppen Objekt Filter hat ungleiche Anzahl von Klammern" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP Benutzer Objekt Filter benötigt genau eine \"%s\" Format Kennung" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP Benutzer Objekt Filter hat ungleiche Anzahl von Klammern" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "Der LDAP Member User Filter benötigt genau eine \"%s\" Formatierungsmarkierung" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "LDAP Member User Filter hat eine ungleiche Anzahl von geöffneten und geschlossenen Klammern" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CA-Zertifikat, Zertifikat oder Key Datei ist kein gültiger Pfad" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Neuen Benutzer hinzufügen" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "SMTP-Einstellungen ändern" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Gmail Account Verifikation erfolgreich" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "G-Mail Konto verifiziert." -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Datenbankfehler: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "Test E-Mail an %(email)s wurde zum Senden in die Warteschlange eingereiht, für das Ergebnis bitte Aufgaben überprüfen" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Es trat ein Fehler beim Versenden der Test-E-Mail auf: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Bitte zuerst E-Mail Adresse konfigurieren..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Einstellungen des E-Mail-Servers aktualisiert" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "Einstellungen für Geplante Aufgaben" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "Ungültigen Startzeitpunkt für Aufgaben spezifiziert" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "Ungültige Laufzeit für Aufgaben spezifiziert" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "Einstellungen für Geplante Aufgaben aktualisiert" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Es ist ein unbekannter Fehler aufgetreten. Bitte später erneut versuchen." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "Einstellungsdatenbank ist nicht schreibbar" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Benutzer %(nick)s bearbeiten" -#: cps/admin.py:1411 +#: cps/admin.py:1436 #, python-format -msgid "Password for user %(user)s reset" +msgid "Success! Password for user %(user)s reset" msgstr "Passwort für Benutzer %(user)s wurde zurückgesetzt" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." -msgstr "Bitte zuerst die SMTP-Einstellung konfigurieren ..." +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." +msgstr "Bitte zuerst die SMTP-Einstellung konfigurieren." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Logdatei Anzeige" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Frage Update an" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Lade Update herunter" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Entpacke Update" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Ersetze Dateien" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Schließe Datenbankverbindungen" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Stoppe Server" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Update abgeschlossen, bitte okay drücken und Seite neu laden" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Update fehlgeschlagen:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP Fehler" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Verbindungsfehler" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Timeout beim Verbindungsaufbau" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Allgemeiner Fehler" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "Updatedatei konnte nicht in Temporärem Ordner gespeichert werden" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "Dateien konnten während des Updates nicht ausgetauscht werden" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "Mindestens ein LDAP Benutzer konnte nicht extrahiert werden" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Mindestens ein LDAP Benutzer konnte nicht erzeugt werden" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Fehler: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Fehler: Keine Benutzerinformationen von LDAP Server empfangen" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Mindestens ein LDAP Benutzer wurde nicht in der Datenbank gefudnen" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Benutzer erfolgreich importiert" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "DB Pfad ist nicht gültig, bitte einen gültigen Pfad angeben" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "Datenbank ist nicht schreibbar" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "Schlüsseldatei ist ungültig, bitte einen gültigen Pfad angeben" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "Zertifikatsdatei ist ungültig, bitte einen gültigen Pfad angeben" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "Passwortlänge muss zwischen 1 und 40 Zeichen liegen" + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "Datenbankeinstellung aktualisiert" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "Datenbank-Konfiguration" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" -msgstr "Bitte alle Felder ausfüllen!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Bitte alle Felder ausfüllen." -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "E-Mail bezieht sich nicht auf eine gültige Domain" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Neuen Benutzer hinzufügen" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Benutzer '%(user)s' angelegt" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "Es existiert bereits ein Account für diese E-Mailadresse oder diesen Benutzernamen." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Benutzer '%(nick)s' gelöscht" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Guest Benutzer kann nicht gelöscht werden" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Benutzer kann nicht gelöscht werden, es wäre kein Admin Benutzer übrig" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" -msgstr "" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "E-Mail kann nicht leer sein und muss gültig sein" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Benutzer '%(nick)s' aktualisiert" @@ -509,122 +515,122 @@ msgstr "Nicht installiert" msgid "Execution permissions missing" msgstr "Ausführeberechtigung fehlt" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Benutzerdefinierte Spalte Nr. %(column)d ist nicht in Calibre Datenbank vorhanden" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Keine" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Öffnen des Buchs fehlgeschlagen. Datei existiert nicht oder ist nicht zugänglich" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "Benutzer hat keine Berechtigung Cover hochzuladen" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "IDs unterscheiden nicht Groß-Kleinschreibung, alte ID wird überschrieben" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadaten wurden erfolgreich aktualisiert" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "Fehler beim editieren des Buches: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Datei %(file)s hochgeladen" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Quell- oder Zielformat für Konvertierung fehlt" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Buch wurde erfolgreich für die Konvertierung nach %(book_format)s eingereiht" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Es trat ein Fehler beim Konvertieren des Buches auf: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Das hochgeladene Buch existiert evtl. schon in der Bibliothek: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "'%(langname)s' ist keine gültige Sprache" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Dateiendung '%(ext)s' kann nicht auf diesen Server hochgeladen werden" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Dateien müssen eine Erweiterung haben, um hochgeladen zu werden" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Die Datei %(filename)s konnte nicht im temporären Ordner gespeichert werden" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Fehler beim Verschieben der Cover Datei %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Buch Format erfolgreich gelöscht" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Buch erfolgreich gelöscht" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "Keine Erlaubnis zum Bücher löschen" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "Metadaten editieren" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s ist keine gültige Zahl, Eintrag wird ignoriert" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "Benutzer hat kein Recht zusätzliche Dateiformate hochzuladen" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Fehler beim Erzeugen des Pfads %(path)s (Zugriff verweigert)" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Fehler beim Speichern der Datei %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Dateiformat %(ext)s zu %(book)s hinzugefügt" @@ -637,179 +643,181 @@ msgstr "Google Drive Setup is nicht komplett, bitte versuche Google Drive zu dea msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Callback Domain ist nicht verifiziert, bitte Domain in der Google Developer Console verifizieren" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s Format für Buch-ID %(book)d nicht gefunden" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s von Buch %(fn)s nicht auf Google Drive gefunden" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s nicht gefunden: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 -msgid "Send to E-Reader" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" msgstr "An E-Reader senden" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +msgid "This Email has been sent via Calibre-Web." msgstr "Diese E-Mail wurde durch Calibre-Web versendet." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" msgstr "Calibre-Web Test-E-Mail" -#: cps/helper.py:115 -msgid "Test e-mail" -msgstr "Test-E-Mail" +#: cps/helper.py:116 +msgid "Test Email" +msgstr "Test E-Mail" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Loslegen mit Calibre-Web" -#: cps/helper.py:137 +#: cps/helper.py:138 #, python-format -msgid "Registration e-mail for user: %(name)s" -msgstr "Registrierungs-E-Mail für Benutzer %(name)s" +msgid "Registration Email for user: %(name)s" +msgstr "Registrierungs-E-Mail für Benutzer: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Konvertiere %(orig)s nach %(format)s und sende an E-Reader" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Sende %(format)s an E-Reader" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "%(book)s an E-Reader gesendet" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Die angeforderte Datei konnte nicht gelesen werden. Evtl. falsche Zugriffsrechte?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "Gelesenen Status konnte nicht aktualisiert werden: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Löschen des Ordners für Buch %(id)s ist fehlgeschlagen, der Pfad hat Unterordner: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Löschen von Buch %(id)s fehlgeschlagen: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Lösche Buch %(id)s nur aus Datenbank, Pfad zum Buch in Datenbank ist nicht gültig: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Umbenennen des Autors '%(src)s' zu '%(dest)s' schlug fehl: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Datei %(file)s wurde nicht auf Google Drive gefunden" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Umbenennen des Titels '%(src)s' zu '%(dest)s' schlug fehl: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "Fehler beim umbenennen der Datei im Pfad: {}" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Buchpfad %(path)s wurde nicht auf Google Drive gefunden" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "Es existiert bereits ein Benutzer für diese E-Mailadresse" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "Es existiert bereits ein Benutzerkonto für diese E-Mail Adresse" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Benutzername ist schon vorhanden" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "Ungültiges E-Mail Adressformat" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "Passwort stimmt nicht mit den Passwortregln überein" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "Python Module 'advocate' ist nicht installiert, wird aber für das Cover hochladen benötigt" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Fehler beim Herunterladen des Covers" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Coverdatei fehlerhaft" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "Keine Berechtigung Cover von Localhost oder dem lokalen Netzwerk hochzuladen" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Fehler beim Erzeugen des Ordners für die Coverdatei" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Cover Datei ist keine gültige Bilddatei, kann nicht gespeichert werden" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Nur jpg/jpeg/png/webp/bmp Dateien werden als Coverdatei unterstützt" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "Ungültiger Cover Dateiinhalt" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Es werden nur jpg/jpeg Dateien als Cover untertützt" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "UnRar Programm nicht gefunden" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "Fehler beim Ausführen von UnRar" -#: cps/helper.py:1040 -#, fuzzy +#: cps/helper.py:1077 msgid "Cover" -msgstr "Entdecke" +msgstr "Titelbild" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" -msgstr "" +msgstr "Alle Bücher für Metadaten Backup einreihen" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Bitte nicht von \"localhost\" auf Calibre-Web zugreifen, um einen gültigen api_endpoint für Kobo Geräte zu erhalten" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo Setup" @@ -818,9 +826,9 @@ msgstr "Kobo Setup" msgid "Register with %(provider)s" msgstr "Anmelden mit %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "Du bist nun eingeloggt als '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -879,12 +887,13 @@ msgstr "Google Oauth Fehler, bitte später erneut versuchen." msgid "Google Oauth error: {}" msgstr "Google Oauth Fehler: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Sterne" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Login" @@ -900,149 +909,149 @@ msgstr "Token ist abgelaufen" msgid "Success! Please return to your device" msgstr "Erfolg! Bitte zum Gerät zurückkehren" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Bücher" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Zeige kürzlich hinzugefügte Bücher" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Beliebte Bücher" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Zeige beliebte Bücher" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Heruntergeladene Bücher" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Zeige heruntergeladene Bücher" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Best bewertete Bücher" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Bestbewertete Bücher anzeigen" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Gelesene Bücher" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +msgid "Show Read and Unread" msgstr "Zeige gelesene/ungelesene Bücher" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Ungelesene Bücher" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Zeige Ungelesene" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Entdecke" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Zeige zufällige Bücher" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Kategorien" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +msgid "Show Category Section" msgstr "Zeige Kategorienauswahl" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Serien" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +msgid "Show Series Section" msgstr "Zeige Serienauswahl" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Autoren" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +msgid "Show Author Section" msgstr "Zeige Autorenauswahl" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Verleger" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +msgid "Show Publisher Section" msgstr "Zeige Verlegerauswahl" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Sprachen" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +msgid "Show Language Section" msgstr "Zeige Sprachauswahl" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Bewertungen" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +msgid "Show Ratings Section" msgstr "Zeige Bewertungsauswahl" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Dateiformate" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +msgid "Show File Formats Section" msgstr "Zeige Dateiformatauswahl" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Archivierte Bücher" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +msgid "Show Archived Books" msgstr "Zeige archivierte Bücher" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Bücherliste" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Zeige Bücherliste" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Suche" @@ -1065,15 +1074,15 @@ msgid "Rating >= %(rating)s" msgstr "Bewertung >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Lesestatus = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Fehler bei der Suche nach eigenen Spalten, bitte Calibre-Web neustarten" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Erweiterte Suche" @@ -1123,7 +1132,7 @@ msgstr "Das Buch wurde aus dem Bücherregal: %(sname)s entfernt" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "Sie haben keine Berechtigung um Bücher aus diesem Bücherregal zu löschen" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Bücherregal erzeugen" @@ -1148,73 +1157,73 @@ msgstr "Bücherregal erfolgreich gelöscht" msgid "Change order of Shelf: '%(name)s'" msgstr "Reihenfolge in Bücherregal '%(name)s' verändern" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "Sie haben keine Berechtigung um öffentliche Bücherregal zu erzeugen" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Bücherregal %(title)s erzeugt" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Bücherregal %(title)s verändert" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Es trat ein Fehler auf" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Es existiert bereit ein öffentliches Bücherregal mit dem Name '%(title)s'." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Es existiert bereit ein privates Bücherregal mit dem Name '%(title)s'." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Bücherregal: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Fehler beim Öffnen des Bücherregals. Bücherregal exisitert nicht oder ist nicht zugänglich" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Aufgaben" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Wartend" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Fehlgeschlagen" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Gestartet" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Beendet" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "Beendet" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "Abgebrochen" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Unbekannter Status" @@ -1247,146 +1256,177 @@ msgstr "Ein neues Update ist verfügbar. Klicke auf den Button unten, um auf Ver msgid "No release information available" msgstr "Keine Releaseinformationen verfügbar" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Entdecke (Zufällige Bücher)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Beliebte Bücher (am meisten Downloads)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Von %(user)s heruntergeladene Bücher" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Author: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Verleger: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Serie: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "Bewertung: Keine" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Bewertung: %(rating)s Sterne" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Dateiformat: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategorie: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Sprache: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Downloads" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Bewertungsliste" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Liste der Dateiformate" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Buch erfolgreich zum Senden an %(kindlemail)s eingereiht" +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "Bitte zuerst die SMTP-Einstellung konfigurieren..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Buch erfolgreich zum Senden an %(eReadermail)s eingereiht" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Beim Senden des Buchs trat ein Fehler auf: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." -msgstr "Bitte zuerst die Kindle E-Mailadresse konfigurieren..." +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "Bitte zuerst die E-Reader E-Mailadresse konfigurieren." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "Der E-Mail Server ist nicht konfigurierte, bitte den Administrator kontaktieren!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "Bitte eine Minute warten vor der Registrierung des nächsten Benutzers " -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Registrieren" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" -msgstr "Diese E-Mail ist nicht für die Registrierung zugelassen" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Der E-Mail Server ist nicht konfigurierte, bitte den Administrator kontaktieren." -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." +msgstr "Diese E-Mail ist nicht für die Registrierung zugelassen." + +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Eine Bestätigungs-E-Mail wurde an deinen E-Mail Account versendet." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "LDAP-Authentifizierung kann nicht aktiviert werden" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "Bitte eine Minute vor dem nächsten Loginversuche warten " + +#: cps/web.py:1376 +#, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "Du bist nun eingeloggt als '%(nickname)s'" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Rückfall Login als: '%(nickname)s', LDAP Server ist nicht erreichbar, oder der Nutzer ist unbekannt" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "Login nicht erfolgreich: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "Falscher Benutzername oder Passwort" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "Das neue Passwort wurde an die E-Mail Adresse verschickt" -#: cps/web.py:1320 +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "Es ist ein unbekannter Fehler aufgetreten. Bitte später erneut versuchen." + +#: cps/web.py:1405 msgid "Please enter valid username to reset password" msgstr "Bitte einen gültigen Benutzernamen zum Zurücksetzen des Passworts angeben" -#: cps/web.py:1327 +#: cps/web.py:1413 #, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Eingeloggt als: '%(nickname)s'" +msgstr "Du bist nun eingeloggt als: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s's Profil" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +msgid "Success! Profile Updated" msgstr "Profil aktualisiert" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Es existiert bereits ein Benutzer für diese E-Mailadresse." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Keine gültige gmail.json Datei mit Oauth informationen gefunden" +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s an E-Reader gesendet" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1429,35 +1469,34 @@ msgstr "Konvertiere" msgid "Reconnecting Calibre database" msgstr "Calibre Datenbank wird neu verbunden" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "E-Mail" -#: cps/tasks/metadata_backup.py:47 -#, fuzzy +#: cps/tasks/metadata_backup.py:46 msgid "Backing up Metadata" -msgstr "Metadaten editieren" +msgstr "Metadaten Backup läuft" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "%(count)s Cover Miniaturansichten erzeugt" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "Cover Miniaturansichtern" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "{0} Serien Miniaturansichten erzeugt" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "Cover Miniaturansichten Cache wird gelöscht" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Upload" @@ -1473,14 +1512,14 @@ msgstr "Benutzername" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "E-Mail" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "An E-Reader E-Mail Adresse senden" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Admin" @@ -1490,8 +1529,8 @@ msgstr "Admin" msgid "Password" msgstr "Passwort" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Download" @@ -1516,16 +1555,12 @@ msgstr "Löschen" msgid "Public Shelf" msgstr "Öffentliches Bücherregal" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Neuen Benutzer hinzufügen" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "LDAP Benutzer importieren" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Einstellungen des SMTP-Servers" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1546,11 +1581,11 @@ msgstr "SMTP-Login" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Absenderadresse" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "E-Mail Service" #: cps/templates/admin.html:91 @@ -1622,102 +1657,104 @@ msgid "Scheduled Tasks" msgstr "Geplante Aufgabe" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "Zeitpunkt an dem die Aufgabe startet" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "Maximale Aufgabendauer" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "Buchcover Miniaturansichten erzeugen" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "Seriencover Miniaturansichten erzeugen" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "Mit Calibre Bibliothek neuverbinden" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "Metadaten Backup Datei erzeugen " + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" msgstr "Cover Miniaturansichten aktualisieren" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Administration" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Debug Daten herunterladen" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Logdateien ansehen" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Calibre-DB neu verbinden" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Neustart" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Calibre-Web beenden" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "Versionsinformation" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Version" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Details" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Aktuelle Version" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Nach Update suchen" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Update durchführen" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Calibre-Web wirklich neustarten?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Abbruch" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Calibre-Web wirklich anhalten?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Updatevorgang, Seite bitte nicht neu laden" @@ -1737,7 +1774,7 @@ msgstr "Sortiere nach Buchdatum, Neuestes zuerst" #: cps/templates/author.html:27 cps/templates/index.html:75 #: cps/templates/search.html:32 cps/templates/shelf.html:21 msgid "Sort according to book date, oldest first" -msgstr "Sortiere nach Buchdatum, Aältestes zuerst" +msgstr "Sortiere nach Buchdatum, Ältestes zuerst" #: cps/templates/author.html:28 cps/templates/index.html:76 #: cps/templates/search.html:33 cps/templates/shelf.html:22 @@ -1807,7 +1844,7 @@ msgid "Author" msgstr "Autor" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Beschreibung" @@ -1832,7 +1869,7 @@ msgstr "Entfernen" msgid "Add Identifier" msgstr "ID hinzufügen" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Tags" @@ -1857,23 +1894,23 @@ msgid "Published Date" msgstr "Herausgabedatum" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Herausgeber" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Sprache" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Ja" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Nein" @@ -1890,8 +1927,8 @@ msgid "Fetch Metadata" msgstr "Metadaten laden" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1913,8 +1950,8 @@ msgstr "Klicke auf das Bild, um die Metadaten zu übertragen" msgid "Loading..." msgstr "Lade..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Schließen" @@ -2139,7 +2176,7 @@ msgid "Enable Uploads" msgstr "Hochladen aktivieren" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "(Bitte stellen Sie sicher das sie über die Upload Berechtigung verfügen)" #: cps/templates/config_edit.html:112 @@ -2155,7 +2192,7 @@ msgid "Enable Public Registration" msgstr "Öffentliche Registrierung aktivieren" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Benutze E-Mail als Benutzername" #: cps/templates/config_edit.html:132 @@ -2345,6 +2382,50 @@ msgstr "Pfad zum Kepubify E-Book Konverter" msgid "Location of Unrar binary" msgstr "Pfad zur UnRar-Binärdatei" +#: cps/templates/config_edit.html:361 +msgid "Security Settings" +msgstr "Sicherheitseinstellungen" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "Login Fehlversuche begrenzen" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "Sessionschutz" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "Einfach" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "Stark" + +#: cps/templates/config_edit.html:380 +msgid "User Password policy" +msgstr "Passwort Regeln" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "Minimale Passwortlänge" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "Erzwinge Nummer" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "Erzwinge Kleinbuchstaben" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "Erzwinge Großbuchstaben" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "Erzwinge Spezialzeichen" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Ansichtskonfiguration" @@ -2357,7 +2438,7 @@ msgstr "Anzahl anzuzeigender zufälliger Bücher" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Anzahl in Übersicht anzuzeigender Autoren (0=alle werden angezeigt)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Theme" @@ -2446,80 +2527,82 @@ msgstr "Erlaubte/Verbotene Tags hinzufügen" msgid "Add Allowed/Denied custom column values" msgstr "Erlaubte/Verbotene Calibre Spalten hinzufügen" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Im Browser lesen" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Im Browser anhören" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "Buch %(index)s von %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Herausgabedatum" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Als ungelesen markieren" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Als gelesen markieren" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Gelesen" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Vom Archiv wiederherstellen" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Zum Archiv hinzufügen" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archiviert" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Beschreibung:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Zu Bücherregal hinzufügen" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Öffentlich)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Metadaten bearbeiten" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Wähle Server Typ" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "Benutze Standard E-Mail Account" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Gmail Account mit Oauth2 Verification" +msgid "Gmail Account" +msgstr "G-Mail Konto" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Gmail Account als E-Mail Server verwenden" +msgid "Setup Gmail Account" +msgstr "G-Mail Konto einrichten" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2542,10 +2625,10 @@ msgid "Attachment Size Limit" msgstr "Anhangsgröße" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" -msgstr "Einstellungen speichern und Test-E-Mail versenden" +msgid "Save and Send Test Email" +msgstr "Einstellungen speichern und Test E-Mail versenden" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Zurück" @@ -2571,13 +2654,13 @@ msgstr "Domainnamen eingeben" msgid "Denied Domains (Blacklist)" msgstr "Verbotene Domains für eine Registrierung" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Nächste" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Öffne die .kobo/Kobo eReader.conf Datei in einem Texteditor und füge hinzu (oder ersetze):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Öffne die .kobo/Kobo/Kobo eReader.conf Datei in einem Texteditor und füge hinzu (oder ersetze):" #: cps/templates/generate_kobo_auth_url.html:11 msgid "Kobo Token:" @@ -2587,19 +2670,19 @@ msgstr "Kobo Token:" msgid "List" msgstr "Liste" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Calibre-Web Instanz ist nicht konfiguriert, bitte den Administrator kontaktieren" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Issue erzeugen" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Zurück zur Hauptseite" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "Benutzer ausloggem" @@ -2629,80 +2712,80 @@ msgstr "Sortiere Serienindex aufsteigend" msgid "Sort descending according to series index" msgstr "Sortiere Serienindex absteigend" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Start" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Bücher alphabetisch" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Bücher alphabetisch sortiert" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Beliebte Publikationen aus dieser Bibliothek basierend auf Anzahl der Downloads." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Beliebte Veröffentlichungen dieses Katalogs basierend auf Bewertung." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Kürzlich hinzugefügte Bücher" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Die neuesten Bücher" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Zufällige Bücher" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Bücher nach Autoren sortiert" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Bücher nach Verlegern sortiert" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Bücher nach Kategorien sortiert" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Bücher nach Serien sortiert" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Bücher nach Sprache sortiert" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Bücher nach Bewertungen sortiert" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Bücher nach Dateiformaten sortiert" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Bücherregale" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Bücher in Bücherregalen organisiert" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Home" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Nagivation umschalten" @@ -2710,48 +2793,48 @@ msgstr "Nagivation umschalten" msgid "Search Library" msgstr "Bibiliothek durchsuchen" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Lade hoch..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Fehler" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Hochladen beendet, verarbeite Daten, bitte warten..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Einstellungen" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Account" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Logout" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Lade hoch..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Fehler" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Hochladen beendet, verarbeite Daten, bitte warten..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Einstellungen" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Bitte die Seite nicht neu laden" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Durchsuchen" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Über" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Vorheriger Eintrag" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Buchdetails" @@ -2767,7 +2850,7 @@ msgstr "Merken" msgid "Forgot Password?" msgstr "Passwort vergessen?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Einloggen mit magischem Link" @@ -2875,135 +2958,159 @@ msgstr "Calibre-Web E-Book-Katalog" msgid "epub Reader" msgstr "epub-Leser" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Hell" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Dunkel" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "Sepia" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 msgid "Black" msgstr "Schwarz" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Text umbrechen, wenn Seitenleiste geöffnet ist." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "Schriftgröße" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "Comic-Leser" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Tastaturkürzel" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Vorherige Seite" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Nächste Seite" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "Einfach Seitendarstellung" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "Fortlaufende Seitendarstellung" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Optimale Skalierung" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Skaliere auf Breite" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Skaliere auf Höhe" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Skaliere 1:1" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Rechts rotieren" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Links rotieren" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Bild umdrehen" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Darstellung" + +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "Einzelne Seite" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "Fortlaufend" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Skalierung" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Beste" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Breite" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Höhe" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "1:1" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Rotieren" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Umdrehen" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Horizontal" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Vertikal" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Leserichtung" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Links nach rechts" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Rechts nach links" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Zurück nach oben" +msgstr "Auf Anfang zurücksetzen" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Position merken" +msgstr "Position speichern" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Scrollleiste" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Zeige" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Verstecke" @@ -3011,7 +3118,7 @@ msgstr "Verstecke" msgid "DJVU Reader" msgstr "DJVU-Leser" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "PDF-Reader" @@ -3028,7 +3135,7 @@ msgid "Choose a username" msgstr "Wähle einen Benutzernamen" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Deine E-Mail-Adresse" #: cps/templates/remote_login.html:5 @@ -3047,10 +3154,6 @@ msgstr "Danach wirst du automatisch auf diesem Gerät eingeloggt sein." msgid "This verification link will expire in 10 minutes." msgstr "Dieser Link wird in 10 Minuten ablaufen." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "Thumbnails für Bücher Cover erzeugen" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "Thumbnails für Serien Cover erzeugen" @@ -3075,43 +3178,51 @@ msgstr "Herausgabedatum von" msgid "Published Date To" msgstr "Herausgabedatum bis" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Tags ausschließen" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Serien ausschließen" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" -msgstr "Bücherregal ausschließen" +msgstr "Bücherregale ausschliessen" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Sprachen ausschließen" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" -msgstr "Erweiterungen" +msgstr "Datei Erweiterungen" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" -msgstr "Erweiterungen ausschließen" +msgstr "Datei Erweiterungen ausschliessen" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Bewertungen größer als" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Bewertungen kleiner als" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "Von:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Bis:" @@ -3203,10 +3314,6 @@ msgstr "Fortschritt" msgid "Run Time" msgstr "Laufzeit" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Startzeitpunkt" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "Aktionen" @@ -3280,15 +3387,15 @@ msgid "Enter Username" msgstr "Benutzernamen eingeben" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "E-Mail-Adresse eingeben" +msgid "Enter Email" +msgstr "E-Mailadresse eingeben" #: cps/templates/user_table.html:136 -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "E-Reader E-Mail Adresse eingeben" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "E-Reader E-Mail" #: cps/templates/user_table.html:137 @@ -3348,10 +3455,6 @@ msgid "Sync selected Shelves with Kobo" msgstr "Ausgesuchte Bücherregale mit Kobo synchronisieren" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Zeige Gelesen/Ungelesen Auswahl" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Zeige zufällige Bücher" - diff --git a/cps/translations/el/LC_MESSAGES/messages.mo b/cps/translations/el/LC_MESSAGES/messages.mo index 6201db16..a4e5e3a8 100644 Binary files a/cps/translations/el/LC_MESSAGES/messages.mo and b/cps/translations/el/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/el/LC_MESSAGES/messages.po b/cps/translations/el/LC_MESSAGES/messages.po index 000bba64..4ebb35ba 100644 --- a/cps/translations/el/LC_MESSAGES/messages.po +++ b/cps/translations/el/LC_MESSAGES/messages.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Depountis Georgios\n" "Language: el\n" @@ -15,498 +15,508 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Στατιστικά" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Ο διακομιστής επανεκκίνησε, παρακαλούμε φόρτωσε ξανά τη σελίδα" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Πραγματοποιείται κλείσιμο του διακομιστή, παρακαλούμε κλείσε το παράθυρο" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Επιτυχής επανασύνδεση" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Άγνωστη εντολή" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Το βιβλίο έχει επιτυχώς μπει σε σειρά για αποστολή στο %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Το βιβλίο έχει επιτυχώς μπει σε σειρά για αποστολή στο %(eReadermail)s" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "ʼΑγνωστο" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Σελίδα διαχειριστή" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Βασική Διαμόρφωση" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "UI Διαμόρφωση" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Χρήστης Διαχειριστής" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Όλα" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Δεν βρέθηκε χρήστης" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Προβολή Όλων" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Δεν έχει απομείνει χρήστης διαχειριστής, δεν μπορεί να αφαιρεθεί ο ρόλος διαχειριστή" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Ενημερώθηκε η διαμόρφωση Calibre-Web" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Θέλεις πραγματικά να διαγράψεις τη Μονάδα Kobo;" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Είσαι σίγουρος/η πως θέλεις να διαγράψεις αυτό το ράφι;" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Είσαι σίγουρος/η πως θέλεις να διαγράψεις αυτό το ράφι;" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Είσαι σίγουρος/η πως θέλεις να διαγράψεις αυτό το ράφι;" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Είσαι σίγουρος/η πως θέλεις να διαγράψεις αυτό το ράφι;" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Είσαι σίγουρος/η πως θέλεις να κάνεις κλείσιμο;" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Απόρριψη" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Επιτρέπεται" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json Δεν Έχει Διαμορφωθεί Για Διαδικτυακή Εφαρμογή" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Το Φύλλο Καταγραφής Τοποθεσίας δεν είναι Έγκυρο, Παρακαλούμε Συμπλήρωσε Τη Σωστή Πορεία" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Η Πρόσβαση Φύλλου Καταγραφης Τοποθεσίας δεν είναι έγκυρη, Παρακαλούμε Συμπλήρωσε Τη Σωστή Πορεία" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Παρακαλούμε Συμπλήρωσε ένα Πάροχο LDAP, Θύρα, DN και Αντικείμενο Αναγνώρισης Χρήστη" -#: cps/admin.py:1179 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Παρακαλούμε συμπλήρωσε ένα έγκυρο όνομα χρήστη για επαναφορά του κωδικού" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "Το Αντικείμενο Φίλτρου Ομάδας LDAP Πρέπει να Έχει Μια \"%s\" Αναγνώριση Μορφής" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Το Αντικείμενο Φίλτρου Ομάδας LDAP Έχει Παρενθέσεις Που Δεν Ταιριάζουν" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "Το Αντικείμενο Φίλτρου Χρήστη LDAP πρέπει να Έχει Μια \"%s\" Αναγνώριση Μορφής" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Το Αντικείμενο Φίλτρου Χρήστη LDAP Έχει Παρενθέσεις Που Δεν Ταιριάζουν" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Προσθήκη νέου χρήστη" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Προσθήκη Νέου Χρήστη" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Επεξεργασία Ρυθμίσεων E-mail Διακομιστή" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Σφάλμα βάσης δεδομένων: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Παρουσιάστηκε σφάλμα κατά την αποστολή του δοκιμαστικού e-mail:% (res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Παρακαλούμε ρύθμισε πρώτα τη διεύθυνση e-mail σου..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Ενημερώθηκαν οι ρυθμίσεις E-mail διακομιστή" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Προέκυψε ένα άγνωστο σφάλμα. Παρακαλούμε δοκίμασε ξανά αργότερα." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Επεξεργασία χρήστη %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Κωδικός για επαναφορά %(user) χρήστη/ών" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Παρακαλούμε διαμόρφωσε πρώτα τις ρυθμίσεις ταχυδρομείου SMTP..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Προβολέας αρχείου φύλλου καταγραφής" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Αίτημα πακέτου ενημέρωσης" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Κατεβάζει πακέτο ενημέρωσης" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Ανοίγει πακέτο ενημέρωσης" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Αντικατάσταση αρχείων" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Οι συνδέσεις βάσης δεδομένων είναι κλειστές" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Σταματάει το διακομιστή" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Η ενημέρωση τελειώσε, παρακαλούμε πιέστε το εντάξει και φορτώστε ξανά τη σελίδα" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Η ενημέρωση απέτυχε:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP Σφάλμα" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Σφάλμα σύνδεσης" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Τελείωσε ο χρόνος κατά την προσπάθεια δημιουργίας σύνδεσης" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Γενικό σφάλμα" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Το Αρχείο Ενημέρωσης Δεν Μπόρεσε Να Αποθηκευτεί σε" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Αποτυχία Δημιουργίας Τουλάχιστον Ενός Χρήστη LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Αποτυχία Δημιουργίας Τουλάχιστον Ενός Χρήστη LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Σφάλμα: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Σφάλμα: Δεν επιστράφηκε χρήστης σε απάντηση του διακομιστή LDAP" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Τουλάχιστον Ένας Χρήστης LDAP Δεν Βρέθηκε Στη Βάση Δεδομένων" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "Η Τοποθεσία DB δεν είναι Έγκυρη, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "Η DB δεν μπορεί να Γραφτεί" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "Το Αρχειο Κλειδί Τοποθεσίας δεν είναι Έγκυρο, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "Η Τοποθεσία Certfile δεν είναι Έγκυρη, Παρακαλούμε Συμπληρώστε Τη Σωστή Πορεία" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Ενημερώθηκαν οι ρυθμίσεις E-mail διακομιστή" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Διαμόρφωση Λειτουργίας" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Παρακαλούμε συμπλήρωσε όλα τα πεδία!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "Το E-mail δεν είναι από έγκυρο domain" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Προσθήκη νέου χρήστη" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Χρήστης/ες '%(user)s' δημιουργήθηκαν" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Βρέθηκε ένας ήδη υπάρχον λογαριασμός για αυτή τη διεύθυνση e-mail ή όνομα χρήστη." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Χρήστης/ες '%(nick)s' διαγράφηκαν" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Δεν έχει απομείνει χρήστης διαχειριστής, δεν μπορεί να διαγραφεί ο χρήστης" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Χρήστης/ες '%(nick)s' ενημερώθηκαν" @@ -519,122 +529,122 @@ msgstr "δεν εγκαταστάθηκε" msgid "Execution permissions missing" msgstr "Λείπουν άδειες εκτέλεσης" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Η ειδικά προσαρμοσμένη στήλη No.%(column)d δεν υπάρχει στο επίπεδο βάσης δεδομένων" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Κανένα" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Oυπς! Ο επιλεγμένος τίτλος βιβλίου δεν είναι διαθέσιμος. Το αρχείο δεν υπάρχει ή δεν είναι προσβάσιμο" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Τα αναγνωριστικά δεν έχουν Διάκριση Πεζών-Κεφαλαίων Γραμμάτων, Αντικατάσταση Παλιού Αναγνωριστικού" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Τα μεταδεδομένα ενημερώθηκαν επιτυχώς" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Το αρχείο %(file)s ανέβηκε" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Η δομή πηγής ή προορισμού για μετατροπή λείπει" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Το βιβλίο είναι σε σειρά επιτυχώς για μετατροπή σε %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Υπήρξε ένα σφάλμα στη μετατροπή αυτού του βιβλίου: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Το βιβλίο που ανέβηκε πιθανόν να υπάρχει στη βιβλιοθήκη, σκέψου να το αλλάξεις πριν ανεβάσεις νέο: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s δεν είναι μια έγκυρη γλώσσα" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Η επέκταση αρχείου '%(ext)s' δεν επιτρέπεται να ανέβει σε αυτό το διακομιστή" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Το αρχείο προς ανέβασμα πρέπει να έχει μια επέκταση" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Το αρχείο %(filename)s δεν μπόρεσε να αποθηκευτεί σε temp dir" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Αποτυχία Μετακίνησης Αρχείου Φόντου %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Η μορφή βιβλίου Διαγράφηκε Επιτυχώς" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Το Βιβλίο Διαγράφηκε Επιτυχώς" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "επεξεργασία μεταδεδομένων" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Αποτυχεία δημιουργίας πορείας %(path)s (Η άδεια απορρήφθηκε)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Αποτυχία αποθήκευσης αρχείου %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Μορφή αρχείου %(ext)s προστέθηκε σε %(book)s" @@ -647,183 +657,188 @@ msgstr "Η ρύθμιση του Google Drive δεν ολοκληρώθηκε, msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Η ανάκληση ονόματος δεν έχει επαληθευτεί, παρακαλούμε ακολούθησε τα βήματα για την επαλήθευση ονόματος στην κονσόλα προγραμματιστή google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s η δομή δεν βρέθηκε για την ταυτότητα βιβλίου: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s δεν βρέθηκε στο Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s δεν βρέθηκε: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Αποστολή στο Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Αυτό το e-mail έχει σταλεί μέσω Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web δοκιμαστικό e-mail" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Δοκιμαστικό e-mail" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Ξεκινήστε με το Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "e-mail εγγραφής για χρήστη: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Μετατροπή %(orig)s σε %(format)s και αποστολή στο Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Αποστολή %(format)s στο Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Αποστολή στο Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Το αρχείου που χητήθηκε δεν μπορεί να διαβαστεί. Μπορεί να υπάρχουν λαθασμένες άδειες;" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Η διαγραφή φακέλου βιβλίου για το βιβλίο %(id)s απέτυχε, η πορεία έχει υπό-φακέλους: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Η διαγραφή βιβλίου %(id)s απέτυχε: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, fuzzy, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Διαγραφή βιβλίου %(id)s, η πορεία βιβλίου δεν είναι έγκυρη: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Η μετονομασία τίτλου από: '%(src)s' σε '%(dest)s' απέτυχε με σφάλμα: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Το αρχείο %(file)s δεν βρέθηκε στο Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Η μετονομασία τίτλου από: '%(src)s' σε '%(dest)s' απέτυχε με σφάλμα: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Η πορεία βιβλίου %(path)s δεν βρέθηκε στο Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Βρέθηκε ένας ήδη υπάρχον λογαριασμός για αυτή τη διεύθυνση e-mail." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Αυτό το όνομα χρήστη έχει ήδη παρθεί" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Σφάλμα Κατεβάσματος Φόντου" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Σφάλμα Μορφής Φόντου" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Αποτυχία δημιουργίας πορείας για φόντο" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Το αρχείο φόντου δεν είναι ένα έγκυρο αρχείο εικόνας, ή δεν μπόρεσε να αποθηκευτεί" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Μόνο jpg/jpeg αρχεία υποστηρίζονται ως αρχεία φόντου" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Δεν βρέθηκε δυαδικό αρχείο Unrar" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Σφάλμα εκτέλεσης UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Ανακάλυψε" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Παρακαλούμε λάβε πρόσβαση στο calibre-web από ένα μη τοπικό εξηπηρετητή για να λάβεις μια έγκυρη api_endpoint για συσκευή kobo" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Καθορισμός Kobo" @@ -832,9 +847,9 @@ msgstr "Καθορισμός Kobo" msgid "Register with %(provider)s" msgstr "Εγγραφή με %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "τώρα έχεις συνδεθεί ως: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -893,12 +908,13 @@ msgstr "Google Oauth σφάλμα, παρακαλούμε δοκίμασε ξα msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Σύνδεση" @@ -914,149 +930,158 @@ msgstr "Η μάρκα έχει λήξει" msgid "Success! Please return to your device" msgstr "Επιτυχία! Παρακαλούμε επέστρεψε στη συσκευή σου" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Βιβλία" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Προβολή πρόσφατων βιβλίων" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Βιβλία στη Μόδα" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Προβολή Βιβλίων στη Μόδα" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Κατεβασμένα Βιβλία" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Προβολή Κατεβασμένων Βιβλίων" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Βιβλία με Κορυφαία Αξιολόγηση" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Προβολή Βιβλίων με Κορυφαία Αξιολόγηση" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Βιβλία που Διαβάστηκαν" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Προβολή διαβασμένων και αδιάβαστων" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Βιβλία που δεν Διαβάστηκαν" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Προβολή αδιάβαστων" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Ανακάλυψε" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Προβολή Τυχαίων Βιβλίων" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Κατηγορίες" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Προβολή επιλογών κατηγορίας" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Σειρές" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Προβολή επιλογών σειράς" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Συγγραφείς" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Προβολή επιλογών συγγραφέα" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Εκδότες" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Προβολή επιλογών εκδότη" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Γλώσσες" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Προβολή επιλογών γλώσσας" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Αξιολογήσεις" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Προβολή επιλογών αξιολόγησης" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Μορφές αρχείου" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Προβολή επιλογών μορφής αρχείου" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Αρχειοθετημένα Βιβλία" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Προβολή αρχειοθετημένων βιβλίων" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Λίστα Βιβλίων" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Προβολή Λίστας Βιβλίων" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Αναζήτηση" @@ -1080,14 +1105,14 @@ msgstr "Αξιολόγηση >= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Προχωρημένη Αναζήτηση" @@ -1138,7 +1163,7 @@ msgstr "Το βιβλίο έχει αφαιρεθεί από το ράφι: %(sn msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Δημιούργησε ένα Ράφι" @@ -1165,73 +1190,73 @@ msgstr "Το Βιβλίο Διαγράφηκε Επιτυχώς" msgid "Change order of Shelf: '%(name)s'" msgstr "Αλλαγή σειράς του Ραφιού: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Το ράφι %(title)s δημιουργήθηκε" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Το ράφι %(title)s άλλαξε" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Υπήρξε ένα σφάλμα" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Ένα δημόσιο ράφι με το όνομα '%(title)s' υπάρχει ήδη." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Ένα ιδιωτικό ράφι με το όνομα '%(title)s' υπάρχει ήδη." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Ράφι: '%(name)s" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Σφάλμα κατά το άνοιγμα του ραφιού. Το ράφι δεν υπάρχει ή δεν είναι προσβάσιμο" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Εργασίες" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Αναμονή" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Απέτυχε" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Ξεκίνησε" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Τελείωσε" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "ʼΑγνωστη κατάσταση" @@ -1264,146 +1289,186 @@ msgstr "Μια νέα ενημέρωση είναι διαθέσιμη. Κάνε msgid "No release information available" msgstr "Δεν υπάρχουν διαθέσιμες πληροφορίες αποδέσμευσης" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Ανακάλυψε (Τυχαία Βιβλία)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Βιβλία στη Μόδα (Με τα περισσότερα κατεβάσματα)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Κατεβασμένα βιβλία από %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Συγγραφέας: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Εκδότης: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Σειρές: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Αξιολόγηση: %(rating)s stars" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Μορφή αρχείου: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Κατηγορία: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Γλώσσα: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Κατεβασμένα" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Λίστα αξιολογήσεων" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Λίστα μορφών αρχείου" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Το βιβλίο έχει επιτυχώς μπει σε σειρά για αποστολή στο %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Παρακαλούμε διαμόρφωσε πρώτα τις ρυθμίσεις ταχυδρομείου SMTP..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Το βιβλίο έχει επιτυχώς μπει σε σειρά για αποστολή στο %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Oυπς! Υπήρξε ένα σφάλμα κατά την αποστολή αυτού του βιβλίου: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Παρακαλούμε ενημέρωσε το προφίλ σου με μια έγκυρη Διεύθυνση E-mail Αποστολής στο Kindle." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "Ο διακομιστής E-Mail δεν έχει διαμορφωθεί, παρακαλούμε επικοινώνησε με το διαχειριστή σου!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Εγγραφή" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Ο διακομιστής E-Mail δεν έχει διαμορφωθεί, παρακαλούμε επικοινώνησε με το διαχειριστή σου!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Η διεύθυνση e-mail σου δεν επιτρέπεται να εγγραφεί" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Το e-mail επιβεβαίωσης έχει σταλεί στον e-mail λογαριασμό σου." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Δεν μπόρεσε να ενεργοποιηθεί η επαλήθευση LDAP" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "τώρα έχεις συνδεθεί ως: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Εναλλακτική Σύνδεση ως: '%(nickname)s', Ο Διακομιστής LDAP δεν είναι προσβάσιμος, ή ο χρήστης δεν είναι γνωστός" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Δεν μπόρεσε να συνδεθεί: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Λανθασμένο Όνομα Χρήστη ή Κωδικός" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Ο Νέος Κωδικός έχει σταλεί στη διεύθυνση email σου" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Προέκυψε ένα άγνωστο σφάλμα. Παρακαλούμε δοκίμασε ξανά αργότερα." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Παρακαλούμε συμπλήρωσε ένα έγκυρο όνομα χρήστη για επαναφορά του κωδικού" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Έχεις συνδεθεί ως: '%(nickname)s'" +msgstr "τώρα έχεις συνδεθεί ως: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s's προφίλ" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Το προφίλ ενημερώθηκε" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Βρέθηκε ένας ήδη υπάρχον λογαριασμός για αυτή τη διεύθυνση e-mail." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Αποστολή στο Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1446,35 +1511,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "επεξεργασία μεταδεδομένων" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Ανέβασμα" @@ -1490,15 +1555,15 @@ msgstr "Όνομα Χρήστη" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Διεύθυνση E-mail" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Διεύθυνση E-mail Αποστολής στο Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Διαχειριστής" @@ -1508,8 +1573,8 @@ msgstr "Διαχειριστής" msgid "Password" msgstr "Κωδικός" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Κατέβασμα" @@ -1534,16 +1599,12 @@ msgstr "Διαγραφή" msgid "Public Shelf" msgstr "Δημόσιο Ράφι" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Προσθήκη Νέου Χρήστη" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Εισαγωγή Χρηστών LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Ρυθμίσεις E-mail Διακομιστή" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1564,11 +1625,11 @@ msgstr "Σύνδεση SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Από E-mail" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1641,102 +1702,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Διοίκηση" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Προβολή Φύλλων Καταγραφής" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Επανασύνδεση Βάσης Δεδομένων Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Επανεκκίνηση" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Κλείσιμο" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Έκδοση" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Λεπτομέρειες" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Τρέχουσα έκδοση" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Έλεγχος για Ενημέρωση" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Πραγματοποίηση Ενημέρωσης" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Είσαι σίγουρος/η πως θέλεις να κάνεις επανεκκίνηση" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Ακύρωση" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Είσαι σίγουρος/η πως θέλεις να κάνεις κλείσιμο;" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Γίνεται ενημέρωση, παρακαλούμε μη φορτώσεις ξανά αυτή τη σελίδα" @@ -1826,7 +1889,7 @@ msgid "Author" msgstr "Συγγραφέας" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Περιγραφή" @@ -1851,7 +1914,7 @@ msgstr "Αφαίρεση" msgid "Add Identifier" msgstr "Προσθήκη Αναγνωριστικού" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Ετικέτες" @@ -1876,23 +1939,23 @@ msgid "Published Date" msgstr "Ημερομηνία Έκδοσης" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Εκδότης" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Γλώσσα" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Ναι" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Όχι" @@ -1909,8 +1972,8 @@ msgid "Fetch Metadata" msgstr "Συγκέντρωση Μεταδεδομένων" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1933,8 +1996,8 @@ msgstr "Κάνε κλικ στο εξώφυλλο για φόρτωση μετα msgid "Loading..." msgstr "Φόρτωση..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Κλείσιμο" @@ -2162,7 +2225,7 @@ msgid "Enable Uploads" msgstr "Ενεργοποίηση Ανεβάσματος" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2178,7 +2241,7 @@ msgid "Enable Public Registration" msgstr "Ενεργοποίηση Δημόσιας Εγγραφής" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Χρήση E-Mail ως Όνομα Χρήστη" #: cps/templates/config_edit.html:132 @@ -2368,6 +2431,52 @@ msgstr "Πορεία για Μετατροπέα Kepubify E-Book" msgid "Location of Unrar binary" msgstr "Τοποθεσία δυαδικού Unrar" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth Ρυθμίσεις" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Επαναφορά Κωδικού χρήστη" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Προβολή Διαμόρφωσης" @@ -2380,7 +2489,7 @@ msgstr "Αριθμός Τυχαίων Βιβλίων για Εμφάνιση" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Αριθμός Συγγραφέων για Εμφάνιση Πριν την Απόκρυψη (0=Απενεργοποίηση Απόκρυψης)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Θέμα" @@ -2471,79 +2580,82 @@ msgstr "Προσθήκη ετικετών Επιτρέπεται/Απορρίπ msgid "Add Allowed/Denied custom column values" msgstr "Προσθήκη τιμών ειδικά κατασκευασμένων στηλών Επιτρέπεται/Απορρίπτεται" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Διάβασε στο Πρόγραμμα Περιήγησης" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "ʼΑκουσε στο Πρόγραμμα Περιήγησης" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, fuzzy, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Εκδόθηκε" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Σήμανση ως Αδιάβαστο" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Σήμανση ως Διαβασμένο" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Διαβάστηκε" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Επαναφορά από το αρχείο" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Προσθήκη στο αρχείο" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Αρχειοθετήθηκε" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Περιγραφή" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Προσθήκη στο ράφι" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Δημόσιο)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Επεξεργασία Μεταδεδομένων" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "" +#, fuzzy +msgid "Gmail Account" +msgstr "Λογαριασμός" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2567,10 +2679,11 @@ msgid "Attachment Size Limit" msgstr "Όριο Μεγέθους Επισύναψης" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Αποθήκευση και Αποστολή E-mail Δοκιμής" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Πίσω" @@ -2596,13 +2709,13 @@ msgstr "Όνομα domain" msgid "Denied Domains (Blacklist)" msgstr "Domains που Απορρίφθηκαν (Μαύρη λίστα)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Επόμενο" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "ʼΑνοιξε το .kobo/Kobo eReader.conf αρχείο σε πρόγραμμα επεξεργασίας κειμένου και πρόσθεσε (ή κάνε επεξεργασία):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "ʼΑνοιξε το .kobo/Kobo/Kobo eReader.conf αρχείο σε πρόγραμμα επεξεργασίας κειμένου και πρόσθεσε (ή κάνε επεξεργασία):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2613,20 +2726,20 @@ msgstr "Kobo Μονάδα Συγχρονισμού" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Ο διακομιστής E-Mail δεν έχει διαμορφωθεί, παρακαλούμε επικοινώνησε με το διαχειριστή σου!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Δημιουργία Θέματος" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Επιστροφή στην Κεντρική" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2656,80 +2769,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Έναρξη" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Δημοφιλείς εκδόσεις από αυτό τον κατάλογο με βάση τις Λήψεις." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Δημοφιλείς εκδόσεις από αυτό τον κατάλογο με βάση την Αξιολόγηση." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Βιβλία που προστέθηκαν Πρόσφατα" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Τα τελευταία Βιβλία" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Τυχαία Βιβλία" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Τα βιβλία ταξινομήθηκαν ανά Συγγραφέα" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Τα βιβλία ταξινομήθηκαν ανά εκδότη" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Τα βιβλία ταξινομήθηκαν ανά κατηγορία" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Τα βιβλία ταξινομήθηκαν ανά σειρές" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Τα βιβλία ταξινομήθηκαν ανά Γλώσσες" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Τα βιβλία ταξινομήθηκαν ανά Αξιολόγηση" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Τα βιβλία ταξινομήθηκαν ανά μορφές αρχείου" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Ράφια" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Βιβλία οργανωμένα σε ράφια" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Κεντρική" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Αλλαγή Θέσης Περιήγησης" @@ -2737,48 +2850,48 @@ msgstr "Αλλαγή Θέσης Περιήγησης" msgid "Search Library" msgstr "Αναζήτηση Βιβλιοθήκης" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Φόρτωση..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Σφάλμα" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Το ανέβασμα έγινε, γίνεται επεξεργασία, παρακαλούμε περίμενε..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Ρυθμίσεις" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Λογαριασμός" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Αποσύνδεση" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Φόρτωση..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Σφάλμα" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Το ανέβασμα έγινε, γίνεται επεξεργασία, παρακαλούμε περίμενε..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Ρυθμίσεις" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Παρακαλούμε μην ανανεώσεις τη σελίδα" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Περιήγηση" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Σχετικά" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Προηγούμενο" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Λεπτομέρειες Βιβλίου" @@ -2794,7 +2907,7 @@ msgstr "Να με Θυμάσαι" msgid "Forgot Password?" msgstr "Ξέχασες τον Κωδικό;" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Σύνδεση με το Μαγικό Σύνδεσμο" @@ -2904,137 +3017,162 @@ msgstr "Calibre-Web Κατάλογος eBook" msgid "epub Reader" msgstr "PDF πρόγραμμα ανάγνωσης" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Φωτεινό" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Σκοτεινό" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Πίσω" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Επανάληψη ροής κειμένου όταν οι μπάρες στο πλάι είναι ανοιχτές." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "PDF πρόγραμμα ανάγνωσης" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Συντομεύσεις Πληκτρολογίου" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Προηγούμενη Σελίδα" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Επόμενη Σελίδα" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Κλιμάκωση στο Καλυτερο" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Κλιμάκωση σε Πλάτος" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Κλιμάκωση σε Ύψος" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Κλιμάκωση σε Τοπικό" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Περιστροφή Δεξιά" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Περιστροφή Αριστερά" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Γύρισμα Σελίδας" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Σελίδα διαχειριστή" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Κλίμακα" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Καλύτερο" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Πλάτος" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Ύψος" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Ντόπιο" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Περιστροφή" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Γύρισμα" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Οριζόντιο" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Κάθετο" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Κατεύθυνση" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Αριστερά προς Δεξιά" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Δεξιά προς Αριστερά" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3043,7 +3181,7 @@ msgstr "" msgid "DJVU Reader" msgstr "PDF πρόγραμμα ανάγνωσης" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "PDF πρόγραμμα ανάγνωσης" @@ -3062,7 +3200,7 @@ msgid "Choose a username" msgstr "Επιλογή ενός ονόματος χρήστη" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Η διεύθυνση email σου" #: cps/templates/remote_login.html:5 @@ -3081,10 +3219,6 @@ msgstr "Με την επαλήθευση, θα συνδεθείτε αυτόμα msgid "This verification link will expire in 10 minutes." msgstr "Αυτός ο σύνδεσμος επαλήθευσης θα λήξει σε 10 λεπτά." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3109,44 +3243,52 @@ msgstr "Ημερομηνία Έκδοσης Από" msgid "Published Date To" msgstr "Ημερομηνία Έκδοσης Μέχρι" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Εξαίρεση Ετικετών" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Εξαίρεση Σειρών" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Εξαίρεση Σειρών" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Εξαίρεση Γλωσσών" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Επεκτάσεις" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Εξαίρεση Επεκτάσεων" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Βαθμολογία Πάνω από" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Βαθμολογία Κάτω από" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3238,10 +3380,6 @@ msgstr "Πρόοδος" msgid "Run Time" msgstr "Χρόνος Λειτουργίας" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Ώρα Έναρξης" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3318,17 +3456,17 @@ msgstr "Επιλογή ενός ονόματος χρήστη" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Η διεύθυνση email σου" +msgid "Enter Email" +msgstr "Δοκιμαστικό e-mail" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "Διεύθυνση E-mail Αποστολής στο Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Δοκιμαστικό e-mail" #: cps/templates/user_table.html:137 @@ -3398,10 +3536,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Προβολή επιλογών σειράς" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Προβολή τυχαίων βιβλίων" - diff --git a/cps/translations/es/LC_MESSAGES/messages.mo b/cps/translations/es/LC_MESSAGES/messages.mo index f2089c96..1c68874b 100644 Binary files a/cps/translations/es/LC_MESSAGES/messages.mo and b/cps/translations/es/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/es/LC_MESSAGES/messages.po b/cps/translations/es/LC_MESSAGES/messages.po index e47e348e..f1015f3f 100644 --- a/cps/translations/es/LC_MESSAGES/messages.po +++ b/cps/translations/es/LC_MESSAGES/messages.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-05-25 17:22+0200\n" "Last-Translator: minakmostoles \n" "Language: es\n" @@ -18,499 +18,509 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" # "Last-Translator: victorhck \n" #: cps/about.py:84 msgid "Statistics" msgstr "Estadísticas" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Servidor reiniciado. Por favor, recargue la página" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "El servidor se está apagando. Por favor, cierre la ventana" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Reconexión correcta" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Comando desconocido" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Libro puesto en la cola de envío a %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Puesto en cola un correo electrónico de prueba enviado a %(email)s, por favor, comprueba el resultado en Tareas" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Desconocido" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Página de administración" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configuración básica" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configuración de la interfaz de usuario" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Editar usuarios" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Todo" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Usuario no encontrado" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} usuarios eliminados con éxito" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Mostrar todo" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Petición mal formulada" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "El nombre de invitado no se puede cambiar" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "El invitado no puede tener ese rol" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "No queda ningún usuario administrador, no se puede eliminar al usuario" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "Valor tiene que ser verdadero o falso" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Rol inválido" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "El invitado no puede tener esta vista" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Vista no válida" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "El sitio del invitado se determina automáticamente y no puede ser cambiado" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "No hay un sitio válido" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "No se ha indicado un idioma válido para el libro" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parámetro no encontrado" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Columna de lectura no válida" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Columna restringida no válida" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Configuración de Calibre-Web actualizada" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "¿Realmente quieres borrar el Token de Kobo?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "¿Realmente deseas borrar este dominio?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "¿Realmente quieres borrar este usuario?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "¿Realmente quieres eliminar este estante?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "¿Realmente quieres cambiar el idioma de los usuarios seleccionados?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "¿Realmente quieres cambiar los idiomas visibles del libro de los usuarios seleccionados?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "¿Realmente quieres cambiar el rol seleccionado de el usuario seleccionado?" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "¿Realmente quieres cambiar las restricciones de los usuarios seleccionados?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "¿Realmente quieres cambiar las restricciones de visibilidad de los usuarios seleccionados?" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "¿Realmente quieres cambiar el comportamiento de sincronización de estante del usuario seleccionado?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "¿Realmente quieres cambiar la ubicación de la biblioteca Calibre?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Denegar" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Permitir" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Etiqueta no encontrada" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Acción no válida" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json no está configurado para la aplicación web" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "La ruta del Logfile no es válida. Por favor, Introduce la ruta correcta" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "La ruta del Access Logfile no es válida. Por favor, Introduce la ruta correcta" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Por favor, Introduce un proveedor LDAP, puerto, DN y el User Object Identifier" -#: cps/admin.py:1179 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Por favor, introduce una cuenta de servicio LDAP y su contraseña" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Por favor, introduce una cuenta de servicio LDAP" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP Group Object Filter necesita tener un identificador de formato \"%s\"" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "El LDAP Group Object Filter tiene un paréntesis diferente" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP Group Object Filter necesita tener un identificador de formato \"%s\"" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "El LDAP Group Object Filter tiene un paréntesis diferente" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "El filtro de usuarios LDAP necesita tener un identificador de formato \"%s\"" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "El filtro de LDAP \"Member User\" tiene paréntesis no coincidentes" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "Ubicaciones del certificado de la CA del LDAP, del certificado o de la clave no válidos. Por favor introduce la ruta correcta" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Añadir un nuevo usuario" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Añadir nuevo usuario" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Cambiar parámetros de correo" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Verificación de cuenta de Gmail exitosa" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Error en la base de datos: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "Puesto en cola un correo electrónico de prueba enviado a %(email)s, por favor, comprueba el resultado en Tareas" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Ocurrió un error enviando el correo electrónico de prueba: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Por favor, configure su correo electrónico primero..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Actualizados los ajustes del servidor de correo electrónico" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Ha ocurrido un error desconocido. Por favor vuelva a intentarlo más tarde." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Editar Usuario %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Contraseña para el usuario %(user)s reinicializada" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Configura primero los parámetros del servidor SMTP..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visor del fichero de log" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Solicitando paquete de actualización" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Descargando paquete de actualización" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Descomprimiendo paquete de actualización" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Remplazando archivos" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Los conexiones con la base datos están cerradas" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Parando el servidor" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Actualización finalizada. Por favor, pulse OK y recargue la página" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Falló la actualización:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Error HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Error de conexión" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Tiempo agotado mientras se trataba de establecer la conexión" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Error general" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "La actualización del archivo no pudo guardarse en el directorio temporal (Temp Dir)" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Error al crear al menos un usuario LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Error al crear al menos un usuario LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Error: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Error: el servidor LDAP no ha devuelto ningún usuario" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Al menos, un usuario LDAP no se ha encontrado en la base de datos" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Usuario importado con éxito" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "La ruta de la base de datos no es válida. Por favor, Introduce la ruta correcta" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "La base de datos no es modificable" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "La ruta del Keyfile no es válida, por favor, Introduce la ruta correcta" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "La ruta de Certfile no es válida, por favor, Introduce la ruta correcta" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Actualizados los ajustes del servidor de correo electrónico" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Configuración de la base de datos" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "¡Por favor, rellena todos los campos!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "El correo electrónico no tiene un dominio válido" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Añadir un nuevo usuario" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Usuario '%(user)s' creado" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Encontrada una cuenta existente para este correo electrónico o nombre de usuario." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Usuario '%(nick)s' eliminado" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "No puedes borrar al Usuario Invitado" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "No queda ningún usuario administrador, no se puede borrar al usuario" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Usuario '%(nick)s' actualizado" @@ -523,122 +533,122 @@ msgstr "no instalado" msgid "Execution permissions missing" msgstr "Faltan permisos de ejecución" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Columna personalizada No.%(column)d no existe en la base de datos calibre" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Ninguno" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "oh, oh, el libro seleccionado no está disponible. El archivo no existe o no es accesible" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Los identificadores no distinguen entre mayúsculas y minúsculas, sobrescribiendo el identificador antiguo" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadatos actualizados con éxito" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "El fichero %(file)s ha sido subido" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Falta la fuente o el formato de destino para la conversión" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Libro puesto a la cola para su conversión a %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Ocurrió un error al convertir este libro: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "El libro cargado probablemente existe en la biblioteca, considera cambiarlo antes de subirlo de nuevo: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s no es un idioma válido" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "No se permite subir archivos con la extensión '%(ext)s' a este servidor" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "El archivo a subir debe tener una extensión" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "El archivo %(filename)s no pudo salvarse en el directorio temporal (Temp Dir)" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Fallo al mover el archivo de cubierta %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Formato de libro eliminado con éxito" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Libro eliminado con éxito" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "editar metadatos" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex) no es un número válido, saltando" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Fallo al crear la ruta %(path)s (permiso denegado)" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Fallo al guardar el archivo %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Archivo con formato %(ext)s añadido a %(book)s" @@ -651,183 +661,189 @@ msgstr "La configuración de Google Drive no se ha completado, intente desactiva msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "El dominio Callback no se ha verificado, siga los pasos para verificarlo en la consola de desarrollador de Google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s formato no encontrado para el id del libro: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s no encontrado en Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s no encontrado: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Enviar al Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Este correo electrónico ha sido enviado usando Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Correo de prueba de Calibre-Web" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Comprobar correo electrónico" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Primeros pasos con Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Correo electrónico de registro para el usuario: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Convertir %(orig)s a %(format)s y enviar al Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Enviado %(format)s al Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Enviar al Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "El archivo solicitado no puede ser leído. ¿Quizás existen problemas con los permisos?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Fallo al intentar borrar la carpeta del libro %(id)s, la ruta tiene subcarpetas: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "El eliminado del libro %(id)s falló: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, fuzzy, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Borrando el libro %(id)s, la ruta del libro es no válida: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "El renombrado del título de: '%(src)s' a '%(dest)s' falló con el error: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Fichero %(file)s no encontrado en Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "El renombrado del título de: '%(src)s' a '%(dest)s' falló con el error: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "La ruta %(path)s del libro no fue encontrada en Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Encontrada una cuenta existente para esa dirección de correo electrónico" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Este nombre de usuario ya está en uso" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Dirección de correo no válida" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Error al descargar la cubierta" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Error en el formato de la cubierta" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Error al crear una ruta para la cubierta" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "El archivo de cubierta no es una imágen válida" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Sólo se admiten como portada los archivos jpg/jpeg/png/webp/bmp" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Sólo se admiten como portada los archivos jpg/jpeg" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "No se encuentra el archivo binario UnRar" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Error ejecutando UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Descubrir" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Por favor, accede a calibre-web desde una ubicación que no sea localhost para obtener una api_endpoint válida para tu dispositivo Kobo" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configuración de Kobo" @@ -836,9 +852,9 @@ msgstr "Configuración de Kobo" msgid "Register with %(provider)s" msgstr "Registrado con %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "has iniciado sesión como : '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -897,12 +913,13 @@ msgstr "Error en Google Oauth, por favor vuelva a intentarlo más tarde." msgid "Google Oauth error: {}" msgstr "Error Google Oauth {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Estrellas" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Inicio de sesión" @@ -918,149 +935,158 @@ msgstr "El token ha expirado" msgid "Success! Please return to your device" msgstr "¡Correcto! Por favor regrese a su dispositivo" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Libros" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Mostrar libros recientes" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Libros populares" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Mostrar libros populares" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Libros Descargados" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Mostrar Libros Descargados" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Libros mejor valorados" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Mostrar libros mejor valorados" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Libros leídos" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Mostrar leídos y no leídos" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Libros no leídos" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Mostrar no leído" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Descubrir" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Mostrar libros al azar" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Categorías" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Mostrar selección de categorías" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Series" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Mostrar selección de series" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Autores" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Mostrar selección de autores" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Editores" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Mostrar selección de editores" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Idiomas" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Mostrar selección de idiomas" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Calificaciones" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Mostrar selección de calificaciones" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Formatos de archivo" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Mostrar selección de formatos de archivo" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Libros archivados" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Mostrar libros archivados" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Lista de Libros" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Mostrar Lista de Libros" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Buscar" @@ -1083,15 +1109,15 @@ msgid "Rating >= %(rating)s" msgstr "Calificación >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Estado de lectura = $(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Error en la búsqueda de columnas personalizadas, por favor reinicia Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Búsqueda avanzada" @@ -1142,7 +1168,7 @@ msgstr "El libro fue eliminado del estante: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Crear un estante" @@ -1169,73 +1195,73 @@ msgstr "Libro eliminado con éxito" msgid "Change order of Shelf: '%(name)s'" msgstr "Cambiar orden del estante: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Estante %(title)s creado" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Estante %(title)s cambiado" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Ha sucedido un error" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Ya existe un estante público con el nombre '%(title)s'." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Ya existe un estante privado con el nombre '%(title)s'." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Estante: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Error al abrir un estante. El estante no existe o no es accesible" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Tareas" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Esperando" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Fallido" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Comenzado" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Finalizado" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Estado desconocido" @@ -1268,146 +1294,186 @@ msgstr "Hay una nueva actualización disponible. Haz clic en el botón de abajo msgid "No release information available" msgstr "No hay información del lanzamiento disponible" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Descubrir (Libros al azar)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Libros populares (los más descargados)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Libros descargados por %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autor/es: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Editor/es: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Series: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Calificación: %(rating)s estrellas" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Formato del archivo: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categoría : %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Idioma: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Descargas" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Lista de calificaciones" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Lista de formatos" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Libro puesto en la cola de envío a %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Configura primero los parámetros del servidor SMTP..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Libro puesto en la cola de envío a %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Ha sucedido un error en el envío del libro: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Por favor actualiza tu perfil con la dirección de correo de su kindle..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "El servidor de correo no está configurado, por favor, ¡avisa a tu administrador!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Registro" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "El servidor de correo no está configurado, por favor, ¡avisa a tu administrador!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Su correo electrónico no está permitido para registrarse" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Se ha enviado un correo electrónico de verificación a su cuenta de correo." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "No se puede activar la autenticación LDAP" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "has iniciado sesión como : '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Fallback login como: '%(nickname)s', no se puede acceder al servidor LDAP o usuario desconocido" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "No se pudo entrar: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Usuario o contraseña inválido" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Una nueva contraseña se ha enviado a su cuenta de correo electrónico" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Ha ocurrido un error desconocido. Por favor vuelva a intentarlo más tarde." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Por favor, introduce un usuario válido para restablecer la contraseña" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Ahora estás conectado como: '%(nickname)s'" +msgstr "has iniciado sesión como : '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Perfil de %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Perfil actualizado" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Encontrada una cuenta existente para esa dirección de correo electrónico" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "No se ha encontrado ningún archivo gmail.json válido con información OAuth" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Enviar al Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1450,35 +1516,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "editar metadatos" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Subir archivo" @@ -1494,15 +1560,15 @@ msgstr "Nombre de usuario" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Correo electrónico" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Enviar al correo de Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Admin" @@ -1512,8 +1578,8 @@ msgstr "Admin" msgid "Password" msgstr "Contraseña" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Descargar" @@ -1538,16 +1604,12 @@ msgstr "Borrar" msgid "Public Shelf" msgstr "Estantería pública" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Añadir nuevo usuario" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importar usuarios LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Ajustes del servidor de correo electrónico" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1568,11 +1630,12 @@ msgstr "Login SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Desde el correo" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "Servicio de Correo" #: cps/templates/admin.html:91 @@ -1645,102 +1708,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Administración" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Descargar paquete de debug" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Ver archivos de registro" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Reconectar a la BD Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Reiniciar" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Apagar" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versión" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detalles" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Versión actual" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Comprobar actualizaciones" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Realizar actualización" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "¿Realmente quieres reiniciar?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Ok" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Cancelar" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "¿Realmente quiere detener?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Actualizando. Por favor, no recargue la página" @@ -1830,7 +1895,7 @@ msgid "Author" msgstr "Autor" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Descripción" @@ -1855,7 +1920,7 @@ msgstr "Borrar" msgid "Add Identifier" msgstr "Añadir identificador" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Etiquetas" @@ -1880,23 +1945,23 @@ msgid "Published Date" msgstr "Fecha de publicación" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Editor" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Idioma" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Sí" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "No" @@ -1913,8 +1978,8 @@ msgid "Fetch Metadata" msgstr "Obtener metadatos" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1937,8 +2002,8 @@ msgstr "Haz clic en la portada para cargar los metadatos en el formulario" msgid "Loading..." msgstr "Cargando..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Cerrar" @@ -2166,7 +2231,7 @@ msgid "Enable Uploads" msgstr "Permitir subidas" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2182,7 +2247,7 @@ msgid "Enable Public Registration" msgstr "Permitir registro público" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Utilizar eMail como nombre de usuario" #: cps/templates/config_edit.html:132 @@ -2372,6 +2437,52 @@ msgstr "Ruta para Kepubify E-Book Converter" msgid "Location of Unrar binary" msgstr "Ubicación del binario de Unrar" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Ajustes OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Resetear contraseña de usuario" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Ver configuración" @@ -2384,7 +2495,7 @@ msgstr "Número de libros aleatorios a mostrar" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Número de autores para mostrar antes de ocultar (0 = desactivar la ocultación)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Tema" @@ -2475,80 +2586,84 @@ msgstr "Añadir etiquetas Permitidas/Denegados" msgid "Add Allowed/Denied custom column values" msgstr "Añadir valores personalizados Permitidos/Denegados" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Leer en el navegador" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Escuchar en el navegador" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, fuzzy, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publicado" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Marcar como no leido" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Marcar como leido" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Leído" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Restarurar desde el archivo" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Añadir a archivación" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archivado" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Descripción:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Agregar al estante" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Público)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Editar metadatos" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Elige tipo de servidor" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Usar cuenta de correo estándar" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Verificación de cuenta Gmal con OAuth2" +#, fuzzy +msgid "Gmail Account" +msgstr "Elige tipo de servidor" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Configurar cuenta de Gmail como servidor de correo" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2571,10 +2686,11 @@ msgid "Attachment Size Limit" msgstr "Tamaño límite del archivo adjunto" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Guardar y enviar un correo electrónico de prueba" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Regresar" @@ -2600,13 +2716,13 @@ msgstr "Introducir nombre de dominio" msgid "Denied Domains (Blacklist)" msgstr "Dominios prohibidos (Blaclist)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Siguiente" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Abre el archivo .kobo/Kobo eReader.conf en un editor de texto y añade (o edita):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Abre el archivo .kobo/Kobo/Kobo eReader.conf en un editor de texto y añade (o edita):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2617,20 +2733,20 @@ msgstr "Token de sincronización de Kobo" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "El servidor de E-Mail no está configurado, por favor contacta a tu administrador" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Crear una incidencia" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Volver al inicio" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "Cerrar sesión" @@ -2660,80 +2776,80 @@ msgstr "Ordenar ascendientemente en base al índice de serie" msgid "Sort descending according to series index" msgstr "Ordenar descendientemente en base al índice de serie" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Iniciar" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Libros Alfabéticos" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Libros ordenados alfabéticamente" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Publicaciones populares de este catálogo basadas en las Descargas." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Publicaciones populares del catálogo basados en la clasificación." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Libros añadidos recientemente" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Últimos ibros" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Libros al azar" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Libros ordenados por autor" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Libros ordenados por editor" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Libros ordenados por categorías" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Libros ordenados por series" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Libros ordenados por idioma" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Libros ordenados por puntuación" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Libros ordenados por formato de archivo" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Estanterías" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Libros organizados en estanterías" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Inicio" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Alternar navegación" @@ -2741,48 +2857,48 @@ msgstr "Alternar navegación" msgid "Search Library" msgstr "Buscar en la librería" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Cargando..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Error" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Carga hecha, procesando, por favor espere ..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Ajustes" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Cuenta" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Cerrar sesión" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Cargando..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Error" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Carga hecha, procesando, por favor espere ..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Ajustes" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Por favor, no actualice la página" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Navegar" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Acerca de" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Previo" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Detalles del libro" @@ -2798,7 +2914,7 @@ msgstr "Recordarme" msgid "Forgot Password?" msgstr "¿Olvidó la contraseña?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Iniciar sesión con un enlace mágico" @@ -2908,137 +3024,162 @@ msgstr "Catálogo de ebooks de Calibre-Web" msgid "epub Reader" msgstr "Lector PDF" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Claro" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Oscuro" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Regresar" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Redimensionar el texto cuando las barras laterales están abiertas." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "Lector PDF" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Atajos de teclado" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Página previa" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Página siguiente" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Escalar a mejor" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Escalar a la ancho" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Escalar a lo alto" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Escalado nativo" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Rotar hacia la derecha" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Rotar hacia la izquierda" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Voltear imagen" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Página de administración" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Escalar" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Mejor" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Ancho" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Alto" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Nativo" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Rotar" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Voltear" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Horizontal" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Vertical" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Dirección" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "De izquierda a derecha" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "De derecha a izquierda" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Volver al principio" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Recordar posición" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Barra de desplazamiento" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Mostrar" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Ocultar" @@ -3047,7 +3188,7 @@ msgstr "Ocultar" msgid "DJVU Reader" msgstr "Lector PDF" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "Lector PDF" @@ -3066,7 +3207,7 @@ msgid "Choose a username" msgstr "Escoger un nombre de usuario" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Tu dirección de correo" #: cps/templates/remote_login.html:5 @@ -3085,10 +3226,6 @@ msgstr "Una vez que lo realice, iniciará sesión automáticamente en ese dispos msgid "This verification link will expire in 10 minutes." msgstr "El enlace expirará después de 10 minutos." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3113,44 +3250,52 @@ msgstr "Fecha de publicación desde" msgid "Published Date To" msgstr "Fecha de publicación hasta" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Excluir etiquetas" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Excluir series" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Excluir estantes" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Excluir idiomas" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Extensiones" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Extensiones excluidas" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Clasificación mayor que" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Clasificación menor que" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "De:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Para:" @@ -3242,10 +3387,6 @@ msgstr "Progreso" msgid "Run Time" msgstr "Tiempo de ejecución" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Fecha de inicio" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3322,17 +3463,17 @@ msgstr "Introduce el nombre de usuario" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Introduce la dirección de correo electrónico" +msgid "Enter Email" +msgstr "Comprobar correo electrónico" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "Introduce la dirección de correo electrónico Kindle" +msgid "Enter eReader Email" +msgstr "Enviar al correo de Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Comprobar correo electrónico" #: cps/templates/user_table.html:137 @@ -3403,10 +3544,6 @@ msgstr "sincronizar estanterías seleccionadas con Kobo" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Mostrar selección leidos/no leidos" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Mostrar libros al azar" - diff --git a/cps/translations/fi/LC_MESSAGES/messages.mo b/cps/translations/fi/LC_MESSAGES/messages.mo index da562e19..6172c12b 100644 Binary files a/cps/translations/fi/LC_MESSAGES/messages.mo and b/cps/translations/fi/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/fi/LC_MESSAGES/messages.po b/cps/translations/fi/LC_MESSAGES/messages.po index 7c2b433a..af37874f 100644 --- a/cps/translations/fi/LC_MESSAGES/messages.po +++ b/cps/translations/fi/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-01-12 13:56+0100\n" "Last-Translator: Samuli Valavuo \n" "Language: fi\n" @@ -16,495 +16,505 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Tilastot" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Palvelin uudelleenkäynnistetty, ole hyvä ja päivitä sivu" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Palvelinta sammutetaan, ole hyvä ja sulje sivu" -#: cps/admin.py:156 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:159 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Kirja lisätty onnistuneeksi lähetettäväksi osoitteeseen %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Kirja lisätty onnistuneeksi lähetettäväksi osoitteeseen %(eReadermail)s" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Tuntematon" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Ylläpitosivu" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Perusasetukset" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Käyttöliittymän asetukset" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Pääkäyttäjä" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Kaikki" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Näytä kaikki" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web asetukset päivitetty" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Oletko varma, että haluat poistaa hyllyn?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Oletko varma, että haluat poistaa hyllyn?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Oletko varma, että haluat poistaa hyllyn?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Oletko varma, että haluat poistaa hyllyn?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Haluatko varmasti pysäyttää Calibre-Webin?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Lisää uusi käyttäjä" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Muuta SMTP asetuksia" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Testisähköpostin lähetyksessä tapahtui virhe: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Sähköpostipalvelimen tiedot päivitetty" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Tapahtui tuntematon virhe. Yritä myöhemmin uudelleen." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Muokkaa käyttäjää %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Käyttäjän %(user)s salasana palautettu" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Ole hyvä ja aseta SMTP postiasetukset ensin..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Lokitiedoston katselin" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Haetaan päivitystiedostoa" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Ladataan päivitystiedostoa" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Puretaan päivitystiedostoa" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Korvataan tiedostoja" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Tietokantayhteydet on katkaistu" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Sammutetaan palvelin" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Päivitys valmistui, ole hyvä ja paina OK ja lataa sivu uudelleen" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Päivitys epäonnistui:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP virhe" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Yhteysvirhe" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Aikakatkaisu yhteyttä luotaessa" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Yleinen virhe" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Sähköpostipalvelimen tiedot päivitetty" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Ominaisuuksien asetukset" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Ole hyvä ja täytä kaikki kentät!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "Sähköpostiosoite ei ole toimivasta domainista" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Lisää uusi käyttäjä" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Käyttäjä '%(user)s' lisätty" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Tälle sähköpostiosoitteelle tai tunnukselle löytyi jo tili." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Käyttäjä '%(nick)s' poistettu" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Pääkäyttäjiä ei jää jäljelle, käyttäjää ei voi poistaa" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Käyttäjä '%(nick)s' päivitetty" @@ -517,122 +527,122 @@ msgstr "ei asennettu" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Ei mitään" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Virhe eKirjan avaamisessa. Tiedostoa ei ole tai se ei ole saatavilla:" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadata päivitetty onnistuneesti" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Tiedosto %(file)s tallennettu" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Lähteen tai kohteen tiedostomuoto puuttuu" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Kirja lisätty muutosjonoon muotoon %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Kirjan muunnoksessa tapahtui virhe: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s ei ole kelvollinen kieli" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Tiedostopääte '%(ext)s' ei ole sallittujen palvelimelle ladattavien listalla" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Ladattavalla tiedostolla on oltava tiedostopääte" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "muokkaa metadataa" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Polun %(path)s luonti epäonnistui (Ei oikeutta)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Tiedoston %(file)s tallennus epäonnistui." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Tiedostoformaatti %(ext)s lisätty %(book)s" @@ -645,181 +655,186 @@ msgstr "Google Drive asetukset ei ole valmiit. Koita poistaa Google Drive käyt msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Paluuosoitteen domain ei ole varmistettu, seuraa ohjeita vamistaaksesi sen googlen kehittäjäkonsolissa" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s tiedostomuotoa ei löytynyt kirjalle: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s ei löytynyt Google Drivesta: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s ei löydy: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Lähetä Kindleen" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Tämä sähköposti on lähetetty Calibre-Web:sta." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web testisähköposti" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Testi sähköposti" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Aloita Calibre-Web:in käyttö" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Rekiströintisähköposti käyttäjälle: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Muunna %(orig)s muotoon %(format)s ja lähetä Kindleen" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Lähetä %(format)s Kindleen" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Lähetä Kindleen" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Haettua tiedostoa ei pystytty lukemaan. Ehkä vaäärät oikeudet?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Tiedon muuttaminen arvosta: '%(src)s' arvoon '%(dest)s' epäonnistui virheeseen: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Tiedostoa %(file)s ei löytynyt Google Drivesta" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Tiedon muuttaminen arvosta: '%(src)s' arvoon '%(dest)s' epäonnistui virheeseen: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Kirjan polkua %(path)s ei löytynyt Google Drivesta" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Tälle sähköpostiosoitteelle läytyi jo käyttäjätunnus." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Löydä" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -828,9 +843,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "Rekisteröi tuottajalle %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "olet nyt kirjautunut tunnuksella: \"%(nickname)s\"" #: cps/oauth_bb.py:148 @@ -889,12 +904,13 @@ msgstr "Google Oauth virhe, yritä myöhemmin uudelleen." msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Kirjaudu sisään" @@ -910,149 +926,158 @@ msgstr "Valtuutus vanhentunut" msgid "Success! Please return to your device" msgstr "Onnistui! Ole hyvä ja palaa laitteellesi" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Kirjat" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Näytä viimeisimmät kirjat" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Kuumat kirjat" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Näytä kuumat kirjat" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Parhaiten arvioidut kirjat" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Näytä parhaiten arvioidut kirjat" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Luetut kirjat" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Näytä luetut ja lukemattomat" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Lukemattomat kirjat" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Näyt lukemattomat" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Löydä" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Näytä satunnausia kirjoja" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Kategoriat" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Näytä kategoriavalinta" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Sarjat" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Näytä sarjavalinta" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Kirjailijat" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Näytä kirjailijavalinta" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Julkaisijat" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Näytä julkaisijavalinta" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Kielet" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Näytä keilivalinta" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Arvostelut" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Näytä arvosteluvalinta" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Tiedotomuodot" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Näytä tiedostomuotovalinta" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" -msgstr "" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Näytä viimeisimmät kirjat" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Hae" @@ -1076,14 +1101,14 @@ msgstr "Arvostelu >= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Edistynyt haku" @@ -1134,7 +1159,7 @@ msgstr "Kirja on poistettu hyllystä: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "luo hylly" @@ -1161,73 +1186,73 @@ msgstr "Metadata päivitetty onnistuneesti" msgid "Change order of Shelf: '%(name)s'" msgstr "Muuta hyllyn: '%(name)s' järjestystä" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Hylly %(title)s luotu" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Hylly %(title)s muutettu" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Tapahtui virhe" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Hylly: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Virhe hyllyn avauksessa. Hyllyä ei ole tai se ei ole saatavilla" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Tehtävät" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Odottaa" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Epäonnistui" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Aloitettu" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Valmistui" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Tuntematon tila" @@ -1260,146 +1285,185 @@ msgstr "Uusi päivitys saatavilla. Paina alla olevaa nappia päivittääksesi ve msgid "No release information available" msgstr "Ei päivitystietoa saatavilla" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Löydä (satunnaiset kirjat)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Kuumat kirjat (ladatuimmat)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Kirjailija: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Julkaisija: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Sarja: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Arvostelu: %(rating)s tähteä" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Tiedostomuoto: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategoria: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Kieli: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "DLS" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Arvostelulistaus" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Tiedostomuotolistaus" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Kirja lisätty onnistuneeksi lähetettäväksi osoitteeseen %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Ole hyvä ja aseta SMTP postiasetukset ensin..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Kirja lisätty onnistuneeksi lähetettäväksi osoitteeseen %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Kirjan: %(res)s lähettämisessa tapahtui virhe" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Ole hyvä ja aseta Kindle sähköpostiosoite ensin..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Rekisteröi" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Sähköpostiosoitteellasi ei ole sallittua rekisteröityä" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Vahvistusviesti on lähetetty sähköpostiosoitteeseesi." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "LDAP autnetikoinnin aktivointi ei onnistu" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "olet nyt kirjautunut tunnuksella: \"%(nickname)s\"" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Väärä käyttäjätunnus tai salasana" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Tapahtui tuntematon virhe. Yritä myöhemmin uudelleen." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" -msgstr "" +msgstr "Väärä käyttäjätunnus tai salasana" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "olet kirjautunut tunnuksella: '%(nickname)s'" +msgstr "olet nyt kirjautunut tunnuksella: \"%(nickname)s\"" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)sn profiili" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Profiili päivitetty" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Tälle sähköpostiosoitteelle läytyi jo käyttäjätunnus." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Lähetä Kindleen" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1442,35 +1506,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "muokkaa metadataa" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Lähetä" @@ -1486,15 +1550,15 @@ msgstr "Lempinimi" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Sähköposti" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Ylläpito" @@ -1504,8 +1568,8 @@ msgstr "Ylläpito" msgid "Password" msgstr "Salasana" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Lataa" @@ -1530,16 +1594,12 @@ msgstr "Poista" msgid "Public Shelf" msgstr "" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "SMTP sähköpostipalvelimen asetukset" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1560,11 +1620,11 @@ msgstr "SMTP tunnus" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Lähettäjän sähköposti" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1637,102 +1697,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Ylläpito" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Katsele lokitiedostoja" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Uudelleenyhdistä Calibre DB" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Uudellenkäynnistä Calibre-Web" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Sammuta Calibre-Web" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versio" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Yksityiskohdat" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Nykyinen versio" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Tarkista päivitykset" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Päivitä" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Haluatko varmasti uudelleenkäynnistää Calibre-Webin?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Ok" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Haluatko varmasti pysäyttää Calibre-Webin?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Päivitetään, älä päivitä sivua" @@ -1822,7 +1884,7 @@ msgid "Author" msgstr "Kirjailija" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Kuvaus" @@ -1847,7 +1909,7 @@ msgstr "" msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Tunnisteet" @@ -1872,23 +1934,23 @@ msgid "Published Date" msgstr "Julkaisupäivä" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Julkaisija" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Kieli" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Kyllä" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Ei" @@ -1905,8 +1967,8 @@ msgid "Fetch Metadata" msgstr "Hae metadata" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1929,8 +1991,8 @@ msgstr "Klikkaa kantta ladataksesi metadata lomakkeelle" msgid "Loading..." msgstr "Ladataan..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Sulje" @@ -2157,7 +2219,7 @@ msgid "Enable Uploads" msgstr "Salli lähetys" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2173,7 +2235,7 @@ msgid "Enable Public Registration" msgstr "Salli julkinen rekisteröinti" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2363,6 +2425,52 @@ msgstr "" msgid "Location of Unrar binary" msgstr "Unrar binäärin paikka" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth asetukset" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Nollaa käyttäjän salasana" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Näytä konfiguraatio" @@ -2375,7 +2483,7 @@ msgstr "Satunnaisten kirjojen näytön lukumäärä" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Kirjailijoiden lukumäärä ennen piilotusta (0=poista piilotus)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Teema" @@ -2466,79 +2574,82 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Lue selaimessa" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Kuuntele selaimessa" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Merkitse lukemattomaksi" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Merkitse luetuksi" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Luettu" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Kuvaus:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Lisää hyllyyn" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Muokkaa metadataa" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "" +#, fuzzy +msgid "Gmail Account" +msgstr "Tili" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2562,10 +2673,11 @@ msgid "Attachment Size Limit" msgstr "" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Tallenna asetukset ja testaa sähköpostia" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Palaa" @@ -2591,12 +2703,12 @@ msgstr "Syötä domainnimi" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Seuraava" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2607,19 +2719,19 @@ msgstr "" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Luo virheilmoitus" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Palaa kotiin" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2649,80 +2761,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Aloita" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Suositut julkaisut tästä kokoelmasta perustuen latauksiin." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Suositut julkaisut tästä kokoelmasta perustuen arvioihin." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Viimeisimmät kirjat" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Satunnaisia kirjoja" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Kirjat kirjailijoittain" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Kirjat julkaisijoittain" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Kirjat kategorioittain" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Kirjat sarjoittain" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Koti" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Vaihda navigointi" @@ -2730,48 +2842,48 @@ msgstr "Vaihda navigointi" msgid "Search Library" msgstr "" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Ladataan..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Virhe" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Lataus tehty, prosessoidaan, ole hyvä ja odota..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Asetukset" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Tili" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Kirjaudu ulos" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Ladataan..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Virhe" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Lataus tehty, prosessoidaan, ole hyvä ja odota..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Asetukset" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Selaa" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Tietoja" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Edellinen" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Kirjan tiedot" @@ -2787,7 +2899,7 @@ msgstr "Muista minut" msgid "Forgot Password?" msgstr "" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Kirjadu käyttäen magic link" @@ -2897,137 +3009,162 @@ msgstr "Calibre-Web e-kirjaluettelo" msgid "epub Reader" msgstr "PDF lukija" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Vaalea" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Tumma" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Palaa" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Uudelleenjärjestä teksti kun sivut on auki." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "PDF lukija" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Näppäimistöpikakomennot" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Edellinen sivu" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Seuraava sivu" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Skaalaa parhaaseen" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Skaalaa leveyteen" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Skaalaa korkeuteen" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Skaalaa alkuperäiseen" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Käännä oikealle" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Käännä vasemmalle" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Käännä kuva" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Ylläpitosivu" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Skaalaa" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Paras" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Leveys" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Korkeus" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Alkuperäinen" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Pyöritä" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Käännä" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Vaakasuunta" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Pystysuunta" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Suunta" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Vasemmalta oikealle" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Oikealta vasemmalle" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3036,7 +3173,7 @@ msgstr "" msgid "DJVU Reader" msgstr "PDF lukija" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "PDF lukija" @@ -3055,7 +3192,7 @@ msgid "Choose a username" msgstr "Valitse käyttäjänimi" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Sähköpostiosoitteesi" #: cps/templates/remote_login.html:5 @@ -3074,10 +3211,6 @@ msgstr "Kun teet näin, sinut kirjataan automaattisesti sisään tälle laitteel msgid "This verification link will expire in 10 minutes." msgstr "Linkki vanhenee 10 minuutissa." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3102,44 +3235,52 @@ msgstr "Julkaisupäivästä" msgid "Published Date To" msgstr "Julkaisupäivään" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Poissulje merkintä" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Poissulje sarja" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Poissulje sarja" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Poissulje kieli" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Arvio enemmän kun" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Arvio vähemmän kun" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3231,10 +3372,6 @@ msgstr "Edistyminen" msgid "Run Time" msgstr "Ajoaika" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Käynnistysaika" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3311,17 +3448,17 @@ msgstr "Valitse käyttäjänimi" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Sähköpostiosoitteesi" +msgid "Enter Email" +msgstr "Testi sähköposti" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Testi sähköposti" #: cps/templates/user_table.html:137 @@ -3385,10 +3522,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Näytä sarjavalinta" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Näytä satunnaisia kirjoja" - diff --git a/cps/translations/fr/LC_MESSAGES/messages.mo b/cps/translations/fr/LC_MESSAGES/messages.mo index 7f35597f..6c97b6c9 100644 Binary files a/cps/translations/fr/LC_MESSAGES/messages.mo and b/cps/translations/fr/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/fr/LC_MESSAGES/messages.po b/cps/translations/fr/LC_MESSAGES/messages.po index bbca624a..1340b87f 100644 --- a/cps/translations/fr/LC_MESSAGES/messages.po +++ b/cps/translations/fr/LC_MESSAGES/messages.po @@ -22,7 +22,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-06-07 06:47+0200\n" "Last-Translator: \n" "Language: fr\n" @@ -31,498 +31,508 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statistiques" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Serveur redémarré, merci de rafraîchir la page" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Arrêt du serveur en cours, merci de fermer la fenêtre" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Reconnecté avec succès" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Commande inconnue" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Le livre a été mis en file de traitement avec succès pour un envoi vers %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Teste les courriels en file d’attente pour l’envoi à %(email)s, veuillez vérifier le résultat des tâches" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Inconnu" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Page admin" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configuration principale" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configuration de l’interface utilisateur" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Éditer les utilisateurs" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Tout" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "L'utilisateur n'a pas été trouvé" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} utilisateurs supprimés avec succès" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Montrer tout" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Demande malformée" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Le nom de l’invité ne peut pas être modifié" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "L’invité ne peut pas avoir ce rôle" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Aucun utilisateur admin restant, impossible de supprimer le rôle admin" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "La valeur doit être vraie ou fausse" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Rôle invalide" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "L’invité ne peut pas avoir cette vue" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Vue invalide" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Les paramètres régionaux de l’invité sont déterminés automatiquement et ne peuvent pas être définis" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Aucun paramètre régional valide n’est donné" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Aucune langue de livre valide donnée" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Paramètre non trouvé" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Colonne de lecture non valide" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Colonne restreinte non valide" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Configuration de Calibre-Web mise à jour" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Voulez-vous vraiment supprimer le jeton Kobo ?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Voulez-vous vraiment supprimer ce domaine ?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Voulez-vous vraiment supprimer cet utilisateur ?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Voulez-vous vraiment supprimer l’étagère ?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Voulez-vous vraiment supprimer l’étagère ?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "Voulez-vous vraiment modifier les langues de livre visibles pour le ou les utilisateurs sélectionnés ?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Voulez-vous vraiment modifier le rôle sélectionné pour le ou les utilisateurs sélectionnés ?" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Voulez-vous vraiment modifier les restrictions sélectionnées pour le ou les utilisateurs sélectionnés ?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "Voulez-vous vraiment modifier les restrictions de visibilité sélectionnées pour le ou les utilisateurs sélectionnés ?" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Voulez-vous vraiment supprimer l’étagère?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Voulez-vous vraiment arrêter Calibre-Web ?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "Êtes-vous certain de vouloir supprimer la base de données de synchronisation de Calibre-Web pour forcer une synchronisation complète avec votre liseuse Kobo ?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Refuser" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Autoriser" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} entrées de synchronisation supprimées" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Étiquette introuvable" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Action invalide" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json n'est pas configuré pour l'application Web" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "L'emplacement du fichier logfile est incorrect, veuillez saisir un chemin valide" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "L'emplacement du fichier Access Logfile est incorrect, veuillez saisir un chemin valide" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Veuillez saisir un fournisseur LDAP, Port, DN et l'identifiant objet de l'utilisateur" -#: cps/admin.py:1179 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Veuillez entrer un nom d'utilisateur valide pour réinitialiser le mot de passe" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Veuillez entrer un compte de service LDAP" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "Le filtre objet du groupe LDAP a besoin d'un identifiant de format \"%s\"" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Le filtre objet du groupe LDAP a une parenthèse non gérée" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "Le filtre objet de l'utilisateur LDAP a besoin d'un identifiant de format \"%s\"" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Le filtre objet de l'utilisateur LDAP a une parenthèse non gérée" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "Le filtre utilisateur des membres LDAP doit avoir un identificateur de format \"%s\\ »" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "Le filtre utilisateur de membre LDAP a des parenthèses non appariées" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CACertificat, certificat ou emplacement de clé non valide, veuillez entrer le chemin correct" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Ajouter un nouvel utilisateur" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Modifier les paramètres du serveur de courriels" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "La vérification du compte Gmail réussie" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Erreur de la base de données: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "Teste les courriels en file d’attente pour l’envoi à %(email)s, veuillez vérifier le résultat des tâches" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Il y a eu une erreur pendant l’envoi du courriel de test : %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Veuillez d'abord configurer votre adresse de courriel..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Les paramètres du serveur de courriels ont été mis à jour" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Une erreur inconnue est survenue. Veuillez réessayer plus tard." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Éditer l'utilisateur %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Le mot de passe de l’utilisateur %(user)s a été réinitialisé" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Veuillez configurer les paramètres SMTP au préalable..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visualiseur de fichier journal" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Demande de mise à jour" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Téléchargement de la mise à jour" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Décompression de la mise à jour" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Remplacement des fichiers" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Les connexions à la base de données ont été fermées" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Arrêt du serveur" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Mise à jour terminée, merci d’appuyer sur okay et de rafraîchir la page" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "La mise à jour a échoué :" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Erreur HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Erreur de connexion" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Délai d'attente dépassé lors de l'établissement de connexion" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Erreur générale" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Le fichier de mise à jour ne peut pas être sauvegardé dans le répertoire temporaire" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "Les fichiers n’ont pas pu être remplacés pendant la mise à jour" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Impossible de créer au moins un utilisateur LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Impossible de créer au moins un utilisateur LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Erreur : %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Erreur : Aucun utilisateur renvoyé dans la réponse LDAP du serveur" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Au moins un utilisateur LDAP n'a pas été trouvé dans la base de données" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} utilisateur importé avec succès" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "L'emplacement de la base de données est incorrect, veuillez saisir un chemin valide" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "La base de données n'est pas accessible en écriture" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "L'emplacement du fichier Keyfile est incorrect, veuillez saisir un chemin valide" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "L'emplacement du fichier Certfile est incorrect, veuillez saisir un chemin valide" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Les paramètres du serveur de courriels ont été mis à jour" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Configuration des options" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Veuillez compléter tous les champs !" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "Cette adresse de courriel n’appartient pas à un domaine valide" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Ajouter un nouvel utilisateur" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Utilisateur '%(user)s' créé" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Un compte existant a été trouvé pour cette adresse de courriel ou pour ce surnom." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Utilisateur '%(nick)s' supprimé" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Impossible de supprimer l’utilisateur Invité" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Aucun utilisateur admin restant, impossible de supprimer l’utilisateur" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Utilisateur '%(nick)s' mis à jour" @@ -535,122 +545,122 @@ msgstr "non installé" msgid "Execution permissions missing" msgstr "Les permissions d'exécutions manquantes" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "La colonne personnalisée No.%(column)d n'existe pas dans la base de données calibre" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Aucun" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Erreur d'ouverture du livre numérique. Le fichier n'existe pas ou n'est pas accessible" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Les identificateurs ne sont pas sensibles à la casse, écrasant l’ancien identificateur" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Les métadonnées ont bien été mises à jour" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Le fichier %(file)s a été téléchargé" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Le format de conversion de la source ou de la destination est manquant" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Le livre a été mis avec succès en file de traitement pour conversion vers %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Une erreur est survenue au cours de la conversion du livre : %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Le fichier téléchargé existe probablement dans la librairie, veuillez le modifier avant de le télécharger de nouveau: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s n'est pas une langue valide" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "L’extension de fichier '%(ext)s' n’est pas autorisée pour être déposée sur ce serveur" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Pour être déposé le fichier doit avoir une extension" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Le fichier %(filename)s ne peut pas être sauvegardé dans le répertoire temporaire" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Impossible de déplacer le fichier de couverture %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Le format du livre a été supprimé avec succès" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Le livre a été supprimé avec succès" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "Vous n’avez par les permissions pour supprimer les livres" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "modifier les métadonnées" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s n’est pas un nombre valide, ignoré" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Impossible de créer le chemin %(path)s (Permission refusée)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Échec de la sauvegarde du fichier %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Le format de fichier %(ext)s a été ajouté à %(book)s" @@ -663,183 +673,189 @@ msgstr "La configuration de Google Drive n’est pas terminée, essayez de désa msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Le domaine de retour d’appel (Callback domain) est non vérifié, veuillez suivre les étapes nécessaires pour vérifier le domaine dans la console de développement de Google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "le format %(format)s est introuvable pour le livre : %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "le %(format)s est introuvable sur Google Drive : %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s introuvable : %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Envoyer vers Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Ce courriel a été envoyé depuis Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Courriel de test de Calibre-Web" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Courriel de test" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Bien démarrer avec Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Courriel d’inscription pour l’utilisateur : %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Convertir de %(orig)s vers %(format)s et envoyer au Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Envoyer %(format)s vers le Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Envoyer vers Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Le fichier demandé n’a pu être lu. Problème de permission d’accès ?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Échec de la suppression du dossier de livre pour le livre %(id)s, le chemin d’accès comporte des sous-dossiers : %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "La suppression du livre %(id)s a échoué: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, fuzzy, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Suppression du livre %(id)s, le chemin du livre est invalide : %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Renommer le titre de : '%(src)s' à '%(dest)s' a échoué avec l’erreur : %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Le fichier %(file)s n'a pas été trouvé dans Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Renommer le titre de : '%(src)s' à '%(dest)s' a échoué avec l’erreur : %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Le chemin du livre %(path)s n'a pas été trouvé dans Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Un compte existant a été trouvé pour cette adresse de courriel." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Cet utilisateur est déjà pris" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Format de l’adresse courriel invalide" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Erreur lors du téléchargement de la couverture" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Erreur de format de couverture" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Impossible de créer le chemin pour la couverture" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Le fichier couverture n'est pas un fichier image valide, ou ne peut pas être stocké" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Seuls les fichiers jpg/jpeg/png/webp/bmp sont supportés comme fichier de couverture" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "Contenu du fichier de couverture invalide" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Seuls les fichiers jpg/jpeg sont supportés comme fichier de couverture" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Fichier binaire Unrar non trouvé" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Une erreur est survenue lors de l'exécution d'UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Découvrir" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Veuilllez ne pas accéder à calibre-web par localhost pour obtenir un api_endpoint valide pour un appareil kobo" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configuration Kobo" @@ -848,9 +864,9 @@ msgstr "Configuration Kobo" msgid "Register with %(provider)s" msgstr "Enregistrer avec %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "vous êtes maintenant connecté comme : '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -909,12 +925,13 @@ msgstr "Erreur Oauth Google, veuillez réessayer plus tard." msgid "Google Oauth error: {}" msgstr "Erreur Oauth Google : {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Étoiles" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Connexion" @@ -930,149 +947,158 @@ msgstr "Jeton expiré" msgid "Success! Please return to your device" msgstr "Réussite! Merci de vous tourner vers votre appareil" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Livres" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Afficher les livres récents" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Livres populaires" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Montrer les livres populaires" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Livres téléchargés" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Montrer les livres téléchargés" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Livres les mieux notés" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Montrer les livres les mieux notés" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Livres lus" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Montrer lus et non-lus" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Livres non-lus" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Afficher non-lus" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Découvrir" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Montrer des livres au hasard" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Catégories" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Montrer la sélection par catégories" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Séries" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Montrer la sélection par séries" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Auteurs" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Montrer la sélection par auteur" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Éditeurs" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Montrer la sélection par éditeur" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Langues" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Montrer la sélection par langue" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Notes" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Afficher la sélection des évaluations" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Formats de fichier" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Afficher la sélection des formats de fichiers" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Livres archivés" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Afficher les livres archivés" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Liste des livres" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Montrer la liste des livres" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Chercher" @@ -1095,15 +1121,15 @@ msgid "Rating >= %(rating)s" msgstr "Évaluation >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Status de lecture = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Erreur lors de la recherche de colonnes personnalisées, veuillez redémarrer Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Recherche avancée" @@ -1154,7 +1180,7 @@ msgstr "Le livre a été supprimé de l'étagère %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "Désolé, vous n’êtes pas autorisé à supprimer un livre de cette étagère" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Créer une étagère" @@ -1181,73 +1207,73 @@ msgstr "Le livre a été supprimé avec succès" msgid "Change order of Shelf: '%(name)s'" msgstr "Modifier l’arrangement de l’étagère : ‘%(name)s’" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "Désolé, vous n’êtes pas autorisé à créer une étagère publique" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Étagère %(title)s créée" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "L’étagère %(title)s a été modifiée" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Il y a eu une erreur" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Une étagère publique avec le nom '%(title)s' existe déjà." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Une étagère privée avec le nom '%(title)s' existe déjà." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Étagère : '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Erreur à l’ouverture de l’étagère. Elle n’existe plus ou n’est plus accessible" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Tâches" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "En attente" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Echoué" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Débuté" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Terminé" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Statut inconnu" @@ -1280,146 +1306,186 @@ msgstr "Une nouvelle mise à jour est disponible. Cliquez sur le bouton ci-desso msgid "No release information available" msgstr "Aucune information concernant cette version n’est disponible" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Découvrir (Livres au hasard)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Livres populaires (les plus téléchargés)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Livres téléchargés par %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Auteur : %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Éditeur : '%(name)s'" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Séries : %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Évaluation : %(rating)s étoiles" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Format de fichier : %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Catégorie : %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Langue : %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Téléchargements" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Liste des évaluations" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Liste de formats de fichiers" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Le livre a été mis en file de traitement avec succès pour un envoi vers %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Veuillez configurer les paramètres SMTP au préalable..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Le livre a été mis en file de traitement avec succès pour un envoi vers %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Il y a eu une erreur en envoyant ce livre : %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Veuillez mettre à jour votre profil avec une adresse de courriel Kindle valide." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "Le serveur de courriel n'est pas configuré, veuillez contacter votre administrateur!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Créer un compte" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Le serveur de courriel n'est pas configuré, veuillez contacter votre administrateur!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Votre adresse de courriel n’est pas autorisé pour une inscription" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Le courriel de confirmation a été envoyé à votre adresse." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Impossible d’activer l’authentification LDAP" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "vous êtes maintenant connecté comme : '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Connexion de secours comme: '%(nickname)s', le serveur LDAP est indisponible, ou l'utilisateur est inconnu" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Impossible de se connecter: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Mauvais nom d'utilisateur ou mot de passe" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Le nouveau mot de passe a été envoyé vers votre adresse de courriel" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Une erreur inconnue est survenue. Veuillez réessayer plus tard." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Veuillez entrer un nom d'utilisateur valide pour réinitialiser le mot de passe" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Vous êtes maintenant connecté en tant que : ‘%(nickname)s’" +msgstr "vous êtes maintenant connecté comme : '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Profil de %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Profil mis à jour" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Un compte existant a été trouvé pour cette adresse de courriel." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Aucun fichier gmail.json avec information OAuth valide trouvé" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Envoyer vers Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1462,35 +1528,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "modifier les métadonnées" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Téléverser" @@ -1506,15 +1572,15 @@ msgstr "Nom d'utilisateur" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Adresse de courriel" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Envoyer vers une adresse de courriel Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Administration" @@ -1524,8 +1590,8 @@ msgstr "Administration" msgid "Password" msgstr "Mot de passe" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Télécharger" @@ -1550,16 +1616,12 @@ msgstr "Supprimer" msgid "Public Shelf" msgstr "Étagère publique" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Ajouter un nouvel utilisateur" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importer des utilisateurs LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Paramètres du serveur de courriels" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1580,11 +1642,12 @@ msgstr "Compte utilisateur SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Expéditeur des courriels" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "Service courriel" #: cps/templates/admin.html:91 @@ -1657,102 +1720,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Administration" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Télécharger le package de débogage" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Afficher les fichiers journaux" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Reconnecter la base de données Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Redémarrer Calibre-Web" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Arrêter Calibre-Web" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Version" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Détails" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Version actuelle" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Rechercher les mises à jour" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Effectuer la mise à jour" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Voulez-vous vraiment redémarrer Calibre-Web?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Annuler" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Voulez-vous vraiment arrêter Calibre-Web?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Mise à jour en cours, ne pas rafraîchir la page" @@ -1842,7 +1907,7 @@ msgid "Author" msgstr "Auteur" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Description" @@ -1867,7 +1932,7 @@ msgstr "Supprimer" msgid "Add Identifier" msgstr "Ajouter un identifiant" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Étiquettes" @@ -1892,23 +1957,23 @@ msgid "Published Date" msgstr "Date de publication" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Éditeur" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Langue" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Oui" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Non" @@ -1925,8 +1990,8 @@ msgid "Fetch Metadata" msgstr "Obtenir les métadonnées" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1949,8 +2014,8 @@ msgstr "Cliquer sur la couverture pour importer les métadonnées dans le formul msgid "Loading..." msgstr "Chargement..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Fermer" @@ -2178,7 +2243,7 @@ msgid "Enable Uploads" msgstr "Autoriser le téléversement de fichier" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "(Svp, vérifiez que les utilisateurs ont aussi les droits de téléchargement vers le serveur)" #: cps/templates/config_edit.html:112 @@ -2194,7 +2259,7 @@ msgid "Enable Public Registration" msgstr "Autoriser l’inscription publique" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Utiliser l'e-mail comme nom d'utilisateur" #: cps/templates/config_edit.html:132 @@ -2384,6 +2449,52 @@ msgstr "Chemin vers le convertisseur de livres Kepubify" msgid "Location of Unrar binary" msgstr "Chemin d’accès à la commande UnRar" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Réglages OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Réinitialiser le mot de passe de l’utilisateur" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Configuration du mode d’affichage" @@ -2396,7 +2507,7 @@ msgstr "Nombre de livres choisis au hasard à afficher" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Nombre d’auteurs à afficher avant de masquer (0=désactiver le masquage)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Thème" @@ -2487,80 +2598,84 @@ msgstr "Ajouter les étiquettes autorisées/refusées" msgid "Add Allowed/Denied custom column values" msgstr "Ajouter les valeurs de colonnes autorisées/refusées" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Lire dans le navigateur" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Écouter dans le navigateur" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, fuzzy, python-format msgid "Book %(index)s of %(range)s" msgstr "Livre %(index)s sur %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publié" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Marquer comme non lu" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Marquer comme lu" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Lu" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Restaurer à partir de l'archive" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Ajouter comme archive" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archivé" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Description :" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Ajouter à l'étagère" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Public)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Éditer les métadonnées" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Choisissez le type de serveur" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Utilisez le compte courriel standard" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Compte Gmail avec vérification OAuth2" +#, fuzzy +msgid "Gmail Account" +msgstr "Choisissez le type de serveur" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Configuration du compte Gmail comme serveur courriel" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2583,10 +2698,11 @@ msgid "Attachment Size Limit" msgstr "Limite de la taille de la pièce jointe" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Sauvegarder les réglages et tester l’envoi d’un courriel" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Retour" @@ -2612,13 +2728,13 @@ msgstr "Saisir le nom du domaine" msgid "Denied Domains (Blacklist)" msgstr "Domaines refusés (Liste noire)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Suivant" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Ouvrir le fichier .kobo/Kobo eReader.conf dans un éditeur de texte et ajouter (ou éditer):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Ouvrir le fichier .kobo/Kobo/Kobo eReader.conf dans un éditeur de texte et ajouter (ou éditer):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2629,20 +2745,20 @@ msgstr "Jeton de synchro Kobo" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Le serveur de courriel n'est pas configuré, veuillez contacter votre administrateur!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Signaler un problème" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Retour à l’accueil" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "Déconnecter l’utilisateur" @@ -2672,80 +2788,80 @@ msgstr "Trier par ordre croissant en fonction de l’index de série" msgid "Sort descending according to series index" msgstr "Trier par ordre décroissant en fonction de l’index de série" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Démarrer" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Livres alphabétiques" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Livres triés dans l’ordre alphabétique" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Publications populaires depuis le catalogue basées sur les téléchargements." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Publications populaires de ce catalogue sur la base des évaluations." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Livres récents ajoutés" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Les derniers livres" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Livres au hasard" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Livres classés par auteur" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Livres classés par éditeur" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Livres classés par catégorie" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Livres classés par série" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Livres classés par langue" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Livres classés par évaluation" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Livres classés par formats de fichiers" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Etagères" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Livres organisés par étagères" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Accueil" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Basculer la navigation" @@ -2753,48 +2869,48 @@ msgstr "Basculer la navigation" msgid "Search Library" msgstr "Chercher dans librairie" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Téléversement en cours..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Erreur" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Téléversement terminé, traitement en cours, veuillez patienter…." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Paramètres" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Compte" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Déconnexion" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Téléversement en cours..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Erreur" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Téléversement terminé, traitement en cours, veuillez patienter…." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Paramètres" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Veuillez ne pas rafraîchir la page" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Explorer" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "À propos" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Précédent" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Détails du livre" @@ -2810,7 +2926,7 @@ msgstr "Se rappeler de moi" msgid "Forgot Password?" msgstr "Mot de passe oublié ?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Se connecter avec Magic Link" @@ -2920,137 +3036,162 @@ msgstr "Catalogue de livres électroniques Calibre-Web" msgid "epub Reader" msgstr "Lecteur PDF" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Clair" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Sombre" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Retour" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Mettre à jour la mise en page du texte quand les bandeaux latéraux sont ouverts." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "Lecteur PDF" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Raccourcis clavier" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Page précédente" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Page suivante" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Mise à l’échelle optimale" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Mise à l’échelle sur la largeur" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Mise à l’échelle sur la hauteur" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Mise à l’échelle d’origine" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Rotation droite" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Rotation gauche" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Inverser l’image" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Page admin" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Échelle" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Optimal" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Largeur" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Hauteur" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Origine" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Rotation" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Inverser" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Horizontal" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Vertical" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Direction" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "De gauche à droite" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "De droite à gauche" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Réinitialiser en haut" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Se rappeler de la position" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Barre de défilement" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Montrer" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Cacher" @@ -3059,7 +3200,7 @@ msgstr "Cacher" msgid "DJVU Reader" msgstr "Lecteur PDF" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "Lecteur PDF" @@ -3078,7 +3219,7 @@ msgid "Choose a username" msgstr "Choisissez un nom d'utilisateur" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Votre adresse de courriel" #: cps/templates/remote_login.html:5 @@ -3097,10 +3238,6 @@ msgstr "Une fois fait, vous serez automatiquement connecté à cet appareil." msgid "This verification link will expire in 10 minutes." msgstr "Le lien expirera après 10 minutes." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3125,44 +3262,52 @@ msgstr "Date de publication (depuis)" msgid "Published Date To" msgstr "Date de publication (jusqu’à)" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Exclure les étiquettes" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Exclure les séries" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Exclure les séries" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Exclure les langues" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Extensions" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Exclure les extensions" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Évaluation supérieure à" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Évaluation inférieure à" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "Depuis" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Vers" @@ -3254,10 +3399,6 @@ msgstr "Avancement" msgid "Run Time" msgstr "Durée" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Démarrage" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3334,17 +3475,17 @@ msgstr "Choisissez un nom d'utilisateur" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Votre adresse de courriel" +msgid "Enter Email" +msgstr "Courriel de test" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "Envoyer vers une adresse de courriel Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Courriel de test" #: cps/templates/user_table.html:137 @@ -3415,10 +3556,6 @@ msgstr "Synchroniser les étagères sélectionnées avec Kobo" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Montrer la sélection par séries" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Montrer des livres au hasard" - diff --git a/cps/translations/gl/LC_MESSAGES/messages.mo b/cps/translations/gl/LC_MESSAGES/messages.mo index a51b6d75..40b996e9 100644 Binary files a/cps/translations/gl/LC_MESSAGES/messages.mo and b/cps/translations/gl/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/gl/LC_MESSAGES/messages.po b/cps/translations/gl/LC_MESSAGES/messages.po index a8245a7e..ffca5448 100644 --- a/cps/translations/gl/LC_MESSAGES/messages.po +++ b/cps/translations/gl/LC_MESSAGES/messages.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2022-08-11 16:46+0200\n" "Last-Translator: pollitor \n" "Language: gl\n" @@ -14,487 +14,497 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Estatísticas" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Servidor reiniciado. Por favor, recargue a páxina" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "O servidor estase apagando. Por favor, peche a xanela" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Reconexión correcta" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Orde descoñecida" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Libro posto na cola de envío a %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Posto en cola un correo electrónico de proba enviado a %(email)s, por favor, comproba o resultado nas Tarefas" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Descoñecido" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Páxina de administración" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configuración Básica" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configuración da Interface de Usuario" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Editar Usuarios" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Todo" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Usuario non atopado" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} usuarios borrados con éxito" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Mostrar Todo" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Petición mal formada" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "O nome do convidado non se pode cambiar" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "O convidado non pode ter este rol" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Non queda ningún usuario administrador, non se pode eliminar ao usuario" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "O Valor ten que ser verdadeiro ou falso" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Rol non válido" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "O convidado non pode ter esta vista" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Vista non válida" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "O sitio do convidado determínase automáticamente e non se pode cambiar" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Non hai unha localización válida" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Non se indicou unha lingua válida para o libro" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parámetro non atopado" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Columna de lectura non válida" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Columna restrinxida non válida" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Configuración de Calibre-Web actualizada" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "De verdade queres borrar o Token de Kobo?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "De verdade desexas borrar este dominio?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "De verdade queres borrar este usuario?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "De verdade queres eliminar este andel?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "De verdade queres cambiar a linguaxe dos usuarios seleccionados?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "De verdade queres cambiar as linguas visibles do libro dos usuarios seleccionados?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "De verdade queres cambiar o rol seleccionado do usuario seleccionado?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "De verdade queres cambiar as restricións escollidas dos usuarios seleccionados?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "De verdade queres cambiar as restricións de visibilidade dos usuarios seleccionados?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "De verdade queres cambiar o comportamento da sincronización do andel para o usuario seleccionado?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "De verdade queres cambiar a localización da biblioteca Calibre?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "Calibre-web buscará cubertas actualizadas e miniaturas de cubertas actualizadas, isto pode levar un intre?" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "Está seguro que quere borrar a base de datos de sincronización de Calibre-Web para forzar unha sincronización completa co seu lector Kobo?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Denegar" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Permitir" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "Elimináronse {} entradas de sincronización" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Etiqueta non atopada" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Acción non válida" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json non está configurado para a aplicación web" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "A localización do arquivo de rexistro non é válida. Por favor, Introduce a ruta correcta" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "A localización do rexistro de accesos non é válida. Por favor, Introduce a ruta correcta" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Por favor, Introduce un provedor LDAP, porto, DN e o User Object Identifier" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "Por favor, introduce unha conta de servizo LDAP e o seu contrasinal" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Por favor, introduce unha conta de servizo LDAP" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP Group Object Filter necesita ter un identificador de formato \"%s\"" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "O LDAP Group Object Filter ten parénteses que non casan" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP Group Object Filter necesita ter un identificador de formato \"%s\"" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "O LDAP Group Object Filter ten parénteses que non casan" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "O filtro de usuarios LDAP necesita ter un identificador de formato \"%s\"" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "O filtro de LDAP \"Member User\" ten parénteses que non casan" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "As localizacións do certificado da CA do LDAP, do certificado ou da chave non válidos. Por favor introduce a ruta correcta" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Engadir un usuario novo" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Engadir novo usuario" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Cambiar os parámetros do correo" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Verificación da conta de Gmail exitosa" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Error na base de datos: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "Posto en cola un correo electrónico de proba enviado a %(email)s, por favor, comproba o resultado nas Tarefas" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Ocurreu un error enviando o correo electrónico de proba: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Por favor, configure o seu correo electrónico primeiro..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Actualizáronse os axustes do servidor de correo electrónico" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "Editar a Configuración das Tarefas Programadas" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "Indicada unha hora incorrecta de comezo de tarefa" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "Indicada unha duracción incorrecta para a tarefa" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "Actualizouse a configuración das tarefas programadas" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Sucedeu un erro descoñecido. Por favor volva a intentalo máis tarde." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "A configuración da DB non se pode escribir" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Editar o Usuario %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Reiniciada a contrasinal para o usuario %(user)s" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Configura primeiro os parámetros do servidor SMTP..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visor do ficheiro de rexistro" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Solicitando paquete de actualización" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Descargando paquete de actualización" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Descomprimendo paquete de actualización" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Remplazando archivos" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "As conexións coa base datos están pechadas" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Detendo o servidor" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Actualización finalizada. Por favor, prema OK e recargue a páxina" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "A actualización fallou:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Erro HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Erro de conexión" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Tempo esgotado mentras se trataba de establecer a conexión" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Erro xeral" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "A actualización do arquivo non se puido gardar no directorio temporal (Temp Dir)" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "Non se puideron substituír os ficheiros durante a actualización" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "Erro ao extraer polo menos un usuario LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Erro ao crear polo menos un usuario LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Erro: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Erro: o servidor LDAP non devolveu ningún usuario" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Polo menos, un usuario LDAP non se atopou na base de datos" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "Usuario {} importado con éxito" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "A localización da base de datos non é válida. Por favor, Introduce a ruta correcta" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "A base de datos non é modificable" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "A localización do Keyfile non é válida, por favor, Introduce a ruta correcta" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "A localización do Certfile non é válida, por favor, Introduce a ruta correcta" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "Actualizados os axustes da base de datos" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "Configuración da base de datos" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Por favor, cubra todos os campos!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "O correo electrónico non ven dun dominio válido" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Engadir un usuario novo" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Usuario '%(user)s' creado" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "Atopada unha conta existente para este correo electrónico ou nome de usuario." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Usuario '%(nick)s' eliminado" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Non se pode borrar ao Usuario Invitado" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Non queda ningún usuario administrador, non se pode borrar ao usuario" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Usuario '%(nick)s' actualizado" @@ -507,122 +517,122 @@ msgstr "non instalado" msgid "Execution permissions missing" msgstr "Faltan permisos de execución" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Columna personalizada No.%(column)d non existe na base de datos calibre" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Ningún" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "oh, oh, o libro seleccionado non está disponible. O arquivo non existe ou non está accesible" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "O usuario non ten permisos para subir a cuberta" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Os identificadores non distinguen entre maiúsculas e minúsculas, sobrescribindo o identificador antigo" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadatos actualizados con éxito" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "Erro editando libro: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "O ficheiro %(file)s subiuse" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Falta a fonte ou o formato de destino para a conversión" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Libro posto na cola para a súa conversión a %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Houbo un erro ao convertir este libro: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "O libro cargado probablemente existe na biblioteca, considera cambialo antes de subilo outra vez: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s non é unha lingua válida" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Non se permite subir arquivos coa extensión '%(ext)s' a este servidor" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "O arquivo que se vai cargar debe ter unha extensión" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "El archivo %(filename)s non puido gravarse no directorio temporal (Temp Dir)" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Fallo ao mover o arquivo de cuberta %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Formato de libro eliminado con éxito" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Libro eliminado con éxito" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "Vostede non ten permisos para borrar libros" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "editar metadatos" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s non é un número válido, saltando" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "O usuario non ten permisos para cargar formatos de ficheiro adicionais" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Fallo ao crear a ruta %(path)s (permiso denegado)" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Fallo ao gardar o arquivo %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Arquivo con formato %(ext)s engadido a %(book)s" @@ -635,179 +645,186 @@ msgstr "A configuración de Google Drive non se completou, intente desactivar e msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "O dominio Callback non se comprobou, siga os pasos para comprobalo na consola de desenvolvedor de Google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s formato non atopado para o id do libro: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s non atopado en Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s non atopado: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 -msgid "Send to E-Reader" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" msgstr "Enviar ao Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Este correo electrónico enviouse empregando Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Correo de proba de Calibre-Web" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Comprobar correo electrónico" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Primeiros pasos con Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Correo electrónico de rexistro para o usuario: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Convertir %(orig)s a %(format)s e enviar ao Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 -#, python-format -msgid "Send %(format)s to E-Reader" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Enviado %(format)s ao Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 -#, python-format -msgid "%(book)s send to E-Reader" +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" msgstr "Enviar ao Kindle %(book)s" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "O arquivo solicitado non pode lerse. Quizais existen problemas cos permisos?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "O estado de lectura non pode fixarse: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Fallo ao intentar borrar a carpeta do libro %(id)s, a ruta ten subcarpetas: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "O borrado do libro %(id)s fallou: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Borrando o libro %(id)s, a ruta de libro non é válida: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "O renomeado do título de: '%(src)s' a '%(dest)s' fallou co erro: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Ficheiro %(file)s non atopado en Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "O renomeado do título de: '%(src)s' a '%(dest)s' fallou co erro: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "Erro ao renomear o ficheiro na ruta: {}" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "A ruta %(path)s do libro non se atopou en Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "Atopada unha conta existente para ese enderezo de correo electrónico" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Este nome de usuario xa está en uso" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Enderezo de correo non válido" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "O módulo Python 'advocate' non está instalado pero se necesita para as cargas de cubertas" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Erro ao descargar a cuberta" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Erro no formato da cuberta" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "Non ten permiso para acceder a localhost ou á rede local para as cargas de cubertas" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Erro ao crear unha ruta para a cuberta" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "O arquivo de cuberta non é unha imaxe válida" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Soamente se admiten como cuberta os arquivos jpg/jpeg/png/webp/bmp" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "Contido do arquivo de cuberta non válido" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Soamente se admiten como cuberta os arquivos jpg/jpeg" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Non se atopa o arquivo binario de UnRar" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "Erro executando UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Descubrir" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Por favor, accede a calibre-web dende unha ubicación que non sexa localhost para obter unha api_endpoint válida para o teu dispositivo Kobo" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configuración de Kobo" @@ -816,9 +833,9 @@ msgstr "Configuración de Kobo" msgid "Register with %(provider)s" msgstr "Rexistrado con %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "Iniciou sesión como : '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -877,12 +894,13 @@ msgstr "Erro en Google Oauth, por favor volva a intentalo máis tarde." msgid "Google Oauth error: {}" msgstr "Erro Google Oauth {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Estrelas" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Inicio de sesión" @@ -898,149 +916,158 @@ msgstr "O token expirou" msgid "Success! Please return to your device" msgstr "Correcto! Por favor volte ao seu dispositivo" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Libros" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Mostrar libros recentes" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Libros populares" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Mostrar libros populares" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Libros descargados" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Mostrar libros descargados" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Libros mellor valorados" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Mostrar libros mellor valorados" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Libros lidos" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Mostrar lidos e non lidos" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Libros non lidos" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Mostrar non lidos" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Descubrir" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Mostrar libros ao chou" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Categorías" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Mostrar selección de categorías" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Series" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Mostrar selección de series" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Autores" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Mostrar selección de autores" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Editores" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Mostrar selección de editores" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Linguas" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Mostrar selección de linguas" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Valoracións" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Mostrar selección de valoracións" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Formatos de arquivo" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Mostrar selección de formatos de arquivo" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Libros arquivados" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Mostrar libros arquivados" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Lista de libros" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Mostrar lista de libros" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Buscar" @@ -1063,15 +1090,15 @@ msgid "Rating >= %(rating)s" msgstr "Valoración >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Estado de lectura = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Erro na busca de columnas personalizadas, por favor reinicia Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Búsqueda avanzada" @@ -1121,7 +1148,7 @@ msgstr "O libro eliminouse do andel: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "Síntoo, non ten permiso para quitar un libro do andel" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Crear un andel" @@ -1146,73 +1173,73 @@ msgstr "Andel eliminado con éxito" msgid "Change order of Shelf: '%(name)s'" msgstr "Cambiar a orde do andel: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "Síntoo, non ten permiso para crear un andel público" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Andel %(title)s creado" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Andel %(title)s cambiado" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Ocorreu un erro" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Xa existe un andel público co nome '%(title)s'." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Xa existe un andel privado co nome '%(title)s'." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Andel: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Erro ao abrir un andel. O andel non existe ou non se pode acceder" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Tarefas" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Esperando" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Fallou" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Comezado" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Rematado" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "Rematado" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "Cancelado" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Estado descoñecido" @@ -1245,146 +1272,185 @@ msgstr "Hai unha nova actualización dispoñible. Preme no botón de abaixo para msgid "No release information available" msgstr "Non hai información do lanzamento dispoñible" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Descubrir (Libros ao chou)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Libros populares (os máis descargados)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Libros descargados por %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autor/es: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Editor/es: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Series: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "Valoración: Ningunha" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Valoración: %(rating)s estrelas" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Formato do arquivo: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categoría: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Lingua: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Descargas" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Lista de valoracións" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Lista de formatos" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Libro posto na cola de envío a %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Configura primeiro os parámetros do servidor SMTP..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Libro posto na cola de envío a %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Oh, oh! Houbo un erro no envío do libro: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Por favor actualiza o teu perfil co enderezo de correo do teu kindle..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "O servidor de correo non está configurado, por favor, avisa ao teu administrador!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Rexistro" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "O servidor de correo non está configurado, por favor, avisa ao teu administrador!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "O seu correo electrónico non está permitido para rexistrarse" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Mandouse un correo electrónico de verificación á súa conta de correo." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Non se pode activar a autenticación LDAP" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "Iniciou sesión como : '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Fallback login como: '%(nickname)s', non se pode acceder ao servidor LDAP ou usuario descoñecido" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Non se puido entrar: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Usuario ou contrasinal no válido" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Unha nova contrasinal enviouse ao seu enderezo de correo electrónico" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Sucedeu un erro descoñecido. Por favor volva a intentalo máis tarde." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Por favor, introduce un usuario válido para restablecer a contrasinal" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Agora estás conectado como: '%(nickname)s'" +msgstr "Iniciou sesión como : '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Perfil de %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Perfil actualizado" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Atopada unha conta existente para ese enderezo de correo electrónico" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Non se atopou ningún arquivo gmail.json válido con información OAuth" +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "Enviar ao Kindle %(book)s" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1427,35 +1493,35 @@ msgstr "Convertir" msgid "Reconnecting Calibre database" msgstr "Reconectando a base de datos de Calibre" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "Correo electrónico" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "editar metadatos" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "Xeradas %(count)s miniaturas de cubertas" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "Miniaturas de cubertas" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "Xeradas {0} miniaturas de series" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "Limpando caché de miniaturas de cubertas" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Subir arquivo" @@ -1471,14 +1537,14 @@ msgstr "Nome de usuario" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Enderezo de correo electrónico" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Enviar ao enderezo de correo electrónico do Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Administrador" @@ -1488,8 +1554,8 @@ msgstr "Administrador" msgid "Password" msgstr "Contrasinal" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Descargar" @@ -1514,16 +1580,12 @@ msgstr "Borrar" msgid "Public Shelf" msgstr "Andel público" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Engadir novo usuario" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importar usuarios LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Axustes do servidor de correo electrónico" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1544,11 +1606,12 @@ msgstr "Login SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Dende o correo electrónico" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "Servizo de correo electrónico" #: cps/templates/admin.html:91 @@ -1620,102 +1683,104 @@ msgid "Scheduled Tasks" msgstr "Tarefas programadas" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "Hora de comezo das tarefas" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "Duración máxima das tarefas" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "Xerar as miniaturas das cubertas dos libros" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "Xerar as miniaturas das cubertas das series" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "Reconectar á librería de Calibre" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" msgstr "Refrescar a caché de miniaturas das cubertas" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Administración" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Descargar o paquete de depuración" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Ver arquivos de rexistro" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Reconectar á base de datos de Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Reiniciar" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Apagar" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "Información de versión" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versión" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detalles" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Versión actual" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Comprobar actualizacións" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Realizar actualización" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "De verdade queres reiniciar?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Vale" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Cancelar" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "De verdade quere deter?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Actualizando. Por favor, non recargue a páxina" @@ -1805,7 +1870,7 @@ msgid "Author" msgstr "Autor" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Descrición" @@ -1830,7 +1895,7 @@ msgstr "Borrar" msgid "Add Identifier" msgstr "Engadir identificador" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Etiquetas" @@ -1855,23 +1920,23 @@ msgid "Published Date" msgstr "Data de publicación" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Editor" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Lingua" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Sí" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Non" @@ -1888,8 +1953,8 @@ msgid "Fetch Metadata" msgstr "Obter metadatos" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1911,8 +1976,8 @@ msgstr "Premer na portada para cargar los metadatos no formulario" msgid "Loading..." msgstr "Cargando..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Pechar" @@ -2137,7 +2202,7 @@ msgid "Enable Uploads" msgstr "Permitir cargas" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "(Por favor asegúrese que os usuarios teñen permisos de carga)" #: cps/templates/config_edit.html:112 @@ -2153,7 +2218,7 @@ msgid "Enable Public Registration" msgstr "Permitir rexistro público" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Utilizar correo electrónico como nome de usuario" #: cps/templates/config_edit.html:132 @@ -2343,6 +2408,52 @@ msgstr "Ruta para Kepubify E-Book Converter" msgid "Location of Unrar binary" msgstr "Localización do binario de Unrar" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Axustes OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Restablecer contrasinal de usuario" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Ver configuración" @@ -2355,7 +2466,7 @@ msgstr "Número de libros aleatorios a mostrar" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Número de autores para mostrar antes de agochar (0 = desactivar o agochamento)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Tema" @@ -2444,80 +2555,84 @@ msgstr "Engadir etiquetas Permitidas/denegados" msgid "Add Allowed/Denied custom column values" msgstr "Engadir valores personalizados Permitidos/denegados" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Ler no navegador" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Escoitar no navegador" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "Libro %(index)s de %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publicado" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Marcar como non lido" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Marcar como lido" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Lido" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Restaurar dende o arquivo" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Engadir a arquivo" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Arquivado" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Descrición:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Engadir ao andel" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Público)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Editar metadatos" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Escolle tipo de servidor" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Usar conta de correo electrónico estándar" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Verificación de conta Gmail con OAuth2" +#, fuzzy +msgid "Gmail Account" +msgstr "Escolle tipo de servidor" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Configurar conta de Gmail como servidor de correo" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2540,10 +2655,11 @@ msgid "Attachment Size Limit" msgstr "Tamaño límite do arquivo achegado" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Gardar e enviar un correo electrónico de proba" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Voltar" @@ -2569,13 +2685,13 @@ msgstr "Introducir nome de dominio" msgid "Denied Domains (Blacklist)" msgstr "Dominios prohibidos (Blaclist)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Seguinte" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Abre o arquivo .kobo/Kobo eReader.conf nun editor de texto e engade (ou edita):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Abre o arquivo .kobo/Kobo/Kobo eReader.conf nun editor de texto e engade (ou edita):" #: cps/templates/generate_kobo_auth_url.html:11 msgid "Kobo Token:" @@ -2585,19 +2701,19 @@ msgstr "Token de sincronización de Kobo" msgid "List" msgstr "Lista" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "A instancia de Calibre-Web non está configurada, por favor contacta co teu administrador" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Crear una incidencia" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Voltar ao inicio" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "Pechar sesión" @@ -2627,80 +2743,80 @@ msgstr "Ordear cara arriba segundo ao índice de serie" msgid "Sort descending according to series index" msgstr "Ordear cara abaixo segundo ao índice de serie" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Comezar" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Libros alfabéticos" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Libros ordeados alfabéticamente" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Publicacións populares do catálogo baseadas nas descargas." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Publicacións populares do catálogo baseadas na valoración." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Libros engadidos recentemente" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Últimos libros" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Libros ao chou" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Libros ordeados por autor" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Libros ordeados por editor" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Libros ordeados por categorías" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Libros ordeados por series" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Libros ordeados por lingua" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Libros ordeados por valoración" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Libros ordeados por formato de arquivo" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Andeis" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Libros organizados en andeis" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Inicio" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Alternar navegación" @@ -2708,48 +2824,48 @@ msgstr "Alternar navegación" msgid "Search Library" msgstr "Buscar na librería" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Cargando..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Erro" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Carga feita, procesando, por favor agarde..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Axustes" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Conta" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Pechar sesión" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Cargando..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Erro" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Carga feita, procesando, por favor agarde..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Axustes" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Por favor, non actualice a páxina" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Navegar" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Acerca de" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Previo" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Detalles do libro" @@ -2765,7 +2881,7 @@ msgstr "Lembrarme" msgid "Forgot Password?" msgstr "Esqueceu a contrasinal?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Iniciar sesión cun enlace máxico" @@ -2873,135 +2989,160 @@ msgstr "Catálogo de libros electrónicos de Calibre-Web" msgid "epub Reader" msgstr "Lector epub" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Claro" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Oscuro" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "Sepia" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 msgid "Black" msgstr "Negro" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Refluxo do texto cando as barras laterais están abertas." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "Lector de Cómics" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Atallos de teclado" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Páxina anterior" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Páxina seguinte" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Escalar ao mellor" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Escalar ao ancho" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Escalar ao alto" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Escalado nativo" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Xirar cara a dereita" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Xirar cara a esquerda" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Voltear a imaxe" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Páxina de administración" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Escalar" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Mellor" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Ancho" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Alto" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Nativo" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Rotar" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Voltear" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Horizontal" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Vertical" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Dirección" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "De esquerda a dereita" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "De dereita a esquerda" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Voltar ao comezo" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Lembrar posición" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Barra de desprazamento" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Mostrar" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Agochar" @@ -3009,7 +3150,7 @@ msgstr "Agochar" msgid "DJVU Reader" msgstr "Lector DJVU" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "Lector PDF" @@ -3026,7 +3167,7 @@ msgid "Choose a username" msgstr "Escolla un nome de usuario" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "O teu enderezo de correo" #: cps/templates/remote_login.html:5 @@ -3045,10 +3186,6 @@ msgstr "Unha vez verificado, iniciará sesión automáticamente neste dispositiv msgid "This verification link will expire in 10 minutes." msgstr "O enlace de verificación caducará despois de 10 minutos." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "Xerar miniaturas de cubertas de libros" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "Xerar miniaturas de cubertas de series" @@ -3073,43 +3210,51 @@ msgstr "Data de publicación dende" msgid "Published Date To" msgstr "Data de publicación ata" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Excluir etiquetas" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Excluir series" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "Excluir andeis" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Excluir linguas" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Extensións" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Excluir extensións" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Valoración superior a" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Valoración inferior a" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "De:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Para:" @@ -3201,10 +3346,6 @@ msgstr "Progreso" msgid "Run Time" msgstr "Tempo de execución" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Hora de inicio" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "Accións" @@ -3278,15 +3419,18 @@ msgid "Enter Username" msgstr "Introduce o nome do usuario" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "Introduce o enderezo de correo electrónico" +#, fuzzy +msgid "Enter Email" +msgstr "Comprobar correo electrónico" #: cps/templates/user_table.html:136 -msgid "Enter E-Reader E-mail Address" -msgstr "Introduce o enderezo de correo electrónico Kindle" +#, fuzzy +msgid "Enter eReader Email" +msgstr "Enviar ao enderezo de correo electrónico do Kindle" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" +#, fuzzy +msgid "eReader Email" msgstr "Comprobar o correo electrónico" #: cps/templates/user_table.html:137 @@ -3346,10 +3490,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "sincronizar andeis seleccionados con Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "Mostrar selección lidos/non lidos" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Mostrar libros ao chou" - diff --git a/cps/translations/hu/LC_MESSAGES/messages.mo b/cps/translations/hu/LC_MESSAGES/messages.mo index 11e912ec..1efa59e8 100644 Binary files a/cps/translations/hu/LC_MESSAGES/messages.mo and b/cps/translations/hu/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/hu/LC_MESSAGES/messages.po b/cps/translations/hu/LC_MESSAGES/messages.po index 1e6b9046..e72070e4 100644 --- a/cps/translations/hu/LC_MESSAGES/messages.po +++ b/cps/translations/hu/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2019-04-06 23:36+0200\n" "Last-Translator: \n" "Language: hu\n" @@ -16,495 +16,504 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statisztika" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "A kiszolgáló újraindult, tölts be újra az oldalt!" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "A kiszolgáló leállítása folyamatban, zárd be ezt az ablakot" -#: cps/admin.py:156 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:159 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:169 -#, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "A könyv sikeresen küldésre lett jelölve a következő címre: %(kindlemail)s" +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Ismeretlen" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Rendszergazda oldala" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Alapvető beállítások" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Felhasználói felület beállításai" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Rendszergazda felhasználó" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Mindent mutass" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "A Calibre-Web konfigurációja frissítve." -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Valóban törölni akarod a polcot?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Valóban törölni akarod a polcot?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Valóban törölni akarod a polcot?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Valóban törölni akarod a polcot?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Valóban le akarod állítani a Calibre-Web-et?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Új felhasználó hozzáadása" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "SMTP beállítások változtatása" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Hiba történt a teszt levél küldése során: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Az e-mail kiszolgáló beállításai frissítve." -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Ismeretlen hiba történt. Próbáld újra később!" -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr " A felhasználó szerkesztése: %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "A(z) %(user)s felhasználó jelszavának alaphelyzetbe állítása" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Először be kell állítani az SMTP levelező beállításokat..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Frissítési csomag kérése" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Frissítési csomag letöltése" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Frissítési csomag kitömörítése" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Fájlok cserélése" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Adatbázis kapcsolatok lezárva" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Szerver leállítása" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "A frissítés települt, kattints az OK-ra és újra tölt az oldal" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "A frissítés nem sikerült:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP hiba" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Kapcsolódási hiba" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Időtúllépés a kapcsolódás során" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Általános hiba" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Az e-mail kiszolgáló beállításai frissítve." -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Funkciók beállítása" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Az összes mezőt ki kell tölteni!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "Az e-mail tartománya nem érvényes." -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Új felhasználó hozzáadása" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "A következő felhasználó létrehozva: %(user)s" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Már létezik felhasználó ehhez az e-mail címhez vagy felhasználói névhez." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "A felhasználó törölve: %(nick)s" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "A felhasználó frissítve: %(nick)s" @@ -517,122 +526,122 @@ msgstr "nincs telepítve" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Nincs" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Hiba történt az e-könyv megnyitásakor. A fájl nem létezik vagy nem érhető el:" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "A metaadatok sikeresen frissültek" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Az átalakításhoz hiányzik a forrás- vagy a célformátum!" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "A könyv sikeresen átalakításra lett jelölve a következő formátumra: %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Hiba történt a könyv átalakításakor: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "A(z) %(langname)s nem érvényes nyelv" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "A(z) \"%(ext)s\" kiterjesztésű fájlok feltöltése nincs engedélyezve ezen a szerveren." -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "A feltöltendő fájlnak kiterjesztéssel kell rendelkeznie!" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "Metaadatok szerkesztése" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Nem sikerült létrehozni az elérési utat (engedély megtagadva): %(path)s." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Nem sikerült elmenteni a %(file)s fájlt." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "A(z) %(ext)s fájlformátum hozzáadva a könyvhez: %(book)s." @@ -645,181 +654,186 @@ msgstr "A Google Drive beállítása nem fejeződött be, próbáld kikapcsolni msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "A visszahívási tartomány nem ellenőrzött, kövesd az alábbi lépéseket a tartomány ellenőrzéséhez a Google Developer Console-ban:" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "A(z) %(format)s formátum nem található a következő könyvhöz: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s nem található a Google Drive-on: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s nem található: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Küldés Kindle-re" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Ez az e-mail a Calibre-Web-en keresztül lett küldve." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web teszt e-mail" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Teszt e-mail" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Kezdő lépések a Calibre-Web-bel" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Regisztrációs e-mail a következő felhasználóhoz: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "%(orig)s konvertálása %(format)s-ra és küldés Kindle-re" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "%(format)s küldése Kindle-re" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Küldés Kindle-re" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "A kért fájl nem olvasható. Esetleg jogosultsági probléma lenne?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "A cím átnevezése \"%(src)s\"-ról \"%(dest)s\"-ra nem sikerült a következő hiba miatt: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "A \"%(file)s\" fájl nem található a Google Drive-on" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "A cím átnevezése \"%(src)s\"-ról \"%(dest)s\"-ra nem sikerült a következő hiba miatt: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "A könyv elérési útja (\"%(path)s\") nem található a Google Drive-on" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Már létezik felhasználó ehhez az e-mail címhez." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Felfedezés" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -828,9 +842,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "Be vagy jelentkezve mint: %(nickname)s" #: cps/oauth_bb.py:148 @@ -889,12 +903,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Belépés" @@ -910,149 +925,158 @@ msgstr "A token érvényessége lejárt." msgid "Success! Please return to your device" msgstr "Sikerült! Újra használható az eszköz." -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Legutóbbi könyvek mutatása" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Kelendő könyvek" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Kelendő könyvek mutatása" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Legjobb könyvek" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Legjobbra értékelt könyvek mutatása" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Olvasott könyvek" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Mutassa az olvasva/olvasatlan állapotot" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Olvasatlan könyvek" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Felfedezés" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Mutass könyveket találomra" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Címkék" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Címke választó mutatása" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Sorozatok" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Sorozat választó mutatása" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Szerzők" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Szerző választó mutatása" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Kiadók" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Kiadó választó mutatása" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Nyelvek" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Nyelv választó mutatása" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" -msgstr "" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" +msgstr "Sorozat választó mutatása" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" -msgstr "" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" +msgstr "Sorozat választó mutatása" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" -msgstr "" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Legutóbbi könyvek mutatása" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Keresés" @@ -1076,14 +1100,14 @@ msgstr "Értékelés <= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Részletes keresés" @@ -1134,7 +1158,7 @@ msgstr "A könyv el lett távolítva a polcról: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Polc készítése" @@ -1161,73 +1185,73 @@ msgstr "A metaadatok sikeresen frissültek" msgid "Change order of Shelf: '%(name)s'" msgstr "A következő polc átrendezése: %(name)s" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "A következő polc létre lett hozva: %(title)s" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "A következő polc megváltoztatva: %(title)s" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Hiba történt" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Polc: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Hiba a polc megnyitásakor. A polc nem létezik vagy nem elérhető." -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Feladatok" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Várakozás" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Nem sikerült" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Elindítva" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Végrehajtva" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Ismeretlen állapot" @@ -1260,146 +1284,184 @@ msgstr "Új frissítés érhető el. Kattints az alábbi gombra a frissítéshez msgid "No release information available" msgstr "Nincs információ a kiadásról." -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Felfedezés (könyvek találomra)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Kelendő könyvek (legtöbbet letöltöttek)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Kiadó: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Sorozat: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Címke: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Nyelv: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Letöltések" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "A könyv sikeresen küldésre lett jelölve a következő címre: %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Először be kell állítani az SMTP levelező beállításokat..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "A könyv sikeresen küldésre lett jelölve a következő címre: %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Hiba történt a könyv küldésekor: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Először be kell állítani a kindle e-mail címet..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Regisztrálás" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Nem engedélyezett a megadott e-mail cím bejegyzése" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Jóváhagyó levél elküldve az email címedre." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "Be vagy jelentkezve mint: %(nickname)s" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Rossz felhasználó név vagy jelszó!" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Ismeretlen hiba történt. Próbáld újra később!" + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" -msgstr "" +msgstr "Rossz felhasználó név vagy jelszó!" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "" +msgstr "Be vagy jelentkezve mint: %(nickname)s" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s profilja" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "A profil frissítve." +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Már létezik felhasználó ehhez az e-mail címhez." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Küldés Kindle-re" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1442,35 +1504,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "Metaadatok szerkesztése" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Feltöltés" @@ -1486,15 +1548,15 @@ msgstr "Felhasználói név" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "E-mail" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Rendszergazda" @@ -1504,8 +1566,8 @@ msgstr "Rendszergazda" msgid "Password" msgstr "Jelszó" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Letöltés" @@ -1530,16 +1592,12 @@ msgstr "Törlés" msgid "Public Shelf" msgstr "" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "SMTP e-mail kiszolgáló beállítások" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1560,11 +1618,11 @@ msgstr "SMTP felhasználó" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Küldő e-mail cím" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1637,102 +1695,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Adminisztráció" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Újracsatlakozás a Calibre adatbázishoz" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "A Calibre adatbázis újraindítása" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "A Calibre adatbázis leállítása" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Verzió" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Részletek" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Jelenlegi verzió" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Frissítés keresése" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Frissítés elkezdése" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Valóban újra akarod indítani a Calibre-Web-et?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Valóban le akarod állítani a Calibre-Web-et?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Frissítés folyamatban, ne töltsd újra az oldalt" @@ -1822,7 +1882,7 @@ msgid "Author" msgstr "Szerző" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Leírás" @@ -1847,7 +1907,7 @@ msgstr "" msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Címkék" @@ -1872,23 +1932,23 @@ msgid "Published Date" msgstr "Kiadás éve" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Kiadó" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Nyelv" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Igen" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Nem" @@ -1905,8 +1965,8 @@ msgid "Fetch Metadata" msgstr "Metaadatok beszerzése" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1929,8 +1989,8 @@ msgstr "Kattints a borítóra a metadatok betöltésére" msgid "Loading..." msgstr "Betöltés..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Bezárás" @@ -2157,7 +2217,7 @@ msgid "Enable Uploads" msgstr "Feltöltés engedélyezése" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2173,7 +2233,7 @@ msgid "Enable Public Registration" msgstr "Nyilvános regisztráció engedélyezése" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2363,6 +2423,51 @@ msgstr "" msgid "Location of Unrar binary" msgstr "Az Unrar futtatási állományának helye" +#: cps/templates/config_edit.html:361 +msgid "Security Settings" +msgstr "" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Felhasználó jelszavának alaphelyzetbe állítása" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Általános beállítások" @@ -2375,7 +2480,7 @@ msgstr "Találomra mutatott könyvek száma" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Mutatott szerzők száma (0=elrejtés kikapcsolása)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Téma" @@ -2466,79 +2571,82 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Olvasás böngészőben" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Legyen olvasatlan" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Legyen olvasott" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Olvasva" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Ismertető:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Hozzáadás polchoz" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Metaadatok szerkesztése" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "" +#, fuzzy +msgid "Gmail Account" +msgstr "Felhasználói fiók" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2562,10 +2670,11 @@ msgid "Attachment Size Limit" msgstr "" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Beállítások mentése és teszt e-mail küldése" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Vissza" @@ -2591,12 +2700,12 @@ msgstr "Tartomány megadása" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Következő" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2607,19 +2716,19 @@ msgstr "" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Vissza a kezdőlapra" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2649,80 +2758,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Kezdés" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Ebből a katalógusból származó népszerű kiadványok letöltések alapján." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Ebből a katalógusból származó népszerű kiadványok értékelések alapján." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "A legfrissebb könyvek" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Könyvek találomra" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Könyvek szerző szerint rendezve" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Könyvek kiadók szerint rendezve" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Könyvek címke szerint rendezve" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Könyvek sorozat szerint rendezve" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Kezdőlap" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Navigáció átkapcsolása" @@ -2730,48 +2839,48 @@ msgstr "Navigáció átkapcsolása" msgid "Search Library" msgstr "" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Feltöltés..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Hiba" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Feltöltés kész, feldolgozás alatt, kérlek várj..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Beállítások" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Felhasználói fiók" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Kilépés" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Feltöltés..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Hiba" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Feltöltés kész, feldolgozás alatt, kérlek várj..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Beállítások" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Böngészés" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Névjegy" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Előző" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Könyv részletei" @@ -2787,7 +2896,7 @@ msgstr "Emlékezz rám" msgid "Forgot Password?" msgstr "" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Belépés varázshivatkozással" @@ -2896,136 +3005,161 @@ msgstr "Calibre-Web e-könyv katalógus" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Világos" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Sötét" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Vissza" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Szöveg újratördelése amikor az oldalsávok nyitva vannak" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Gyorsbillentyűk" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Előző oldal" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Következő oldal" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Méretezés a legjobbra" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Méretezés a szélességre" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Méretezés a magasságra" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Méretezés a natívra" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Forgatás balra" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Forgatás jobbra" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Kép tükrözése" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Rendszergazda oldala" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Méretezés" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Legjobb" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Szélesség" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Magasság" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Natív" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Forgatás" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Tökrözés" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Vízszintes" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Függőleges" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3033,7 +3167,7 @@ msgstr "" msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -3051,7 +3185,7 @@ msgid "Choose a username" msgstr "Válassz egy felhasználónevet" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Az e-mail címed" #: cps/templates/remote_login.html:5 @@ -3070,10 +3204,6 @@ msgstr "Az első belépés után automatikusan be leszel léptetve ezen az eszk msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3098,44 +3228,52 @@ msgstr "Kiadás éve ettől: " msgid "Published Date To" msgstr "Kiadás éve eddig: " -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Cimkék kizárása" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Sorozatok kizárása" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Sorozatok kizárása" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Nyelvek kizárása" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Értékelés nagyob mint" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Értékelés kisebb mint" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3227,10 +3365,6 @@ msgstr "Állapot" msgid "Run Time" msgstr "Futásidő" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Indítás ideje" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3307,17 +3441,17 @@ msgstr "Válassz egy felhasználónevet" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Az e-mail címed" +msgid "Enter Email" +msgstr "Teszt e-mail" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Teszt e-mail" #: cps/templates/user_table.html:137 @@ -3381,10 +3515,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Sorozat választó mutatása" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Könyvek találomra mutatása" - diff --git a/cps/translations/id/LC_MESSAGES/messages.mo b/cps/translations/id/LC_MESSAGES/messages.mo new file mode 100644 index 00000000..19a83560 Binary files /dev/null and b/cps/translations/id/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/id/LC_MESSAGES/messages.po b/cps/translations/id/LC_MESSAGES/messages.po new file mode 100644 index 00000000..be23dd39 --- /dev/null +++ b/cps/translations/id/LC_MESSAGES/messages.po @@ -0,0 +1,3499 @@ +# Indonesian translations for Calibre-Web. +# Copyright (C) 2017 Calibre-Web +# This file is distributed under the same license as the Calibre-Web +# project. +# FIRST AUTHOR Arief Hidayat, 2021-2023. +msgid "" +msgstr "" +"Project-Id-Version: Calibre-Web\n" +"Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" +"PO-Revision-Date: 2023-01-21 10:00+0700\n" +"Last-Translator: Arief Hidayat\n" +"Language: id\n" +"Language-Team: Arief Hidayat \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.13.1\n" + +#: cps/about.py:84 +msgid "Statistics" +msgstr "Statistik" + +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." +msgstr "Server dimulai ulang, harap muat ulang halaman" + +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." +msgstr "Mematikan server, silakan tutup jendela" + +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 +msgid "Unknown command" +msgstr "Perintah tidak diketahui" + +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Uji email diantrean untuk dikirim ke %(email), harap periksa Tasks untuk hasilnya" + +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 +msgid "Unknown" +msgstr "Tidak diketahui" + +#: cps/admin.py:231 +msgid "Admin page" +msgstr "Halaman Admin" + +#: cps/admin.py:251 +msgid "Basic Configuration" +msgstr "Pengaturan Dasar" + +#: cps/admin.py:289 +msgid "UI Configuration" +msgstr "Pengaturan Antarmuka" + +#: cps/admin.py:323 cps/templates/admin.html:51 +msgid "Edit Users" +msgstr "Edit pengguna" + +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 +#: cps/templates/list.html:13 +msgid "All" +msgstr "Semua" + +#: cps/admin.py:394 cps/admin.py:1405 +msgid "User not found" +msgstr "Pengguna tidak ditemukan" + +#: cps/admin.py:408 +msgid "{} users deleted successfully" +msgstr "{} pengguna berhasil dihapus" + +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 +#: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 +msgid "Show All" +msgstr "Tampilkan semua" + +#: cps/admin.py:452 cps/admin.py:458 +msgid "Malformed request" +msgstr "Permintaan salah" + +#: cps/admin.py:470 cps/admin.py:2023 +msgid "Guest Name can't be changed" +msgstr "Nama Tamu tidak dapat diganti" + +#: cps/admin.py:482 +msgid "Guest can't have this role" +msgstr "Tamu tidak dapat memiliki peran ini" + +#: cps/admin.py:494 cps/admin.py:1977 +msgid "No admin user remaining, can't remove admin role" +msgstr "Tidak ada pengguna admin yang tersisa, tidak dapat menghapus peran admin" + +#: cps/admin.py:498 cps/admin.py:512 +msgid "Value has to be true or false" +msgstr "Nilai harus benar atau salah" + +#: cps/admin.py:500 +msgid "Invalid role" +msgstr "Peran tidak valid" + +#: cps/admin.py:504 +msgid "Guest can't have this view" +msgstr " Tamu tidak dapat mengakses tampilan ini" + +#: cps/admin.py:514 +msgid "Invalid view" +msgstr " Tampilan tidak valid" + +#: cps/admin.py:517 +msgid "Guest's Locale is determined automatically and can't be set" +msgstr "Lokal Tamu ditentukan secara otomatis dan tidak dapat disetel" + +#: cps/admin.py:521 +msgid "No Valid Locale Given" +msgstr "Tidak Ada Lokal yang Valid Diberikan" + +#: cps/admin.py:532 +msgid "No Valid Book Language Given" +msgstr "Tidak Ada Bahasa Buku yang Valid Diberikan" + +#: cps/admin.py:534 cps/editbooks.py:453 +msgid "Parameter not found" +msgstr "Parameter tidak ditemukan" + +#: cps/admin.py:571 +msgid "Invalid Read Column" +msgstr "Kolom Baca Tidak Valid" + +#: cps/admin.py:577 +msgid "Invalid Restricted Column" +msgstr "Kolom Dibatasi Tidak Valid" + +#: cps/admin.py:597 cps/admin.py:1848 +msgid "Calibre-Web configuration updated" +msgstr "Pengaturan Calibre-Web telah diperbarui" + +#: cps/admin.py:609 +msgid "Do you really want to delete the Kobo Token?" +msgstr "Apakah Anda yakin ingin menghapus Token Kobo?" + +#: cps/admin.py:611 +msgid "Do you really want to delete this domain?" +msgstr "Apakah Anda yakin ingin menghapus domain ini?" + +#: cps/admin.py:613 +msgid "Do you really want to delete this user?" +msgstr "Apakah Anda yakin ingin menghapus pengguna ini?" + +#: cps/admin.py:615 +msgid "Are you sure you want to delete this shelf?" +msgstr "Apakah Anda yakin ingin menghapus rak ini?" + +#: cps/admin.py:617 +msgid "Are you sure you want to change locales of selected user(s)?" +msgstr "Apakah Anda yakin ingin merubah lokalisasi untuk pengguna yang dipilih?" + +#: cps/admin.py:619 +msgid "Are you sure you want to change visible book languages for selected user(s)?" +msgstr "Apakah Anda yakin ingin merubah bahasa buku yang terlihat untuk pengguna yang dipilih?" + +#: cps/admin.py:621 +msgid "Are you sure you want to change the selected role for the selected user(s)?" +msgstr "Apakah Anda yakin ingin merubah peran untuk pengguna yang dipilih?" + +#: cps/admin.py:623 +msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" +msgstr "Apakah Anda yakin ingin mengubah batasan yang dipilih untuk pengguna yang dipilih?" + +#: cps/admin.py:625 +msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" +msgstr "Apakah Anda yakin ingin merubah batasan visibilitas untuk pengguna yang dipilih?" + +#: cps/admin.py:628 +msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" +msgstr "Apakah Anda yakin ingin mengubah perilaku sinkronisasi rak untuk pengguna yang dipilih?" + +#: cps/admin.py:630 +msgid "Are you sure you want to change Calibre library location?" +msgstr "Apakah Anda yakin ingin mengubah lokasi perpustakaan Calibre?" + +#: cps/admin.py:632 +msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" +msgstr "Calibre-Web akan mencari Sampul yang diperbarui dan memperbarui Thumbnail Sampul, ini mungkin memakan waktu cukup lama?" + +#: cps/admin.py:635 +msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +msgstr "Apakah Anda yakin ingin menghapus database sinkronisasi Calibre-Web untuk memaksakan sinkronisasi penuh dengan Kobo Reader Anda?" + +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 +#: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 +#: cps/templates/user_table.html:58 +msgid "Deny" +msgstr "Tolak" + +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 +#: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 +#: cps/templates/user_table.html:61 +msgid "Allow" +msgstr "Izinkan" + +#: cps/admin.py:921 +msgid "{} sync entries deleted" +msgstr "{} entri sinkronisasi dihapus" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Tag tidak ditemukan" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Tindakan Tidak Valid" + +#: cps/admin.py:1111 +msgid "client_secrets.json Is Not Configured For Web Application" +msgstr "client_secrets.json Tidak Diatur Untuk Aplikasi Web" + +#: cps/admin.py:1156 +msgid "Logfile Location is not Valid, Please Enter Correct Path" +msgstr "Lokasi Logfile tidak Valid, Harap Masukkan Jalur yang Benar" + +#: cps/admin.py:1162 +msgid "Access Logfile Location is not Valid, Please Enter Correct Path" +msgstr "Akses Logfile Catatan tidak Valid, Harap Masukkan Jalur yang Benar" + +#: cps/admin.py:1196 +msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" +msgstr "Harap Masukkan Provider LDAP, Port, DN dan User Obect Identifier" + +#: cps/admin.py:1202 +msgid "Please Enter a LDAP Service Account and Password" +msgstr "Masukkan Akun Layanan LDAP dan Kata Sandi" + +#: cps/admin.py:1205 +msgid "Please Enter a LDAP Service Account" +msgstr "Masukkan Akun Layanan LDAP" + +#: cps/admin.py:1210 +#, python-format +msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" +msgstr "Filter Objek Grup LDAP Harus Memiliki Satu Pengidentifikasi Format \"%s\"" + +#: cps/admin.py:1212 +msgid "LDAP Group Object Filter Has Unmatched Parenthesis" +msgstr "Filter Objek Grup LDAP Memiliki Tanda kurung yang Tak Berpasangan" + +#: cps/admin.py:1216 +#, python-format +msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" +msgstr "Filter Objek Pengguna LDAP harus Memiliki Satu Pengidentifikasi Format \"%s\"" + +#: cps/admin.py:1218 +msgid "LDAP User Object Filter Has Unmatched Parenthesis" +msgstr "Filter Objek Pengguna LDAP Memiliki Tanda kurung yang Tak Berpasangan" + +#: cps/admin.py:1225 +#, python-format +msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" +msgstr "Filter Pengguna Anggota LDAP harus Memiliki Satu Pengenal Format \"%s\"" + +#: cps/admin.py:1227 +msgid "LDAP Member User Filter Has Unmatched Parenthesis" +msgstr "Filter Pengguna Anggota LDAP Memiliki Tanda Kurung yang Tak Berpasangan" + +#: cps/admin.py:1234 +msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" +msgstr "Lokasi LDAP Sertifikat CA, Sertifikat, atau Kunci tidak Valid, Harap Masukkan Jalur yang Benar " + +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Tambah Pengguna Baru" + +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Edit Pengaturan Server Email" + +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" + +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 +#, python-format +msgid "Oops! Database Error: %(error)s." +msgstr "Kesalahan basis data: %(error)s" + +#: cps/admin.py:1323 +#, python-format +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +msgstr "Uji email diantrean untuk dikirim ke %(email), harap periksa Tasks untuk hasilnya" + +#: cps/admin.py:1326 +#, python-format +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "Terjadi kesalahan saat mengirim email tes: %(res)s" + +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "Harap atur alamat email Anda terlebih dahulu.." + +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Setelan server email diperbarui" + +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "Edit Pengaturan Tugas Terjadwal" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "Waktu mulai tidak valid untuk tugas yang ditentukan" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "Durasi tidak valid untuk tugas yang ditentukan" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Pengaturan tugas terjadwal diperbarui" + +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." +msgstr "Terjadi kesalahan yang tidak diketahui. Coba lagi nanti." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "Pengaturan DB tidak dapat ditulisi" + +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "Edit pengguna %(nick)s" + +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" +msgstr "Kata sandi untuk pengaturan ulang pengguna %(user) " + +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." +msgstr "Harap atur pengaturan email SMTP terlebih dahulu..." + +#: cps/admin.py:1453 +msgid "Logfile viewer" +msgstr "Penampil berkas log" + +#: cps/admin.py:1519 +msgid "Requesting update package" +msgstr "Meminta paket pembaruan" + +#: cps/admin.py:1520 +msgid "Downloading update package" +msgstr "Mengunduh paket pembaruan" + +#: cps/admin.py:1521 +msgid "Unzipping update package" +msgstr "Mengekstrak paket pembaruan" + +#: cps/admin.py:1522 +msgid "Replacing files" +msgstr "Mengganti berkas" + +#: cps/admin.py:1523 +msgid "Database connections are closed" +msgstr "Koneksi basis data ditutup" + +#: cps/admin.py:1524 +msgid "Stopping server" +msgstr "Menghentikan server" + +#: cps/admin.py:1525 +msgid "Update finished, please press okay and reload page" +msgstr "Pembaruan selesai, silakan tekan OK dan muat ulang halaman" + +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 +msgid "Update failed:" +msgstr "Pembaruan gagal:" + +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +msgid "HTTP Error" +msgstr "Kesalahan HTTP" + +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 +msgid "Connection error" +msgstr "Kesalahan koneksi" + +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 +msgid "Timeout while establishing connection" +msgstr "Batas waktu saat membuat koneksi" + +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 +msgid "General error" +msgstr "Kesalahan umum" + +#: cps/admin.py:1530 +msgid "Update file could not be saved in temp dir" +msgstr "Berkas pembaruan tidak dapat disimpan di direktori temp" + +#: cps/admin.py:1531 +msgid "Files could not be replaced during update" +msgstr "Berkas tidak dapat diganti selama pembaruan" + +#: cps/admin.py:1555 +msgid "Failed to extract at least One LDAP User" +msgstr "Gagal mengekstrak setidaknya Satu Pengguna LDAP" + +#: cps/admin.py:1600 +msgid "Failed to Create at Least One LDAP User" +msgstr "Gagal Membuat Sedikitnya Satu Pengguna LDAP" + +#: cps/admin.py:1613 +#, python-format +msgid "Error: %(ldaperror)s" +msgstr "Kesalahan: %(ldaperror)s" + +#: cps/admin.py:1617 +msgid "Error: No user returned in response of LDAP server" +msgstr "Error: Tidak ada pengguna yang dikembalikan sebagai respons dari server LDAP" + +#: cps/admin.py:1650 +msgid "At Least One LDAP User Not Found in Database" +msgstr "Setidaknya Satu Pengguna LDAP Tidak Ditemukan di Basis Data" + +#: cps/admin.py:1652 +msgid "{} User Successfully Imported" +msgstr "{} Pengguna Berhasil Diimpor" + +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "Lokasi Basis Data tidak Valid, Harap Masukkan Jalur yang Benar" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Basis Data tidak dapat ditulisi" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "Lokasi keyfile tidak Valid, Harap Masukkan Jalur yang Benar " + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "Lokasi Sertifikat tidak Valid, Harap Masukkan Jalur yang Benar " + +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "Pengaturan Basis Data diperbarui" + +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Pengaturan Basis Data" + +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Harap masukkan seluruh isian!" + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "Email bukan dari domain yang valid" + +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Tambahkan pengguna baru" + +#: cps/admin.py:1920 +#, python-format +msgid "User '%(user)s' created" +msgstr "Pengguna '%(user)s' telah dibuat" + +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "Ditemukan akun yang ada untuk alamat email atau nama ini." + +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Pengguna '%(nick)s' telah dihapus" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Tidak dapat menghapus Pengguna Tamu" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "Tidak ada pengguna admin tersisa, tidak dapat menghapus pengguna" + +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "Alamat email tidak boleh kosong dan harus berupa email yang valid" + +#: cps/admin.py:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Pengguna '%(nick)s' diperbarui" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "belum dipasang" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Izin eksekusi hilang" + +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 +#, python-format +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "Kolom Kustom No.%(column)d tidak ada di basis data kaliber" + +#: cps/db.py:993 cps/templates/config_edit.html:204 +#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 +msgid "None" +msgstr "Tidak ada" + +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" +msgstr "Ups! Judul buku yang dipilih tidak tersedia. Berkas tidak ada atau tidak dapat diakses" + +#: cps/editbooks.py:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" +msgstr "Pengguna tidak berhak mengganti sampul" + +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +msgstr "IDは大文字小文字を区別しません。元のIDを上書きします" + +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Metadata berhasil diperbarui" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" +msgstr "Kesalahan pengeditan buku: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Berkas %(file)s telah diunggah" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Format sumber atau tujuan untuk konversi tidak ada" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "Buku berhasil diantrekan untuk dikonversi ke %(book_format)s" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "Terjadi kesalahan saat mengonversi buku ini: %(res)s" + +#: cps/editbooks.py:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " +msgstr "Buku yang diunggah mungkin ada di perpustakaan, pertimbangkan untuk mengubahnya sebelum mengunggah yang baru: " + +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "'%(langname)s' bukan bahasa yang valid" + +#: cps/editbooks.py:741 cps/editbooks.py:1179 +#, python-format +msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" +msgstr "Ekstensi berkas '%(ext)s' tidak diizinkan untuk diunggah ke server ini" + +#: cps/editbooks.py:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "Berkas yang akan diunggah harus memiliki ekstensi" + +#: cps/editbooks.py:753 +#, python-format +msgid "File %(filename)s could not saved to temp dir" +msgstr "Berkas %(filename)s tidak dapat disimpan ke direktori temp" + +#: cps/editbooks.py:773 +#, python-format +msgid "Failed to Move Cover File %(file)s: %(error)s" +msgstr "Gagal Memindahkan Berkas Sampul %(file)s: %(error)s" + +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Format Buku Berhasil Dihapus" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Buku Berhasil Dihapus" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "Anda tidak memiliki izin untuk menghapus buku" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "edit metadata" + +#: cps/editbooks.py:992 +#, python-format +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s dilewati karena bukan angka yang valid" + +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "Pengguna tidak memiliki izin untuk mengunggah format berkas tambahan" + +#: cps/editbooks.py:1195 +#, python-format +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Gagal membuat jalur %(path)s (Izin ditolak)." + +#: cps/editbooks.py:1200 +#, python-format +msgid "Failed to store file %(file)s." +msgstr "Gagal menyimpan berkas %(file)s." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Format berkas %(ext)s ditambahkan ke %(book)s" + +#: cps/gdrive.py:58 +msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" +msgstr "Pengaturan Google Drive belum selesai, coba nonaktifkan dan aktifkan kembali Google Drive" + +#: cps/gdrive.py:95 +msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" +msgstr "Domain panggilan balik tidak diverifikasi, ikuti langkah-langkah untuk memverifikasi domain di konsol pengembang google" + +#: cps/helper.py:81 +#, python-format +msgid "%(format)s format not found for book id: %(book)d" +msgstr "%(format)s format tidak ditemukan untuk id buku: %(book)d" + +#: cps/helper.py:88 cps/tasks/convert.py:75 +#, python-format +msgid "%(format)s not found on Google Drive: %(fn)s" +msgstr "%(format)s tidak ditemukan di Google Drive: %(fn)s" + +#: cps/helper.py:93 +#, python-format +msgid "%(format)s not found: %(fn)s" +msgstr "%(format)s tidak ditemukan: %(fn)s" + +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" +msgstr "Kirim ke E-Reader" + +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." +msgstr "Email ini telah dikirim melalui Calibre-Web." + +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" +msgstr "Email tes Calibre-Web" + +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" +msgstr "Email tes" + +#: cps/helper.py:133 +msgid "Get Started with Calibre-Web" +msgstr "Memulai dengan Calibre-Web" + +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" +msgstr "Email pendaftaran untuk pengguna: %(name)s" + +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +msgid "Convert %(orig)s to %(format)s and send to eReader" +msgstr "Ubah %(orig)s menjadi %(format)s dan kirim ke E-Reader" + +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" +msgstr "Kirim %(format)s ke E-Reader" + +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" +msgstr "%%(buku)s telah dikirim ke E-Reader" + +#: cps/helper.py:227 +msgid "The requested file could not be read. Maybe wrong permissions?" +msgstr "Berkas yang diminta tidak dapat dibaca. Mungkin izinnya salah?" + +#: cps/helper.py:342 +msgid "Read status could not set: {}" +msgstr "Status baca tidak bisa disetel: {}" + +#: cps/helper.py:365 +#, python-format +msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" +msgstr "Menghapus folder buku untuk buku %(id)s gagal, jalur memiliki subfolder: %(path)s" + +#: cps/helper.py:371 +#, python-format +msgid "Deleting book %(id)s failed: %(message)s" +msgstr "Gagal menghapus buku %(id)s: %(message)s" + +#: cps/helper.py:382 +#, python-format +msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" +msgstr "Menghapus buku %(id)s hanya dari basis data, jalur buku di basis data tidak valid: %(path)s" + +#: cps/helper.py:447 +#, python-format +msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Ganti nama pengarang dari: '%(src)s' menjadi '%(dest)s' gagal dengan kesalahan: %(error)s" + +#: cps/helper.py:519 cps/helper.py:528 +#, python-format +msgid "File %(file)s not found on Google Drive" +msgstr "Berkas %(file)s tidak ditemukan di Google Drive" + +#: cps/helper.py:562 +#, python-format +msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Ganti nama judul dari: '%(src)s' menjadi '%(dest)s' gagal dengan kesalahan: %(error)s" + +#: cps/helper.py:582 +msgid "Error in rename file in path: {}" +msgstr "Kesalahan dalam mengganti nama berkas di jalur: {}" + +#: cps/helper.py:600 +#, python-format +msgid "Book path %(path)s not found on Google Drive" +msgstr "Jalur buku %(path)s tidak ditemukan di Google Drive" + +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" + +#: cps/helper.py:673 +msgid "This username is already taken" +msgstr "Nama pengguna ini sudah digunakan" + +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" +msgstr "Format alamat email tidak valid" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "Modul 'advocate' Python tidak diinstal tetapi diperlukan untuk unggahan sampul" + +#: cps/helper.py:862 +msgid "Error Downloading Cover" +msgstr "Kesalahan Mengunduh Sampul" + +#: cps/helper.py:865 +msgid "Cover Format Error" +msgstr "Kesalahan Format Sampul" + +#: cps/helper.py:868 +msgid "You are not allowed to access localhost or the local network for cover uploads" +msgstr "Anda tidak diizinkan mengakses localhost atau jaringan lokal untuk unggahan sampul" + +#: cps/helper.py:878 +msgid "Failed to create path for cover" +msgstr "Gagal membuat jalur untuk sampul" + +#: cps/helper.py:894 +msgid "Cover-file is not a valid image file, or could not be stored" +msgstr "Berkas sampul bukan berkas gambar yang valid, atau tidak dapat disimpan" + +#: cps/helper.py:905 +msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" +msgstr "Hanya berkas jpg/jpeg/png/webp/bmp yang didukung sebagai berkas sampul" + +#: cps/helper.py:917 +msgid "Invalid cover file content" +msgstr "Konten berkas sampul tidak valid" + +#: cps/helper.py:921 +msgid "Only jpg/jpeg files are supported as coverfile" +msgstr "Hanya berkas jpg/jpeg yang didukung sebagai berkas sampul" + +#: cps/helper.py:973 +msgid "Unrar binary file not found" +msgstr "Berkas biner unrar tidak ditemukan" + +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" +msgstr "Kesalahan saat menjalankan UnRar" + +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Sampul" + +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "Antrian semua buku untuk cadangan metadata" + +#: cps/kobo_auth.py:90 +msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" +msgstr "Mohon akses calibre-web dari non localhost untuk mendapatkan api_endpoint yang valid untuk perangkat kobo" + +#: cps/kobo_auth.py:116 +msgid "Kobo Setup" +msgstr "Pengaturan Kobo" + +#: cps/oauth_bb.py:77 +#, python-format +msgid "Register with %(provider)s" +msgstr "Daftar dengan %(provider)s" + +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 +#, python-format +msgid "Success! You are now logged in as: %(nickname)s" +msgstr "Anda sekarang login sebagai: %(nickname)s" + +#: cps/oauth_bb.py:148 +#, python-format +msgid "Link to %(oauth)s Succeeded" +msgstr "Tautan ke %(oauth)s Berhasil" + +#: cps/oauth_bb.py:155 +msgid "Login failed, No User Linked With OAuth Account" +msgstr "Login gagal, Tidak Ada Pengguna yang Tertaut Dengan Akun OAuth" + +#: cps/oauth_bb.py:197 +#, python-format +msgid "Unlink to %(oauth)s Succeeded" +msgstr "Membatalkan tautan ke %(oauth)s Berhasil" + +#: cps/oauth_bb.py:202 +#, python-format +msgid "Unlink to %(oauth)s Failed" +msgstr "Membatalkan tautan ke %(oauth)s Gagal" + +#: cps/oauth_bb.py:205 +#, python-format +msgid "Not Linked to %(oauth)s" +msgstr "Tidak Tertaut ke %(oauth)s" + +#: cps/oauth_bb.py:261 +msgid "Failed to log in with GitHub." +msgstr "Gagal masuk dengan GitHub." + +#: cps/oauth_bb.py:267 +msgid "Failed to fetch user info from GitHub." +msgstr "Gagal mengambil info pengguna dari GitHub." + +#: cps/oauth_bb.py:279 +msgid "Failed to log in with Google." +msgstr "Gagal masuk dengan Google." + +#: cps/oauth_bb.py:285 +msgid "Failed to fetch user info from Google." +msgstr "Gagal mengambil info pengguna dari Google." + +#: cps/oauth_bb.py:332 +msgid "GitHub Oauth error, please retry later." +msgstr "Kesalahan GitHub Oauth, silakan coba lagi nanti." + +#: cps/oauth_bb.py:335 +msgid "GitHub Oauth error: {}" +msgstr "Kesalahan GitHub OAuth: {}" + +#: cps/oauth_bb.py:356 +msgid "Google Oauth error, please retry later." +msgstr "Kesalahan Google Oauth, harap coba lagi nanti." + +#: cps/oauth_bb.py:359 +msgid "Google Oauth error: {}" +msgstr "Kesalahan Google OAuth: {}" + +#: cps/opds.py:274 +msgid "{} Stars" +msgstr "{}★" + +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 +msgid "Login" +msgstr "Masuk" + +#: cps/remotelogin.py:74 cps/remotelogin.py:108 +msgid "Token not found" +msgstr "Token tidak ditemukan" + +#: cps/remotelogin.py:83 cps/remotelogin.py:116 +msgid "Token has expired" +msgstr "Token telah kedaluwarsa" + +#: cps/remotelogin.py:92 +msgid "Success! Please return to your device" +msgstr "Berhasil! Silakan kembali ke perangkat Anda" + +#: cps/render_template.py:42 cps/web.py:414 +msgid "Books" +msgstr "Buku" + +#: cps/render_template.py:44 +msgid "Show recent books" +msgstr "Tampilkan buku terbaru" + +#: cps/render_template.py:45 cps/templates/index.xml:26 +msgid "Hot Books" +msgstr "Buku Populer" + +#: cps/render_template.py:47 +msgid "Show Hot Books" +msgstr "Tampilkan Buku Populer" + +#: cps/render_template.py:49 cps/render_template.py:54 +msgid "Downloaded Books" +msgstr "Buku yang Diunduh" + +#: cps/render_template.py:51 cps/render_template.py:56 +#: cps/templates/user_table.html:167 +msgid "Show Downloaded Books" +msgstr "Tampilkan Buku yang Diunduh" + +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 +msgid "Top Rated Books" +msgstr "Buku Berperingkat Teratas" + +#: cps/render_template.py:61 cps/templates/user_table.html:161 +msgid "Show Top Rated Books" +msgstr "Tampilkan Buku Berperingkat Teratas" + +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 +msgid "Read Books" +msgstr "Buku Telah Dibaca" + +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" +msgstr "Tampilkan sudah dibaca dan belum dibaca" + +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 +msgid "Unread Books" +msgstr "Buku yang Belum Dibaca" + +#: cps/render_template.py:68 +msgid "Show unread" +msgstr "Tampilkan belum dibaca" + +#: cps/render_template.py:69 +msgid "Discover" +msgstr "Temukan" + +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 +msgid "Show Random Books" +msgstr "Tampilkan Buku Acak" + +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 +msgid "Categories" +msgstr "Kategori" + +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" +msgstr "Tampilkan pilihan kategori" + +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 +msgid "Series" +msgstr "Seri" + +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" +msgstr "Tampilkan pilihan seri" + +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 +msgid "Authors" +msgstr "Penulis" + +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" +msgstr "Tampilkan pilihan penulis" + +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 +msgid "Publishers" +msgstr "Penerbit" + +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" +msgstr "Tampilkan pilihan penerbit" + +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 +msgid "Languages" +msgstr "Bahasa" + +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" +msgstr "Tampilkan pilihan bahasa" + +#: cps/render_template.py:89 cps/templates/index.xml:105 +msgid "Ratings" +msgstr "Peringkat" + +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" +msgstr "Tampilkan pilihan peringkat" + +#: cps/render_template.py:92 cps/templates/index.xml:113 +msgid "File formats" +msgstr "Format berkas" + +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" +msgstr "Tampilkan pilihan format berkas" + +#: cps/render_template.py:96 cps/web.py:776 +msgid "Archived Books" +msgstr "Buku yang Diarsipkan" + +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Tampilkan buku yang diarsipkan" + +#: cps/render_template.py:101 cps/web.py:807 +msgid "Books List" +msgstr "Daftar Buku" + +#: cps/render_template.py:103 cps/templates/user_table.html:168 +msgid "Show Books List" +msgstr "Tampilkan Daftar Buku" + +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 +#: cps/templates/layout.html:46 cps/templates/layout.html:49 +#: cps/templates/search_form.html:227 +msgid "Search" +msgstr "Telusuri" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Terbit setelah " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Terbit sebelum " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Peringkat ≤ %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Peringkat ≥ %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Status Baca = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "Terjadi kesalahan saat mencari kolom khusus, harap mulai ulang Calibre-Web" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Penelusuran Lanjutan" + +#: cps/shelf.py:49 cps/shelf.py:103 +msgid "Invalid shelf specified" +msgstr "Rak yang ditentukan tidak valid" + +#: cps/shelf.py:55 +msgid "Sorry you are not allowed to add a book to that shelf" +msgstr "Maaf Anda tidak diperbolehkan menambahkan buku ke rak: %(shelfname)s" + +#: cps/shelf.py:64 +#, python-format +msgid "Book is already part of the shelf: %(shelfname)s" +msgstr "Buku sudah menjadi bagian dari rak: %(shelfname)s" + +#: cps/shelf.py:89 +#, python-format +msgid "Book has been added to shelf: %(sname)s" +msgstr "Buku telah ditambahkan ke rak: %(sname)s" + +#: cps/shelf.py:108 +msgid "You are not allowed to add a book to the shelf" +msgstr "Anda tidak diperbolehkan menambahkan buku ke rak: %(name)s" + +#: cps/shelf.py:126 +#, python-format +msgid "Books are already part of the shelf: %(name)s" +msgstr "Buku sudah menjadi bagian dari rak: %(name)s" + +#: cps/shelf.py:138 +#, python-format +msgid "Books have been added to shelf: %(sname)s" +msgstr "Buku telah ditambahkan ke rak: %(sname)s" + +#: cps/shelf.py:145 +#, python-format +msgid "Could not add books to shelf: %(sname)s" +msgstr "Tidak dapat menambahkan buku ke rak: %(sname)s" + +#: cps/shelf.py:191 +#, python-format +msgid "Book has been removed from shelf: %(sname)s" +msgstr "Buku telah dihapus dari rak: %(sname)s" + +#: cps/shelf.py:200 +msgid "Sorry you are not allowed to remove a book from this shelf" +msgstr "Maaf Anda tidak diizinkan untuk menghapus buku dari rak ini: %(sname)s" + +#: cps/shelf.py:210 cps/templates/layout.html:157 +msgid "Create a Shelf" +msgstr "Buat Rak" + +#: cps/shelf.py:218 +msgid "Sorry you are not allowed to edit this shelf" +msgstr "Maaf, Anda tidak diizinkan mengedit rak ini" + +#: cps/shelf.py:220 +msgid "Edit a shelf" +msgstr "Edit Rak" + +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Kesalahan menghapus Rak" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Rak berhasil dihapus" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Ubah urutan Rak: '%(name)s'" + +#: cps/shelf.py:316 +msgid "Sorry you are not allowed to create a public shelf" +msgstr "Maaf, Anda tidak diizinkan membuat rak publik" + +#: cps/shelf.py:333 +#, python-format +msgid "Shelf %(title)s created" +msgstr "Rak %(title)s dibuat" + +#: cps/shelf.py:336 +#, python-format +msgid "Shelf %(title)s changed" +msgstr "Rak %(title)s diubah" + +#: cps/shelf.py:350 +msgid "There was an error" +msgstr "Ada kesalahan" + +#: cps/shelf.py:372 +#, python-format +msgid "A public shelf with the name '%(title)s' already exists." +msgstr "Rak publik dengan nama '%(title)s' sudah ada." + +#: cps/shelf.py:383 +#, python-format +msgid "A private shelf with the name '%(title)s' already exists." +msgstr "Rak pribadi dengan nama '%(title)s' sudah ada." + +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "Rak: '%(name)s'" + +#: cps/shelf.py:469 +msgid "Error opening shelf. Shelf does not exist or is not accessible" +msgstr "Terjadi kesalahan saat membuka rak. Rak tidak ada atau tidak dapat diakses" + +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Tugas" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Menunggu" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Gagal" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Dimulai" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Selesai" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Berakhir" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Dibatalkan" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Status Tidak Diketahui" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 +msgid "Unexpected data while reading update information" +msgstr "Data tak terduga saat membaca informasi pembaruan" + +#: cps/updater.py:438 cps/updater.py:550 +msgid "No update available. You already have the latest version installed" +msgstr "Tidak ada pembaruan yang tersedia. Anda telah memasang versi terbaru" + +#: cps/updater.py:456 +msgid "A new update is available. Click on the button below to update to the latest version." +msgstr "Pembaruan tersedia. Klik tombol di bawah untuk memperbarui ke versi terbaru." + +#: cps/updater.py:474 +msgid "Could not fetch update information" +msgstr "Tidak dapat mengambil informasi pembaruan" + +#: cps/updater.py:484 +msgid "Click on the button below to update to the latest stable version." +msgstr "Klik tombol di bawah untuk memperbarui ke versi stabil terbaru." + +#: cps/updater.py:493 cps/updater.py:507 cps/updater.py:518 +#, python-format +msgid "A new update is available. Click on the button below to update to version: %(version)s" +msgstr "Pembaruan tersedia. Klik tombol di bawah untuk memperbarui ke versi: %(version)s" + +#: cps/updater.py:536 +msgid "No release information available" +msgstr "Tidak ada informasi rilis yang tersedia" + +#: cps/templates/index.html:6 cps/web.py:441 +msgid "Discover (Random Books)" +msgstr "Temukan (Buku Acak)" + +#: cps/web.py:477 +msgid "Hot Books (Most Downloaded)" +msgstr "Buku Populer (Paling Banyak Diunduh)" + +#: cps/web.py:508 +#, python-format +msgid "Downloaded books by %(user)s" +msgstr "Buku telah diunduh oleh %(user)s" + +#: cps/web.py:541 +#, python-format +msgid "Author: %(name)s" +msgstr "Penulis: %(name)s" + +#: cps/web.py:577 +#, python-format +msgid "Publisher: %(name)s" +msgstr "Penerbit: %(name)s" + +#: cps/web.py:605 +#, python-format +msgid "Series: %(serie)s" +msgstr "Seri: %(serie)s" + +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Peringkat: Tidak ada" + +#: cps/web.py:629 +#, python-format +msgid "Rating: %(rating)s stars" +msgstr "Peringkat: %(rating)s★" + +#: cps/web.py:645 +#, python-format +msgid "File format: %(format)s" +msgstr "Format berkas: %(format)s" + +#: cps/web.py:682 +#, python-format +msgid "Category: %(name)s" +msgstr "Kategori: %(name)s" + +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Bahasa: %(name)s" + +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "Unduhan" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "Daftar peringkat" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Daftar format berkas" + +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Harap atur pengaturan email SMTP terlebih dahulu..." + +#: cps/web.py:1240 +#, python-format +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Buku telah diantrikan untuk dikirim ke %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" +msgstr "Oops! Terjadi kesalahan saat mengirim buku: %(res)s" + +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "Harap perbarui profil Anda dengan alamat e-mail Kirim ke Kindle yang valid." + +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" + +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 +msgid "Register" +msgstr "Daftar" + +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Server email belum diatur, silakan hubungi administrator!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." +msgstr "Alamat email Anda tidak diizinkan untuk mendaftar" + +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "E-mail konfirmasi telah dikirimkan ke alamat email Anda." + +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy +msgid "Cannot activate LDAP authentication" +msgstr "Tidak dapat mengaktifkan autentikasi LDAP." + +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "Anda sekarang login sebagai: %(nickname)s" + +#: cps/web.py:1383 +#, fuzzy, python-format +msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" +msgstr "Login Pengganti sebagai: '%(nickname)s', Server LDAP tidak dapat dijangkau, atau pengguna tidak diketahui." + +#: cps/web.py:1388 +#, fuzzy, python-format +msgid "Could not login: %(message)s" +msgstr "Tidak dapat login: %(message)s" + +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy +msgid "Wrong Username or Password" +msgstr "Pengguna atau Kata Sandi salah" + +#: cps/web.py:1399 +#, fuzzy +msgid "New Password was send to your email address" +msgstr "Kata Sandi baru telah dikirimkan ke alamat email Anda" + +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Terjadi kesalahan yang tidak diketahui. Coba lagi nanti." + +#: cps/web.py:1405 +#, fuzzy +msgid "Please enter valid username to reset password" +msgstr "Harap masukkan pengguna valid untuk mengatur ulang kata sandi" + +#: cps/web.py:1413 +#, fuzzy, python-format +msgid "You are now logged in as: '%(nickname)s'" +msgstr "Anda sekarang login sebagai: %(nickname)s" + +#: cps/web.py:1471 cps/web.py:1521 +#, python-format +msgid "%(name)s's Profile" +msgstr "Profil %(name)s" + +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" +msgstr "Profil diperbarui" + +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Ditemukan akun yang ada untuk alamat email ini" + +#: cps/services/gmail.py:58 +msgid "Found no valid gmail.json file with OAuth information" +msgstr "Tidak ditemukan berkas gmail.json yang valid dengan informasi OAuth" + +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%%(buku)s telah dikirim ke E-Reader" + +#: cps/tasks/convert.py:153 +#, python-format +msgid "Calibre ebook-convert %(tool)s not found" +msgstr "Calibre ebook-convert %(tool)s tidak ditemukan" + +#: cps/tasks/convert.py:186 +#, python-format +msgid "%(format)s format not found on disk" +msgstr "%(format)s format tidak ditemukan dalam disk" + +#: cps/tasks/convert.py:190 +msgid "Ebook converter failed with unknown error" +msgstr "Konverter ebook gagal dengan kesalahan yang tidak diketahui." + +#: cps/tasks/convert.py:202 +#, python-format +msgid "Kepubify-converter failed: %(error)s" +msgstr "Kebupify-converter gagal: %(error)s" + +#: cps/tasks/convert.py:224 +#, python-format +msgid "Converted file not found or more than one file in folder %(folder)s" +msgstr "Berkas yang telah dikonversi tidak ditemukan atau terdapat duplikat dalam folder %(folder)s" + +#: cps/tasks/convert.py:247 +#, python-format +msgid "Ebook-converter failed: %(error)s" +msgstr "Ebook-converter gagal: %(error)s" + +#: cps/tasks/convert.py:270 +#, python-format +msgid "Calibre failed with error: %(error)s" +msgstr "Calibre gagal dengan kesalahan: %(error)s" + +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Konversi" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Menghubungkan kembali basis data Calibre" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "Email" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "Mencadangkan Metadata" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "%(count)s thumbnail sampul dibuat" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "Thumbnail Sampul" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "{0} thumbnail seri dihasilkan" + +#: cps/tasks/thumbnail.py:454 +msgid "Clearing cover thumbnail cache" +msgstr "Menghapus cache thumbnail sampul" + +#: cps/tasks/upload.py:38 cps/templates/admin.html:20 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Unggah" + +#: cps/templates/admin.html:9 +msgid "Users" +msgstr "Pengguna" + +#: cps/templates/admin.html:13 cps/templates/login.html:9 +#: cps/templates/login.html:10 cps/templates/register.html:9 +#: cps/templates/user_edit.html:10 cps/templates/user_table.html:134 +msgid "Username" +msgstr "Nama Pengguna" + +#: cps/templates/admin.html:14 cps/templates/register.html:14 +#: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 +msgid "Email" +msgstr "Alamat Email" + +#: cps/templates/admin.html:15 cps/templates/user_edit.html:28 +msgid "Send to eReader Email" +msgstr "Alamat E-mail untuk Kirim ke E-Reader" + +#: cps/templates/admin.html:17 cps/templates/layout.html:91 +#: cps/templates/user_table.html:143 +msgid "Admin" +msgstr "Admin" + +#: cps/templates/admin.html:18 cps/templates/login.html:13 +#: cps/templates/login.html:14 cps/templates/user_edit.html:23 +msgid "Password" +msgstr "Kata Sandi" + +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 +#: cps/templates/user_table.html:146 +msgid "Download" +msgstr "Unduh" + +#: cps/templates/admin.html:23 +msgid "View Books" +msgstr "Lihat Buku" + +#: cps/templates/admin.html:24 cps/templates/user_table.html:131 +#: cps/templates/user_table.html:148 +msgid "Edit" +msgstr "Edit" + +#: cps/templates/admin.html:25 cps/templates/book_edit.html:17 +#: cps/templates/book_table.html:100 cps/templates/modal_dialogs.html:63 +#: cps/templates/modal_dialogs.html:116 cps/templates/user_edit.html:67 +#: cps/templates/user_table.html:149 +msgid "Delete" +msgstr "Hapus" + +#: cps/templates/admin.html:26 +msgid "Public Shelf" +msgstr "Rak Publik" + +#: cps/templates/admin.html:55 +msgid "Import LDAP Users" +msgstr "Impor Pengguna LDAP" + +#: cps/templates/admin.html:62 +msgid "Email Server Settings" +msgstr "Pengaturan Server Email" + +#: cps/templates/admin.html:67 cps/templates/email_edit.html:31 +msgid "SMTP Hostname" +msgstr "Hostname SMTP" + +#: cps/templates/admin.html:71 cps/templates/email_edit.html:35 +msgid "SMTP Port" +msgstr "Port SMTP" + +#: cps/templates/admin.html:75 cps/templates/email_edit.html:39 +msgid "Encryption" +msgstr "Enkripsi" + +#: cps/templates/admin.html:79 cps/templates/email_edit.html:47 +msgid "SMTP Login" +msgstr "Login SMTP" + +#: cps/templates/admin.html:83 cps/templates/admin.html:94 +#: cps/templates/email_edit.html:55 +msgid "From Email" +msgstr "Dari Email" + +#: cps/templates/admin.html:90 +#, fuzzy +msgid "Email Service" +msgstr "Layanan Email" + +#: cps/templates/admin.html:91 +msgid "Gmail via Oauth2" +msgstr "Gmail via Oauth2" + +#: cps/templates/admin.html:106 +msgid "Configuration" +msgstr "Pengaturan" + +#: cps/templates/admin.html:109 +msgid "Calibre Database Directory" +msgstr "Jalur Database Calibre" + +#: cps/templates/admin.html:113 cps/templates/config_edit.html:68 +msgid "Log Level" +msgstr "Log Level" + +#: cps/templates/admin.html:117 +msgid "Port" +msgstr "Port" + +#: cps/templates/admin.html:122 +msgid "External Port" +msgstr "Port Eksternal" + +#: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 +msgid "Books per Page" +msgstr "Buku per halaman" + +#: cps/templates/admin.html:133 +msgid "Uploads" +msgstr "Unggah" + +#: cps/templates/admin.html:137 +msgid "Anonymous Browsing" +msgstr "Penjelajahan Anonim" + +#: cps/templates/admin.html:141 +msgid "Public Registration" +msgstr "Registrasi Publik" + +#: cps/templates/admin.html:145 +msgid "Magic Link Remote Login" +msgstr "Login Jarak Jauh dengan Magic Link" + +#: cps/templates/admin.html:149 +msgid "Reverse Proxy Login" +msgstr "Login Reverse Proxy" + +#: cps/templates/admin.html:154 cps/templates/config_edit.html:173 +msgid "Reverse Proxy Header Name" +msgstr "Nama Header Reverse Proxy" + +#: cps/templates/admin.html:159 +msgid "Edit Calibre Database Configuration" +msgstr "Edit Pengaturan Basis Data Caliber" + +#: cps/templates/admin.html:160 +msgid "Edit Basic Configuration" +msgstr "Edit Pengaturan Dasar" + +#: cps/templates/admin.html:161 +msgid "Edit UI Configuration" +msgstr "Edit Pengaturan Antarmuka" + +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Tugas Terjadwal" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "Waktu saat tugas mulai dijalankan" + +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +msgid "Maximum Duration" +msgstr "Durasi tugas maksimum" + +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" +msgstr "Buat thumbnail sampul buku" + +#: cps/templates/admin.html:182 +msgid "Generate series cover thumbnails" +msgstr "Buat thumbnail sampul seri" + +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Sambungkan kembali ke Perpustakaan Caliber" + +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "Segarkan Cache Thumbnail Sampul" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Administrasi" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Unduh Paket Debug" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Tampilkan Log" + +#: cps/templates/admin.html:211 +msgid "Restart" +msgstr "Mulai Ulang" + +#: cps/templates/admin.html:212 +msgid "Shutdown" +msgstr "Matikan" + +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Informasi Versi" + +#: cps/templates/admin.html:225 +msgid "Version" +msgstr "Versi" + +#: cps/templates/admin.html:226 +msgid "Details" +msgstr "Detail" + +#: cps/templates/admin.html:232 +msgid "Current Version" +msgstr "Versi saat ini" + +#: cps/templates/admin.html:239 +msgid "Check for Update" +msgstr "Periksa Pembaruan" + +#: cps/templates/admin.html:240 +msgid "Perform Update" +msgstr "Lakukan Pembaruan" + +#: cps/templates/admin.html:253 +msgid "Are you sure you want to restart?" +msgstr "Apa Anda yakin untuk memulai ulang?" + +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 +msgid "OK" +msgstr "OK" + +#: cps/templates/admin.html:259 cps/templates/admin.html:273 +#: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 +#: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 +#: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 +#: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 +#: cps/templates/user_edit.html:144 +msgid "Cancel" +msgstr "Batal" + +#: cps/templates/admin.html:271 +msgid "Are you sure you want to shutdown?" +msgstr "Apa Anda yakin untuk mematikan layanan?" + +#: cps/templates/admin.html:283 +msgid "Updating, please do not reload this page" +msgstr "Memperbarui, jangan memuat ulang halaman ini" + +#: cps/templates/author.html:15 +msgid "via" +msgstr "melalui" + +#: cps/templates/author.html:23 +msgid "In Library" +msgstr "Dalam Pustaka" + +#: cps/templates/author.html:26 cps/templates/index.html:74 +#: cps/templates/search.html:31 cps/templates/shelf.html:20 +msgid "Sort according to book date, newest first" +msgstr "Urutkan menurut tanggal buku, terbaru dulu" + +#: cps/templates/author.html:27 cps/templates/index.html:75 +#: cps/templates/search.html:32 cps/templates/shelf.html:21 +msgid "Sort according to book date, oldest first" +msgstr "Urutkan menurut tanggal buku, terlama dulu" + +#: cps/templates/author.html:28 cps/templates/index.html:76 +#: cps/templates/search.html:33 cps/templates/shelf.html:22 +msgid "Sort title in alphabetical order" +msgstr "Urutkan judul dalam urutan abjad" + +#: cps/templates/author.html:29 cps/templates/index.html:77 +#: cps/templates/search.html:34 cps/templates/shelf.html:23 +msgid "Sort title in reverse alphabetical order" +msgstr "Urutkan judul dalam urutan abjad terbalik" + +#: cps/templates/author.html:30 cps/templates/index.html:80 +#: cps/templates/search.html:37 cps/templates/shelf.html:26 +msgid "Sort according to publishing date, newest first" +msgstr "Urutkan menurut tanggal penerbitan, yang terbaru dulu" + +#: cps/templates/author.html:31 cps/templates/index.html:81 +#: cps/templates/search.html:38 cps/templates/shelf.html:27 +msgid "Sort according to publishing date, oldest first" +msgstr "Urutkan menurut tanggal penerbitan, yang terlama dulu" + +#: cps/templates/author.html:56 cps/templates/author.html:115 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 +msgid "reduce" +msgstr "kurangi" + +#: cps/templates/author.html:99 +msgid "More by" +msgstr "Lainnya oleh" + +#: cps/templates/book_edit.html:11 +msgid "Delete Book" +msgstr "Hapus" + +#: cps/templates/book_edit.html:14 +msgid "Delete formats:" +msgstr "Hapus format:" + +#: cps/templates/book_edit.html:25 +msgid "Convert book format:" +msgstr "KOnversi format buku:" + +#: cps/templates/book_edit.html:30 +msgid "Convert from:" +msgstr "Konversi dari:" + +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 +msgid "select an option" +msgstr "pilih opsi" + +#: cps/templates/book_edit.html:37 +msgid "Convert to:" +msgstr "Konversi ke:" + +#: cps/templates/book_edit.html:46 +msgid "Convert book" +msgstr "Konversi buku" + +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 +msgid "Book Title" +msgstr "Judul Buku" + +#: cps/templates/book_edit.html:63 cps/templates/book_edit.html:271 +#: cps/templates/book_edit.html:289 cps/templates/search_form.html:12 +msgid "Author" +msgstr "Penulis" + +#: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 +msgid "Description" +msgstr "Deskripsi" + +#: cps/templates/book_edit.html:73 +msgid "Identifiers" +msgstr "Pengidentifikasi" + +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +msgid "Identifier Type" +msgstr "Tipe Pengidentifikasi" + +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +msgid "Identifier Value" +msgstr "Nilai Pengidentifikasi" + +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 +#: cps/templates/user_table.html:24 +msgid "Remove" +msgstr "Hapus" + +#: cps/templates/book_edit.html:83 +msgid "Add Identifier" +msgstr "Tambah Pengidentifikasi" + +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 +msgid "Tags" +msgstr "Tag" + +#: cps/templates/book_edit.html:95 +msgid "Series ID" +msgstr "ID Seri" + +#: cps/templates/book_edit.html:99 +msgid "Rating" +msgstr "Rating" + +#: cps/templates/book_edit.html:104 +msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" +msgstr "Ambil Sampul dari URL (JPEG - Gambar akan diunduh dan disimpan dalam basis data)" + +#: cps/templates/book_edit.html:108 +msgid "Upload Cover from Local Disk" +msgstr "Unggah Sampul dari disk lokal" + +#: cps/templates/book_edit.html:113 +msgid "Published Date" +msgstr "Tanggal Terbit" + +#: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 +msgid "Publisher" +msgstr "Penerbit" + +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 +msgid "Language" +msgstr "Bahasa" + +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 +msgid "Yes" +msgstr "Ya" + +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 +msgid "No" +msgstr "Tidak" + +#: cps/templates/book_edit.html:201 +msgid "Upload Format" +msgstr "Format Unggahan" + +#: cps/templates/book_edit.html:209 +msgid "View Book on Save" +msgstr "Tampilkan Buku setelah Disimpan" + +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 +msgid "Fetch Metadata" +msgstr "Ambil Metadata" + +#: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 +#: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 +#: cps/templates/user_edit.html:142 +msgid "Save" +msgstr "Simpan" + +#: cps/templates/book_edit.html:233 +msgid "Keyword" +msgstr "Kata Kunci" + +#: cps/templates/book_edit.html:234 +msgid "Search keyword" +msgstr "Cari Kata kunci" + +#: cps/templates/book_edit.html:240 +msgid "Click the cover to load metadata to the form" +msgstr "Klik sampul untuk memuat metadata ke formulir" + +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 +msgid "Loading..." +msgstr "Memuat..." + +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 +#: cps/templates/user_edit.html:163 +msgid "Close" +msgstr "Tutup" + +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 +msgid "Source" +msgstr "Sumber" + +#: cps/templates/book_edit.html:287 +msgid "Search error!" +msgstr "Kesalahan pencarian!" + +#: cps/templates/book_edit.html:288 +msgid "No Result(s) found! Please try another keyword." +msgstr "Tidak ada hasil yang ditemukan! Silakan coba kata kunci lain." + +#: cps/templates/book_table.html:12 cps/templates/book_table.html:69 +#: cps/templates/user_table.html:14 cps/templates/user_table.html:77 +#: cps/templates/user_table.html:100 +msgid "This Field is Required" +msgstr "Isian Ini Diperlukan" + +#: cps/templates/book_table.html:37 +msgid "Merge selected books" +msgstr "Gabungkan buku terpiih" + +#: cps/templates/book_table.html:38 cps/templates/user_table.html:124 +msgid "Remove Selections" +msgstr "Hapus Pilihan" + +#: cps/templates/book_table.html:41 +msgid "Exchange author and title" +msgstr "Tukar penulis dan judul" + +#: cps/templates/book_table.html:47 +msgid "Update Title Sort automatically" +msgstr "Perbarui Pengurutan Judul secara otomatis" + +#: cps/templates/book_table.html:51 +msgid "Update Author Sort automatically" +msgstr "Perbarui Pengurutan Penulis secara otomatis" + +#: cps/templates/book_table.html:63 cps/templates/book_table.html:69 +msgid "Enter Title" +msgstr "Masukkan Judul" + +#: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 +#: cps/templates/shelf_edit.html:8 +msgid "Title" +msgstr "Judul" + +#: cps/templates/book_table.html:64 +msgid "Enter Title Sort" +msgstr "Masukkan Urutan Judul" + +#: cps/templates/book_table.html:64 +msgid "Title Sort" +msgstr "Urutan Judul" + +#: cps/templates/book_table.html:65 +msgid "Enter Author Sort" +msgstr "Masukkan Urutan Penulis" + +#: cps/templates/book_table.html:65 +msgid "Author Sort" +msgstr "Urutan Penulis" + +#: cps/templates/book_table.html:66 +msgid "Enter Authors" +msgstr "Masukkan Penulis" + +#: cps/templates/book_table.html:67 +msgid "Enter Categories" +msgstr "Masukkan Kategori" + +#: cps/templates/book_table.html:68 +msgid "Enter Series" +msgstr "Masukkan Seri" + +#: cps/templates/book_table.html:69 +msgid "Series Index" +msgstr "Indeks Pencarian" + +#: cps/templates/book_table.html:70 +msgid "Enter Languages" +msgstr "Masukkan Bahasa" + +#: cps/templates/book_table.html:71 +msgid "Publishing Date" +msgstr "Tanggal Terbit" + +#: cps/templates/book_table.html:72 +msgid "Enter Publishers" +msgstr "Masukkan Penerbit" + +#: cps/templates/book_table.html:73 +msgid "Enter comments" +msgstr "Masukkan komentar" + +#: cps/templates/book_table.html:73 +msgid "Comments" +msgstr "Komentar" + +#: cps/templates/book_table.html:75 +msgid "Archive Status" +msgstr "Status Arsip" + +#: cps/templates/book_table.html:77 cps/templates/search_form.html:42 +msgid "Read Status" +msgstr "Status Baca" + +#: cps/templates/book_table.html:80 cps/templates/book_table.html:82 +#: cps/templates/book_table.html:84 cps/templates/book_table.html:86 +#: cps/templates/book_table.html:90 cps/templates/book_table.html:92 +#: cps/templates/book_table.html:96 +msgid "Enter " +msgstr "入力: " + +#: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 +msgid "Are you really sure?" +msgstr "Apakah Anda yakin?" + +#: cps/templates/book_table.html:117 +msgid "Books with Title will be merged from:" +msgstr "Buku dengan Judul akan digabungkan dari:" + +#: cps/templates/book_table.html:121 +msgid "Into Book with Title:" +msgstr "Ke dalam Buku dengan Judul:" + +#: cps/templates/book_table.html:126 +msgid "Merge" +msgstr "Gabungkan" + +#: cps/templates/config_db.html:12 +msgid "Location of Calibre Database" +msgstr "Lokasi Database Calibre" + +#: cps/templates/config_db.html:22 +msgid "Use Google Drive?" +msgstr "Gunakan Google Drive?" + +#: cps/templates/config_db.html:27 +msgid "Authenticate Google Drive" +msgstr "Autentikasi Google Drive" + +#: cps/templates/config_db.html:32 +msgid "Google Drive Calibre folder" +msgstr "Silakan tekan simpan untuk melanjutkan penyiapan" + +#: cps/templates/config_db.html:40 +msgid "Metadata Watch Channel ID" +msgstr "ID Saluran Metadata Watch" + +#: cps/templates/config_db.html:43 +msgid "Revoke" +msgstr "Tarik Kembali" + +#: cps/templates/config_db.html:68 +msgid "New db location is invalid, please enter valid path" +msgstr "Lokasi basis data baru tidak valid, harap masukkan jalur yang valid" + +#: cps/templates/config_edit.html:18 +msgid "Server Configuration" +msgstr "Pengaturan Server" + +#: cps/templates/config_edit.html:25 +msgid "Server Port" +msgstr "Port Server" + +#: cps/templates/config_edit.html:28 +msgid "SSL certfile location (leave it empty for non-SSL Servers)" +msgstr "Lokasi berkas sertifikat SSL (biarkan kosong untuk Server non-SSL)" + +#: cps/templates/config_edit.html:35 +msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" +msgstr "Lokasi SSL Keyfile (biarkan kosong untuk Server non-SSL)" + +#: cps/templates/config_edit.html:43 +msgid "Update Channel" +msgstr "Saluran Pembaruan" + +#: cps/templates/config_edit.html:45 +msgid "Stable" +msgstr "Stabil" + +#: cps/templates/config_edit.html:46 +msgid "Nightly" +msgstr "Nightly" + +#: cps/templates/config_edit.html:50 +msgid "Trusted Hosts (Comma Separated)" +msgstr "Host Tepercaya (Pisahkan dengan Koma)" + +#: cps/templates/config_edit.html:61 +msgid "Logfile Configuration" +msgstr "Pengaturan Logfile" + +#: cps/templates/config_edit.html:77 +msgid "Location and name of logfile (calibre-web.log for no entry)" +msgstr "Lokasi dan nama logfile (caliber-web.log jika tanpa entri)" + +#: cps/templates/config_edit.html:82 +msgid "Enable Access Log" +msgstr "Aktifkan Log Akses" + +#: cps/templates/config_edit.html:85 +msgid "Location and name of access logfile (access.log for no entry)" +msgstr "Lokasi dan nama access logfile (access.log jika tanpa entri)" + +#: cps/templates/config_edit.html:96 +msgid "Feature Configuration" +msgstr "Pengaturan Fitur" + +#: cps/templates/config_edit.html:104 +msgid "Convert non-English characters in title and author while saving to disk" +msgstr "Konversikan karakter non-Inggris dalam judul dan penulis saat menyimpan ke disk" + +#: cps/templates/config_edit.html:108 +msgid "Enable Uploads" +msgstr "Izinkan Unggahan" + +#: cps/templates/config_edit.html:108 +msgid "(Please ensure that users also have upload permissions)" +msgstr "(Harap pastikan pengguna juga memiliki hak mengunggah)" + +#: cps/templates/config_edit.html:112 +msgid "Allowed Upload Fileformats" +msgstr "Format Berkas Unggahan yang Diizinkan" + +#: cps/templates/config_edit.html:118 +msgid "Enable Anonymous Browsing" +msgstr "Izinkan Penjelajahan Anonim" + +#: cps/templates/config_edit.html:122 +msgid "Enable Public Registration" +msgstr "Izinkan Registrasi Publik" + +#: cps/templates/config_edit.html:127 +msgid "Use Email as Username" +msgstr "Gunakan Email sebagai Nama Pengguna" + +#: cps/templates/config_edit.html:132 +msgid "Enable Magic Link Remote Login" +msgstr "Izinkan Login Jarak Jauh dengan Magic Link" + +#: cps/templates/config_edit.html:137 +msgid "Enable Kobo sync" +msgstr "Aktifkan sinkronisasi Kobo" + +#: cps/templates/config_edit.html:142 +msgid "Proxy unknown requests to Kobo Store" +msgstr "Proxy permintaan tidak dikenal ke Kobo Store" + +#: cps/templates/config_edit.html:145 +msgid "Server External Port (for port forwarded API calls)" +msgstr "Port Eksternal Server (untuk panggilan API melalui port forward)" + +#: cps/templates/config_edit.html:153 +msgid "Use Goodreads" +msgstr "Gunakan Goodreads" + +#: cps/templates/config_edit.html:154 +msgid "Create an API Key" +msgstr "Buat Kunci API" + +#: cps/templates/config_edit.html:158 +msgid "Goodreads API Key" +msgstr "Kunci API Goodreads" + +#: cps/templates/config_edit.html:162 +msgid "Goodreads API Secret" +msgstr "Goodreads API Secret" + +#: cps/templates/config_edit.html:169 +msgid "Allow Reverse Proxy Authentication" +msgstr "Izinkan Reverse Proxy Authentication" + +#: cps/templates/config_edit.html:180 +msgid "Login type" +msgstr "Tipe Login" + +#: cps/templates/config_edit.html:182 +msgid "Use Standard Authentication" +msgstr "Gunakan Otentikasi Standar" + +#: cps/templates/config_edit.html:184 +msgid "Use LDAP Authentication" +msgstr "Gunakan Otentikasi LDAP" + +#: cps/templates/config_edit.html:187 +msgid "Use OAuth" +msgstr "Gunakan Oauth" + +#: cps/templates/config_edit.html:194 +msgid "LDAP Server Host Name or IP Address" +msgstr "Nama Host Server atau Alamat IP LDAP" + +#: cps/templates/config_edit.html:198 +msgid "LDAP Server Port" +msgstr "Port Server LDAP" + +#: cps/templates/config_edit.html:202 +msgid "LDAP Encryption" +msgstr "Enkripsi LDAP" + +#: cps/templates/config_edit.html:205 +msgid "TLS" +msgstr "TLS" + +#: cps/templates/config_edit.html:206 +msgid "SSL" +msgstr "SSL" + +#: cps/templates/config_edit.html:210 +msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" +msgstr "Jalur CACertificate LDAP (Hanya diperlukan untuk Autentikasi Sertifikat Klien)" + +#: cps/templates/config_edit.html:217 +msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" +msgstr "Jalur Sertifikat LDAP (Hanya diperlukan untuk Otentikasi Sertifikat Klien)" + +#: cps/templates/config_edit.html:224 +msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" +msgstr "Jalur Keyfile LDAP (Hanya diperlukan untuk Otentikasi Sertifikat Klien)" + +#: cps/templates/config_edit.html:233 +msgid "LDAP Authentication" +msgstr "Otentikasi LDAP" + +#: cps/templates/config_edit.html:235 +msgid "Anonymous" +msgstr "Anonim" + +#: cps/templates/config_edit.html:236 +msgid "Unauthenticated" +msgstr "Tidak diautentikasi" + +#: cps/templates/config_edit.html:237 +msgid "Simple" +msgstr "Sederhana" + +#: cps/templates/config_edit.html:242 +msgid "LDAP Administrator Username" +msgstr "Nama Pengguna Administrator LDAP" + +#: cps/templates/config_edit.html:248 +msgid "LDAP Administrator Password" +msgstr "Kata Sandi Administrator LDAP" + +#: cps/templates/config_edit.html:253 +msgid "LDAP Distinguished Name (DN)" +msgstr "Distinguished Name (DN) LDAP" + +#: cps/templates/config_edit.html:257 +msgid "LDAP User Object Filter" +msgstr "Filter Objek Pengguna LDAP" + +#: cps/templates/config_edit.html:262 +msgid "LDAP Server is OpenLDAP?" +msgstr "Server LDAP adalah OpenLDAP?" + +#: cps/templates/config_edit.html:264 +msgid "Following Settings are Needed For User Import" +msgstr "Pengaturan Berikut Diperlukan Untuk Impor Pengguna" + +#: cps/templates/config_edit.html:266 +msgid "LDAP Group Object Filter" +msgstr "Filter Objek Grup LDAP" + +#: cps/templates/config_edit.html:270 +msgid "LDAP Group Name" +msgstr "Nama Grup LDAP" + +#: cps/templates/config_edit.html:274 +msgid "LDAP Group Members Field" +msgstr "Bidang Group Members LDAP" + +#: cps/templates/config_edit.html:278 +msgid "LDAP Member User Filter Detection" +msgstr "Deteksi Filter Pengguna Anggota LDAP" + +#: cps/templates/config_edit.html:280 +msgid "Autodetect" +msgstr "Deteksi otomatis" + +#: cps/templates/config_edit.html:281 +msgid "Custom Filter" +msgstr "Filter Kustom" + +#: cps/templates/config_edit.html:286 +msgid "LDAP Member User Filter" +msgstr "Filter Pengguna Anggota LDAP" + +#: cps/templates/config_edit.html:297 +#, python-format +msgid "Obtain %(provider)s OAuth Credential" +msgstr "Dapatkan %(provider)s Kredensial OAuth" + +#: cps/templates/config_edit.html:300 +#, python-format +msgid "%(provider)s OAuth Client Id" +msgstr "ID Klien %(provider)s OAuth" + +#: cps/templates/config_edit.html:304 +#, python-format +msgid "%(provider)s OAuth Client Secret" +msgstr "Client Secret %(provider)s OAuth" + +#: cps/templates/config_edit.html:320 +msgid "External binaries" +msgstr "Binari Eksternal" + +#: cps/templates/config_edit.html:326 +msgid "Path to Calibre E-Book Converter" +msgstr "Jalur ke Konverter E-Book Calibre" + +#: cps/templates/config_edit.html:334 +msgid "Calibre E-Book Converter Settings" +msgstr "Pengaturan Konverter E-Book Caliber" + +#: cps/templates/config_edit.html:337 +msgid "Path to Kepubify E-Book Converter" +msgstr "Jalur ke Konverter E-Book Kepubify" + +#: cps/templates/config_edit.html:345 +msgid "Location of Unrar binary" +msgstr "Lokasi binari Unrar" + +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Pengaturan OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Atur ulang kata sandi pengguna" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + +#: cps/templates/config_view_edit.html:17 +msgid "View Configuration" +msgstr "Pengaturan Tampilan" + +#: cps/templates/config_view_edit.html:32 +msgid "No. of Random Books to Display" +msgstr "Jumlah Buku Acak untuk Ditampilkan" + +#: cps/templates/config_view_edit.html:36 +msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" +msgstr "Jumlah Penulis untuk Ditampilkan Sebelum Disembunyikan (0=Nonaktifkan Penyembunyian)" + +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 +msgid "Theme" +msgstr "Tema" + +#: cps/templates/config_view_edit.html:42 +msgid "Standard Theme" +msgstr "Tema Standar" + +#: cps/templates/config_view_edit.html:43 +msgid "caliBlur! Dark Theme" +msgstr "Tema Gelap caliBlur!" + +#: cps/templates/config_view_edit.html:47 +msgid "Regular Expression for Ignoring Columns" +msgstr "Ekspresi Reguler untuk Mengabaikan Kolom" + +#: cps/templates/config_view_edit.html:51 +msgid "Link Read/Unread Status to Calibre Column" +msgstr "Tautkan Status Baca/Belum Dibaca ke Kolom Kaliber" + +#: cps/templates/config_view_edit.html:60 +msgid "View Restrictions based on Calibre column" +msgstr "Lihat Batasan berdasarkan kolom Caliber" + +#: cps/templates/config_view_edit.html:69 +msgid "Regular Expression for Title Sorting" +msgstr "Ekspresi Reguler untuk Penyortiran Judul" + +#: cps/templates/config_view_edit.html:80 +msgid "Default Settings for New Users" +msgstr "Pengaturan Default untuk Pengguna Baru" + +#: cps/templates/config_view_edit.html:88 cps/templates/user_edit.html:96 +msgid "Admin User" +msgstr "Pengguna Admin" + +#: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 +msgid "Allow Downloads" +msgstr "Izinkan Unduhan" + +#: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 +msgid "Allow eBook Viewer" +msgstr "Izinkan Penampil eBook" + +#: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 +msgid "Allow Uploads" +msgstr "Izinkan Unggahan" + +#: cps/templates/config_view_edit.html:106 cps/templates/user_edit.html:115 +msgid "Allow Edit" +msgstr "Izinkan Edit" + +#: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 +msgid "Allow Delete Books" +msgstr "Izinkan Menghapus Buku" + +#: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 +msgid "Allow Changing Password" +msgstr "Izinkan Mengganti Kata Sandi" + +#: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 +msgid "Allow Editing Public Shelves" +msgstr "Izinkan Mengedit Rak Publik" + +#: cps/templates/config_view_edit.html:123 +msgid "Default Language" +msgstr "Bahasa Bawaan" + +#: cps/templates/config_view_edit.html:131 +msgid "Default Visible Language of Books" +msgstr "Bahasa Buku Bawaan yang Terlihat" + +#: cps/templates/config_view_edit.html:147 +msgid "Default Visibilities for New Users" +msgstr "Visibilitas Default untuk Pengguna Baru" + +#: cps/templates/config_view_edit.html:163 cps/templates/user_edit.html:84 +#: cps/templates/user_table.html:154 +msgid "Show Random Books in Detail View" +msgstr "Tampilkan Buku Acak dalam Tampilan Detail" + +#: cps/templates/config_view_edit.html:166 cps/templates/user_edit.html:87 +msgid "Add Allowed/Denied Tags" +msgstr "Tambahkan Tag yang Diizinkan/Ditolak" + +#: cps/templates/config_view_edit.html:167 +msgid "Add Allowed/Denied custom column values" +msgstr "Tambahkan nilai kolom khusus yang Diizinkan/Ditolak" + +#: cps/templates/detail.html:77 cps/templates/detail.html:91 +msgid "Read in Browser" +msgstr "Baca di Peramban" + +#: cps/templates/detail.html:100 cps/templates/detail.html:120 +msgid "Listen in Browser" +msgstr "Dengarkan di Browser" + +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 +#, python-format +msgid "Book %(index)s of %(range)s" +msgstr "Buku" + +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 +msgid "Published" +msgstr "Diterbitkan" + +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 +msgid "Mark As Unread" +msgstr "Tandai sebagai Belum dibaca" + +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 +msgid "Mark As Read" +msgstr "Tandai sebagai dibaca" + +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 +msgid "Read" +msgstr "Baca" + +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 +msgid "Restore from archive" +msgstr "Pulihkan dari arsip" + +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 +msgid "Add to archive" +msgstr "Tambahkan ke Arsip" + +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 +msgid "Archived" +msgstr "Diarsipkan" + +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 +msgid "Description:" +msgstr "Deskripsi:" + +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 +msgid "Add to shelf" +msgstr "Tambah ke rak" + +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 +#: cps/templates/search.html:22 +msgid "(Public)" +msgstr "(Publik)" + +#: cps/templates/detail.html:339 +msgid "Edit Metadata" +msgstr "Edit Metadata" + +#: cps/templates/email_edit.html:13 +msgid "Email Account Type" +msgstr "Pilih Jenis Server" + +#: cps/templates/email_edit.html:15 +#, fuzzy +msgid "Standard Email Account" +msgstr "Gunakan Akun Email Standar" + +#: cps/templates/email_edit.html:16 +#, fuzzy +msgid "Gmail Account" +msgstr "Pilih Jenis Server" + +#: cps/templates/email_edit.html:22 +msgid "Setup Gmail Account" +msgstr "" + +#: cps/templates/email_edit.html:24 +msgid "Revoke Gmail Access" +msgstr "Cabut Akses G-Mail" + +#: cps/templates/email_edit.html:42 +msgid "STARTTLS" +msgstr "STARTTLS" + +#: cps/templates/email_edit.html:43 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: cps/templates/email_edit.html:51 +msgid "SMTP Password" +msgstr "Kata Sandi SMTP" + +#: cps/templates/email_edit.html:58 +msgid "Attachment Size Limit" +msgstr "Batas Ukuran Lampiran" + +#: cps/templates/email_edit.html:66 +#, fuzzy +msgid "Save and Send Test Email" +msgstr "Simpan dan Kirim Email Percobaan" + +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 +#: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 +msgid "Back" +msgstr "Kembali" + +#: cps/templates/email_edit.html:74 +msgid "Allowed Domains (Whitelist)" +msgstr "Domain yang Diizinkan (Daftar Putih)" + +#: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 +msgid "Add Domain" +msgstr "Tambahkan Domain" + +#: cps/templates/email_edit.html:81 cps/templates/email_edit.html:108 +#: cps/templates/user_table.html:27 +msgid "Add" +msgstr "Tambah" + +#: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 +msgid "Enter domainname" +msgstr "Masukkan Nama Domain" + +#: cps/templates/email_edit.html:92 +msgid "Denied Domains (Blacklist)" +msgstr "Domain yang Ditolak (Daftar Hitam)" + +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 +msgid "Next" +msgstr "Selanjutnya" + +#: cps/templates/generate_kobo_auth_url.html:6 +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Buka berkas .kobo/Kobo/Kobo eReader.conf di editor teks dan tambahkan (atau edit):" + +#: cps/templates/generate_kobo_auth_url.html:11 +msgid "Kobo Token:" +msgstr "Token Kobo:" + +#: cps/templates/grid.html:21 +msgid "List" +msgstr "Daftar" + +#: cps/templates/http_error.html:34 +msgid "Calibre-Web Instance is unconfigured, please contact your administrator" +msgstr "Instans Calibre-Web belum diatur, harap hubungi administrator Anda" + +#: cps/templates/http_error.html:44 +msgid "Create Issue" +msgstr "Buat Isu" + +#: cps/templates/http_error.html:51 +msgid "Return to Home" +msgstr "Kembali ke Beranda" + +#: cps/templates/http_error.html:53 +msgid "Logout User" +msgstr "Keluar Pengguna" + +#: cps/templates/index.html:71 +msgid "Sort ascending according to download count" +msgstr "Urutkan naik menurut jumlah unduhan" + +#: cps/templates/index.html:72 +msgid "Sort descending according to download count" +msgstr "Urutkan turun menurut jumlah unduhan" + +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 +msgid "Sort authors in alphabetical order" +msgstr "Urutkan penulis dalam urutan abjad" + +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 +msgid "Sort authors in reverse alphabetical order" +msgstr "Urutkan penulis dalam urutan abjad terbalik" + +#: cps/templates/index.html:83 +msgid "Sort ascending according to series index" +msgstr "Urutkan naik menurut indeks seri" + +#: cps/templates/index.html:84 +msgid "Sort descending according to series index" +msgstr "Urutkan menurun menurut indeks seri" + +#: cps/templates/index.xml:7 +msgid "Start" +msgstr "Mulai" + +#: cps/templates/index.xml:19 +msgid "Alphabetical Books" +msgstr "Buku Abjad" + +#: cps/templates/index.xml:23 +msgid "Books sorted alphabetically" +msgstr "Buku diurutkan menurut abjad" + +#: cps/templates/index.xml:30 +msgid "Popular publications from this catalog based on Downloads." +msgstr "Publikasi populer dari katalog ini berdasarkan Unduhan." + +#: cps/templates/index.xml:37 +msgid "Popular publications from this catalog based on Rating." +msgstr "Publikasi populer dari katalog ini berdasarkan Rating." + +#: cps/templates/index.xml:40 +msgid "Recently added Books" +msgstr "Buku yang baru ditambahkan" + +#: cps/templates/index.xml:44 +msgid "The latest Books" +msgstr "Buku-buku terbaru" + +#: cps/templates/index.xml:47 +msgid "Random Books" +msgstr "Buku Acak" + +#: cps/templates/index.xml:74 +msgid "Books ordered by Author" +msgstr "Buku yang diurutkan menurut Penulis" + +#: cps/templates/index.xml:81 +msgid "Books ordered by publisher" +msgstr "Buku yang diurutkan menurut Penerbit" + +#: cps/templates/index.xml:88 +msgid "Books ordered by category" +msgstr "Buku yang diurutkan menurut Kategori" + +#: cps/templates/index.xml:95 +msgid "Books ordered by series" +msgstr "Buku yang diurutkan menurut Seri" + +#: cps/templates/index.xml:102 +msgid "Books ordered by Languages" +msgstr "Buku yang diurutkan menurut Bahasa" + +#: cps/templates/index.xml:109 +msgid "Books ordered by Rating" +msgstr "Buku yang diurutkan menurut Peringkat" + +#: cps/templates/index.xml:117 +msgid "Books ordered by file formats" +msgstr "Buku yang diurutkan menurut format berkas" + +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 +msgid "Shelves" +msgstr "Rak" + +#: cps/templates/index.xml:124 +msgid "Books organized in shelves" +msgstr "本棚に整理された本" + +#: cps/templates/layout.html:26 cps/templates/login.html:30 +msgid "Home" +msgstr "Beranda" + +#: cps/templates/layout.html:32 +msgid "Toggle Navigation" +msgstr "Alihkan Navigasi" + +#: cps/templates/layout.html:47 +msgid "Search Library" +msgstr "Cari di Pustaka" + +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Akun" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Keluar" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Mengunggah..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Terjadi Kesalahan" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Unggahan selesai, harap tunggu, data sedang diproses..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Pengaturan" + +#: cps/templates/layout.html:135 +msgid "Please do not refresh the page" +msgstr "Harap jangan segarkan halaman" + +#: cps/templates/layout.html:145 +msgid "Browse" +msgstr "Jelajahi" + +#: cps/templates/layout.html:158 cps/templates/stats.html:3 +msgid "About" +msgstr "Tentang" + +#: cps/templates/layout.html:172 +msgid "Previous" +msgstr "Sebelumnya" + +#: cps/templates/layout.html:199 +msgid "Book Details" +msgstr "Detail Buku" + +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Terjadi Kesalahan" + +#: cps/templates/login.html:18 +msgid "Remember Me" +msgstr "Ingat saya" + +#: cps/templates/login.html:23 +msgid "Forgot Password?" +msgstr "Lupa Kata Sandi?" + +#: cps/templates/login.html:34 +msgid "Log in with Magic Link" +msgstr "Masuk dengan Magic Link" + +#: cps/templates/logviewer.html:6 +msgid "Show Calibre-Web Log: " +msgstr "Tampilkan Log Caliber-Web:" + +#: cps/templates/logviewer.html:8 +msgid "Calibre-Web Log: " +msgstr "Log Calibre-Web: " + +#: cps/templates/logviewer.html:8 +msgid "Stream output, can't be displayed" +msgstr "Output aliran, tidak dapat ditampilkan" + +#: cps/templates/logviewer.html:12 +msgid "Show Access Log: " +msgstr "Tampilkan Log Akses:" + +#: cps/templates/logviewer.html:18 +msgid "Download Calibre-Web Log" +msgstr "Unduh Calibre-Web Log" + +#: cps/templates/logviewer.html:21 +msgid "Download Access Log" +msgstr "Unduh Log Akses" + +#: cps/templates/modal_dialogs.html:6 +msgid "Select Allowed/Denied Tags" +msgstr "Pilih Tag yang Diizinkan/Ditolak" + +#: cps/templates/modal_dialogs.html:7 +msgid "Select Allowed/Denied Custom Column Values" +msgstr "Pilih Nilai Kolom Kustom yang Diizinkan/Ditolak" + +#: cps/templates/modal_dialogs.html:8 +msgid "Select Allowed/Denied Tags of User" +msgstr "Pilih Tag Pengguna yang Diizinkan/Ditolak" + +#: cps/templates/modal_dialogs.html:9 +msgid "Select Allowed/Denied Custom Column Values of User" +msgstr "Pilih Nilai Kolom Pengguna yang Diizinkan/Ditolak" + +#: cps/templates/modal_dialogs.html:15 +msgid "Enter Tag" +msgstr "Masukkan Tag" + +#: cps/templates/modal_dialogs.html:24 +msgid "Add View Restriction" +msgstr "Tambahkan Batasan Tampilan" + +#: cps/templates/modal_dialogs.html:50 +msgid "This book format will be permanently erased from database" +msgstr "Format buku ini akan dihapus secara permanen dari database" + +#: cps/templates/modal_dialogs.html:51 +msgid "This book will be permanently erased from database" +msgstr "Buku ini akan dihapus secara permanen dari basis data" + +#: cps/templates/modal_dialogs.html:52 +msgid "and hard disk" +msgstr "dan harddisk" + +#: cps/templates/modal_dialogs.html:56 +msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." +msgstr "Catatan Penting Kobo: buku yang dihapus akan tetap ada di perangkat Kobo yang telah dipasangkan." + +#: cps/templates/modal_dialogs.html:57 +msgid "Books must first be archived and the device synced before a book can safely be deleted." +msgstr "Buku harus diarsipkan terlebih dahulu dan perangkat disinkronkan sebelum buku dapat dihapus dengan aman." + +#: cps/templates/modal_dialogs.html:76 +msgid "Choose File Location" +msgstr "Pilih Lokasi Berkas" + +#: cps/templates/modal_dialogs.html:82 +msgid "type" +msgstr "tipe" + +#: cps/templates/modal_dialogs.html:83 +msgid "name" +msgstr "nama" + +#: cps/templates/modal_dialogs.html:84 +msgid "size" +msgstr "ukuran" + +#: cps/templates/modal_dialogs.html:90 +msgid "Parent Directory" +msgstr "Direktori Induk" + +#: cps/templates/modal_dialogs.html:98 +msgid "Select" +msgstr "Pilih" + +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 +msgid "Ok" +msgstr "Ok" + +#: cps/templates/osd.xml:5 +msgid "Calibre-Web eBook Catalog" +msgstr "Katalog eBook Calibre-Web" + +#: cps/templates/read.html:6 +msgid "epub Reader" +msgstr "Pembaca EPUB" + +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Terang" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Gelap" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "Sepia" + +#: cps/templates/read.html:84 +msgid "Black" +msgstr "Hitam" + +#: cps/templates/read.html:88 +msgid "Reflow text when sidebars are open." +msgstr "Reflow teks saat sidebar terbuka." + +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 +msgid "Comic Reader" +msgstr "Pembaca Komik" + +#: cps/templates/readcbr.html:75 +msgid "Keyboard Shortcuts" +msgstr "Pintasan Keyboard" + +#: cps/templates/readcbr.html:78 +msgid "Previous Page" +msgstr "Halaman Sebelumnya" + +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 +msgid "Next Page" +msgstr "Halaman Selanjutnya" + +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 +msgid "Scale to Best" +msgstr "Skala ke Terbaik" + +#: cps/templates/readcbr.html:83 +msgid "Scale to Width" +msgstr "Skala ke Lebar" + +#: cps/templates/readcbr.html:84 +msgid "Scale to Height" +msgstr "Skala ke Tinggi" + +#: cps/templates/readcbr.html:85 +msgid "Scale to Native" +msgstr "Skalakan ke Asli" + +#: cps/templates/readcbr.html:86 +msgid "Rotate Right" +msgstr "Putar ke Kanan" + +#: cps/templates/readcbr.html:87 +msgid "Rotate Left" +msgstr "Putar ke Kiri" + +#: cps/templates/readcbr.html:88 +msgid "Flip Image" +msgstr "Balikkan Gambar" + +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Halaman Admin" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 +msgid "Scale" +msgstr "Skala" + +#: cps/templates/readcbr.html:122 +msgid "Best" +msgstr "Terbaik" + +#: cps/templates/readcbr.html:123 +msgid "Width" +msgstr "Lebar" + +#: cps/templates/readcbr.html:124 +msgid "Height" +msgstr "Tinggi" + +#: cps/templates/readcbr.html:125 +msgid "Native" +msgstr "Asli" + +#: cps/templates/readcbr.html:130 +msgid "Rotate" +msgstr "Putar" + +#: cps/templates/readcbr.html:141 +msgid "Flip" +msgstr "Balik" + +#: cps/templates/readcbr.html:144 +msgid "Horizontal" +msgstr "Horizontal" + +#: cps/templates/readcbr.html:145 +msgid "Vertical" +msgstr "Vertical" + +#: cps/templates/readcbr.html:150 +msgid "Direction" +msgstr "Arah Baca" + +#: cps/templates/readcbr.html:153 +msgid "Left to Right" +msgstr "Kiri ke Kanan" + +#: cps/templates/readcbr.html:154 +msgid "Right to Left" +msgstr "Kanan ke Kiri" + +#: cps/templates/readcbr.html:162 +msgid "Reset to Top" +msgstr "" + +#: cps/templates/readcbr.html:163 +msgid "Remember Position" +msgstr "" + +#: cps/templates/readcbr.html:168 +msgid "Scrollbar" +msgstr "Scrollbar" + +#: cps/templates/readcbr.html:171 +msgid "Show" +msgstr "Tampilkan" + +#: cps/templates/readcbr.html:172 +msgid "Hide" +msgstr "Sembunyikan" + +#: cps/templates/readdjvu.html:5 +msgid "DJVU Reader" +msgstr "Pembaca DJVU" + +#: cps/templates/readpdf.html:32 +msgid "PDF Reader" +msgstr "Pembaca PDF" + +#: cps/templates/readtxt.html:6 +msgid "txt Reader" +msgstr "Pembaca txt" + +#: cps/templates/register.html:4 +msgid "Register New Account" +msgstr "Daftar Akun Baru" + +#: cps/templates/register.html:10 +msgid "Choose a username" +msgstr "Pilih nama pengguna" + +#: cps/templates/register.html:15 +msgid "Your Email" +msgstr "Alamat email Anda" + +#: cps/templates/remote_login.html:5 +msgid "Magic Link - Authorise New Device" +msgstr "Magic Link - Otorisasi Perangkat Baru" + +#: cps/templates/remote_login.html:7 +msgid "On another device, login and visit:" +msgstr "Di perangkat lain, masuk dan kunjungi:" + +#: cps/templates/remote_login.html:11 +msgid "Once verified, you will automatically be logged in on this device." +msgstr "Setelah diverifikasi, Anda akan secara otomatis masuk ke perangkat ini." + +#: cps/templates/remote_login.html:14 +msgid "This verification link will expire in 10 minutes." +msgstr "Tautan verifikasi ini akan kedaluwarsa dalam 10 menit." + +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Hasilkan Thumbnail Sampul Seri" + +#: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "Tidak ada hasil yang ditemukan" + +#: cps/templates/search.html:7 +msgid "Search Term:" +msgstr "Istilah Penelusuran:" + +#: cps/templates/search.html:9 +msgid "Results for:" +msgstr "Hasil untuk:" + +#: cps/templates/search_form.html:21 +msgid "Published Date From" +msgstr "Tanggal Diterbitkan Dari" + +#: cps/templates/search_form.html:31 +msgid "Published Date To" +msgstr "Tanggal Diterbitkan Hingga" + +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 +msgid "Exclude Tags" +msgstr "Kecualikan Tag" + +#: cps/templates/search_form.html:78 +msgid "Exclude Series" +msgstr "Kecualikan Seri" + +#: cps/templates/search_form.html:96 +msgid "Exclude Shelves" +msgstr "Kecualikan Rak" + +#: cps/templates/search_form.html:116 +msgid "Exclude Languages" +msgstr "Kecualikan Bahasa" + +#: cps/templates/search_form.html:127 +msgid "Extensions" +msgstr "Ekstensi" + +#: cps/templates/search_form.html:135 +msgid "Exclude Extensions" +msgstr "Kecualikan Ekstensi" + +#: cps/templates/search_form.html:145 +msgid "Rating Above" +msgstr "Peringkat Diatas" + +#: cps/templates/search_form.html:149 +msgid "Rating Below" +msgstr "Peringkat Dibawah" + +#: cps/templates/search_form.html:181 +msgid "From:" +msgstr "Dari:" + +#: cps/templates/search_form.html:191 +msgid "To:" +msgstr "Hingga:" + +#: cps/templates/shelf.html:13 +msgid "Delete this Shelf" +msgstr "Hapus rak ini" + +#: cps/templates/shelf.html:14 +msgid "Edit Shelf Properties" +msgstr "Edit Properti Rak" + +#: cps/templates/shelf.html:17 +msgid "Arrange books manually" +msgstr "Atur buku secara manual" + +#: cps/templates/shelf.html:18 +msgid "Disable Change order" +msgstr "Nonaktifkan Ubah urutan" + +#: cps/templates/shelf.html:18 +msgid "Enable Change order" +msgstr "Aktifkan Ubah urutan" + +#: cps/templates/shelf_edit.html:14 +msgid "Share with Everyone" +msgstr "Bagikan dengan Semua Orang" + +#: cps/templates/shelf_edit.html:21 +msgid "Sync this shelf with Kobo device" +msgstr "Sinkronkan rak ini dengan perangkat Kobo" + +#: cps/templates/shelf_order.html:5 +msgid "Drag to Rearrange Order" +msgstr "Seret untuk Mengatur Ulang Urutan" + +#: cps/templates/shelf_order.html:33 +msgid "Hidden Book" +msgstr "Buku Tersembunyi" + +#: cps/templates/stats.html:7 +msgid "Library Statistics" +msgstr "Statistik Pustaka" + +#: cps/templates/stats.html:12 +msgid "Books in this Library" +msgstr "Buku dalam Pustaka Ini" + +#: cps/templates/stats.html:16 +msgid "Authors in this Library" +msgstr "Penulis dalam Pustaka Ini" + +#: cps/templates/stats.html:20 +msgid "Categories in this Library" +msgstr "Kategori dalam Pustaka Ini" + +#: cps/templates/stats.html:24 +msgid "Series in this Library" +msgstr "Seri dalam Pustaka Ini" + +#: cps/templates/stats.html:29 +msgid "System Statistics" +msgstr "Statistik Sistem" + +#: cps/templates/stats.html:33 +msgid "Program" +msgstr "Pustaka Program" + +#: cps/templates/stats.html:34 +msgid "Installed Version" +msgstr "Versi Terpasang" + +#: cps/templates/tasks.html:12 +msgid "User" +msgstr "Pengguna" + +#: cps/templates/tasks.html:14 +msgid "Task" +msgstr "Tugas" + +#: cps/templates/tasks.html:15 +msgid "Status" +msgstr "Status" + +#: cps/templates/tasks.html:16 +msgid "Progress" +msgstr "Kemajuan" + +#: cps/templates/tasks.html:17 +msgid "Run Time" +msgstr "Waktu Jalan" + +#: cps/templates/tasks.html:20 +msgid "Actions" +msgstr "Tindakan" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +msgstr "Tugas ini akan dibatalkan. Setiap kemajuan yang dibuat oleh tugas ini akan disimpan." + +#: cps/templates/tasks.html:41 +msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." +msgstr "Jika ini adalah tugas terjadwal, ini akan dijalankan ulang selama waktu terjadwal berikutnya." + +#: cps/templates/user_edit.html:20 +msgid "Reset user Password" +msgstr "Atur ulang kata sandi pengguna" + +#: cps/templates/user_edit.html:43 +msgid "Language of Books" +msgstr "Bahasa Buku" + +#: cps/templates/user_edit.html:54 +msgid "OAuth Settings" +msgstr "Pengaturan OAuth" + +#: cps/templates/user_edit.html:56 +msgid "Link" +msgstr "Tautan" + +#: cps/templates/user_edit.html:58 +msgid "Unlink" +msgstr "Batalkan tautan" + +#: cps/templates/user_edit.html:64 +msgid "Kobo Sync Token" +msgstr "Token Kobo Sync" + +#: cps/templates/user_edit.html:66 +msgid "Create/View" +msgstr "Buat/Lihat" + +#: cps/templates/user_edit.html:70 +msgid "Force full kobo sync" +msgstr "Paksa sinkronisasi kobo penuh" + +#: cps/templates/user_edit.html:88 +msgid "Add allowed/Denied Custom Column Values" +msgstr "Tambahkan Nilai Kolom Kustom yang Diizinkan/Ditolak" + +#: cps/templates/user_edit.html:137 +msgid "Sync only books in selected shelves with Kobo" +msgstr "Sinkronkan hanya buku di rak yang dipilih dengan Kobo" + +#: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 +msgid "Delete User" +msgstr "Hapus Pengguna" + +#: cps/templates/user_edit.html:159 +msgid "Generate Kobo Auth URL" +msgstr "Hasilkan URL Autentikasi Kobo" + +#: cps/templates/user_table.html:80 cps/templates/user_table.html:103 +msgid "Select..." +msgstr "Pilih..." + +#: cps/templates/user_table.html:131 +msgid "Edit User" +msgstr "Edit Pengguna" + +#: cps/templates/user_table.html:134 +msgid "Enter Username" +msgstr "Masukkan Nama Pengguna" + +#: cps/templates/user_table.html:135 +#, fuzzy +msgid "Enter Email" +msgstr "Email tes" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "Enter eReader Email" +msgstr "Alamat E-mail untuk Kirim ke E-Reader" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "eReader Email" +msgstr "Email E-Reader" + +#: cps/templates/user_table.html:137 +msgid "Locale" +msgstr "Lokal" + +#: cps/templates/user_table.html:138 +msgid "Visible Book Languages" +msgstr "Bahasa Buku Terlihat" + +#: cps/templates/user_table.html:139 +msgid "Edit Allowed Tags" +msgstr "Edit Tag yang Diizinkan" + +#: cps/templates/user_table.html:139 +msgid "Allowed Tags" +msgstr "Tag yang Diizinkan" + +#: cps/templates/user_table.html:140 +msgid "Edit Denied Tags" +msgstr "Edit Tag yang Ditolak" + +#: cps/templates/user_table.html:140 +msgid "Denied Tags" +msgstr "Tag yang Ditolak" + +#: cps/templates/user_table.html:141 +msgid "Edit Allowed Column Values" +msgstr "Edit Nilai Kolom yang Diizinkan" + +#: cps/templates/user_table.html:141 +msgid "Allowed Column Values" +msgstr "Nilai Kolom yang Diizinkan" + +#: cps/templates/user_table.html:142 +msgid "Edit Denied Column Values" +msgstr "Edit Nilai Kolom yang Ditolak" + +#: cps/templates/user_table.html:142 +msgid "Denied Column Values" +msgstr "Nilai Kolom yang Ditolak" + +#: cps/templates/user_table.html:144 +msgid "Change Password" +msgstr "Ubah Kata Sandi" + +#: cps/templates/user_table.html:147 +msgid "View" +msgstr "Tampilan" + +#: cps/templates/user_table.html:150 +msgid "Edit Public Shelves" +msgstr "Edit Rak Publik" + +#: cps/templates/user_table.html:152 +msgid "Sync selected Shelves with Kobo" +msgstr "Sinkronkan Rak yang dipilih dengan Kob" + +#: cps/templates/user_table.html:156 +#, fuzzy +msgid "Show Read/Unread Section" +msgstr "Tampilkan pilihan baca/belum dibaca" + diff --git a/cps/translations/it/LC_MESSAGES/messages.mo b/cps/translations/it/LC_MESSAGES/messages.mo index 6192fe82..ec2d16d5 100644 Binary files a/cps/translations/it/LC_MESSAGES/messages.mo and b/cps/translations/it/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/it/LC_MESSAGES/messages.po b/cps/translations/it/LC_MESSAGES/messages.po index 76181077..40f5ad5a 100644 --- a/cps/translations/it/LC_MESSAGES/messages.po +++ b/cps/translations/it/LC_MESSAGES/messages.po @@ -2,499 +2,507 @@ # Copyright (C) 2016 Smart Cities Community # This file is distributed under the same license as the Calibre-Web # Juan F. Villa , 2016. +# SPDX-FileCopyrightText: 2023 Massimo Pissarello msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" -"PO-Revision-Date: 2017-04-04 15:09+0200\n" -"Last-Translator: ElQuimm \n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" +"PO-Revision-Date: 2023-10-21 15:27+0200\n" +"Last-Translator: Massimo Pissarello \n" "Language: it\n" -"Language-Team: \n" +"Language-Team: Italian <>\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statistiche" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +msgid "Server restarted, please reload page." msgstr "Server riavviato, per favore ricarica la pagina" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +msgid "Performing Server shutdown, please close window." msgstr "Eseguo l'arresto del server, per favore chiudi la finestra" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Ricollegato con successo" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "Tutto OK! Database riconnesso" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Comando sconosciuto" -#: cps/admin.py:169 -msgid "Books successfully queued for Metadata Backup" -msgstr "Libro accodato con successo per il backup dei metadati" +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Tutto OK! Libri in coda per il backup dei metadati, controlla le attività per il risultato" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Sconosciuto" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Pagina di amministrazione" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configurazione di base" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configurazione dell'interfaccia utente" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Modifica gli utenti" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Tutti" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Utente non trovato" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" -msgstr "{} utente eliminato con successo" +msgstr "{} utenti eliminati con successo" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" -msgstr "tutte le lingue presenti" +msgstr "Mostra tutto" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Richiesta non formulata correttamente" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Il nome dell'utente Guest (ospite) non può essere modificato" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "L'utente Guest (ospite) non può avere questo ruolo" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Non rimarrebbe nessun utente amministratore, non posso rimuovere il ruolo di amministratore" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" -msgstr "Il valore deve essere o vero o flaso" +msgstr "Il valore deve essere o vero o falso" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ruolo non valido" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" -msgstr "L'utente Guest (ospite) non può avere questa schermata" +msgstr "L'utente Guest (ospite) non può visualizzare questa schermata" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" -msgstr "Visualizzazione invalida" +msgstr "Visualizzazione non valida" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Le impostazioni locali dell'utente Guest (ospite) sono determinate automaticamente e non possono essere configurate" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Nessuna lingua valida indicata" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Nessuna lingua valida per il libro" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parametro non trovato" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Colonna di lettura non valida" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Colonna con restrizioni non valida" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "La configurazione di Calibre-Web è stata aggiornata" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Vuoi veramente eliminare il token di Kobo?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Vuoi veramente eliminare questo dominio?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Vuoi veramente eliminare questo utente?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Vuoi veramente eliminare questo scaffale?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Sei sicuro di voler modificare le impostazioni locali del/degli utente/i selezionato/i?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" -msgstr "Sei sicuro di voler modificare le impostazioni delle lingue visualizzabili del/degli utente/i selezionato/i?" +msgstr "Sei sicuro di voler modificare le impostazioni delle lingue visualizzabili dall'/dagli utente/i selezionato/i?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Sei sicuro di voler modificare il ruolo evidenziato del/degli utente/i selezionato/i?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Sei sicuro di voler modificare le restrizioni selezionate del/degli utente/i selezionato/i?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" -msgstr "Sei sicuro di voler modificare le restrizioni di visualizzazione del/degli utente/i selezionato/i?" +msgstr "Sei sicuro di voler modificare le restrizioni di visibilità selezionate per l'utente(i) selezionato(i)?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Sei sicuro di voler modificare il comportamento di sincronizzazione dello scaffale per l'/gli utente/i selezionato/i?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "Sei sicuro di voler modificare la posizione della libreria di Calibre?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "Calibre-Web cercherà le copertine aggiornate e aggiornerà le miniature delle copertine, questo richiederà un po' di tempo." -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" -msgstr "Sei sicuro di voler eliminare il database sincoronizzato di Calibre-Web e forzare una sincronizzazione completa con il tuo lettore Kobo?" +msgstr "Sei sicuro di voler eliminare il database sincronizzato di Calibre-Web e forzare una sincronizzazione completa con il tuo lettore Kobo?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Nega" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Permetti" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" -msgstr "{} eliminate voci di sincronizzazione" +msgstr "{} voci di sincronizzazione eliminate" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Etichetta non trovata" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Azione non valida" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json non è configurato per Web Application" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" -msgstr "La posizione del Logfile non è valida, per favore indica il percorso corretto" +msgstr "La posizione del file di log non è valida, per favore indica il percorso corretto" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" -msgstr "La posizione dell'Access Logfile non è valida, per favore indica il percorso corretto" +msgstr "La posizione del file di log di accesso non è valida, per favore indica il percorso corretto" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Per favore digita un Provider LDAP, porta, DN e User Object Identifier" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "Per favore digita nome di utente e password del servizio LDAP" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Per favore indica un account di servizio LDAP" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP Group Object Filter deve avere un \"%s\" Format Identifier" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" -msgstr "LDAP Group Object Filter contiene una parentesi senza la corrispettiva" +msgstr "LDAP Group Object Filter contiene una parentesi senza la corrispondenza" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP User Object Filter deve avere un \"%s\" Format Identifier" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" -msgstr "LDAP User Object Filter contiene una parentesi senza la corrispettiva" +msgstr "LDAP User Object Filter contiene una parentesi senza la corrispondenza" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP Member User Filter deve avere un \"%s\" Format Identifier" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" -msgstr "LDAP Member User Filter contiene una parentesi senza la corrispettiva" +msgstr "LDAP Member User Filter contiene una parentesi senza la corrispondenza" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CACertificate, il certificato o la posizione della chiave non sono corretti, per favore indica il percorso corretto" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Aggiungi un nuovo utente" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Modifica le impostazioni del server e-mail" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "L'account Gmail è stato verificato con successo" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Tutto OK! Account Gmail verificato." -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Errore nel database: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" -msgstr "L'e-mail di test è stato accodato con successo per essere spedito a %(email)s, per favore verifica tramite il pulsante 'Compito' il risultato" +msgstr "L'e-mail di test è stato accodata con successo per essere spedita a %(email)s, per favore controlla le attività per il risultato" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Si è verificato un errore nell'invio dell'e-mail di test: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Per favore prima configura il tuo indirizzo e-mail..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" -msgstr "Configurazione del server e-mail aggiornata" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Le impostazioni del server e-mail sono state aggiornate" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "Modifica le impostazioni delle attività pianificate" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "Ora di inizio non valida per l'attività specificata" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "Durata non valida per l'attività specificata" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "Impostazioni delle attività pianificate aggiornate" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Si è verificato un errore sconosciuto: per favore riprova." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "Il DB delle impostazioni non è scrivibile" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Modifica l'utente %(nick)s" -#: cps/admin.py:1411 +#: cps/admin.py:1436 #, python-format -msgid "Password for user %(user)s reset" -msgstr "La password dell'utente %(user)s è stata resettata" +msgid "Success! Password for user %(user)s reset" +msgstr "Tutto OK! Reimpostazione della password per l'utente %(user)s" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." -msgstr "Configura dapprima le impostazioni del server SMTP..." +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." +msgstr "Configura prima le impostazioni del server SMTP." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" -msgstr "Visualizzatore del Logfile" +msgstr "Visualizzatore del file di log" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" -msgstr "Richiedo il pacchetto di aggiornamento" +msgstr "Richiesta del pacchetto di aggiornamento" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" -msgstr "Scarico il pacchetto di aggiornamento" +msgstr "Download del pacchetto di aggiornamento" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" -msgstr "Decomprimo il pacchetto di aggiornamento" +msgstr "Decompressione del pacchetto di aggiornamento" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" -msgstr "Sostituisco i file" +msgstr "Sostituzione dei file" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Le connessioni al database sono chiuse" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" -msgstr "Arresto il server" +msgstr "Arresto del server" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Aggiornamento completato, per favore premi ok e ricarica la pagina" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Aggiornamento non riuscito:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Errore HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Errore di connessione" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Tempo scaduto nello stabilire la connessione" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Errore generale" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "Il file di aggiornamento non può essere salvato nella cartella temporanea" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "Durante l'aggiornamento non è stato possibile sostituire alcuni file" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" -msgstr "Fallita l'estrazione di almeno un utente LDAP" +msgstr "Impossibile estrarre almeno un utente LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" -msgstr "Fallita la creazione di almeno un utente LDAP" +msgstr "Impossibile creare almeno un utente LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Errore: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Errore: nessun utente restituito in risposta dal server LDAP" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" -msgstr "Almeno un utente LDAP non è stato trovato nel database" +msgstr "Non è stato trovato nessun utente LDAP nel database" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} utente importato con successo" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "La posizione del DB non è valida, per favore indica il percorso corretto" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "Il DB non è scrivibile" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "La posizione del Keyfile non è valida, per favore indica il percorso corretto" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "La posizione del Certfile non è valida, per favore indica il percorso corretto" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "La lunghezza della password deve essere compresa tra 1 e 40" + +#: cps/admin.py:1871 msgid "Database Settings updated" -msgstr "Configurazione del Database aggiornata" +msgstr "Impostazioni database aggiornate" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" -msgstr "Configurazione del Database" +msgstr "Configurazione del database" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Per favore compila tutti i campi!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "L'e-mail non proviene da un dominio valido" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Aggiungi un nuovo utente" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "L'utente '%(user)s' è stato creato" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." -msgstr "Trovato un account esistente con questo e-mail o nome di utente" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "Trovato un account esistente con questa e-mail o nome utente" -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "L'utente '%(nick)s' è stato eliminato" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Non posso eliminare l'utente Guest (ospite)" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Non rimarrebbe nessun utente amministratore, non posso eliminare l'utente" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "L'indirizzo e-mail non può essere vuoto e deve essere un recapito valido" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "L'utente '%(nick)s' è stato aggiornato" @@ -507,122 +515,122 @@ msgstr "non installato" msgid "Execution permissions missing" msgstr "Mancano i permessi di esecuzione" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 -#, fuzzy, python-format +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 +#, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "La colonna personalizzata no.%(column)d non esiste nel database di Calibre" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Nessuna" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" -msgstr "Errore durante l'apertura del libro selezionato. Il file non esiste o il file non è accessibile" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" +msgstr "Il libro selezionato non è disponibile. Il file non esiste o non è accessibile" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "L'utente non ha i permessi per caricare le copertine" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" -msgstr "Gli identificatori non tengono conto delle lettere maiuscole o minuscole, sovrascrivo l'identificatore precedente" +msgstr "Gli identificatori non fanno distinzione tra maiuscole e minuscole, sovrascrivendo il vecchio identificatore" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "I metadati sono stati aggiornati con successo" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "Errore durante la modifica del libro: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Il file %(file)s è stato caricato" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Mancano o il formato sorgente o quello di destinazione, entrambi necessari alla conversione" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Libro accodato con successo per essere convertito in %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Si è verificato un errore durante la conversione del libro: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " -msgstr "Probabilmente il libro caricato esiste già nella libreria; considera di cambiarlo prima di sottoporlo nuovamente: " +msgstr "Probabilmente il libro caricato esiste già nella libreria, cambialo prima di caricarlo nuovamente:" -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s non è una lingua valida" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Non è consentito caricare file con l'estensione '%(ext)s' su questo server" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Il file da caricare deve avere un'estensione" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Il file %(filename)s non può essere salvato nella cartella temporanea" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Impossibile spostare il file della copertina %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Il formato del libro è stato eliminato con successo" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" -msgstr "Il libro é stato eliminato con successo" +msgstr "Il libro è stato eliminato con successo" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" -msgstr "Non disponi delle autorizzazioni per eliminare libri" +msgstr "Mancano le autorizzazioni per eliminare i libri" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "modifica i metadati" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" -msgstr "%(seriesindex)s non è un numero valido, vado oltre" +msgstr "%(seriesindex)s non è un numero valido, lo salto" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "L'utente non ha i permessi per caricare formati di file aggiuntivi" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." -msgstr "Impossibile creare la cartella %(path)s (autorizzazione negata)." +msgstr "Impossibile creare il percorso %(path)s (autorizzazione negata)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Il salvataggio del file %(file)s non è riuscito." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Ho aggiunto il formato %(ext)s al libro %(book)s" @@ -633,180 +641,183 @@ msgstr "La configurazione di Google Drive non è stata completata correttamente. #: cps/gdrive.py:95 msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" -msgstr "Callback domain non è stato verificato. Per favore intraprendi il necessario per verificare il dominio nella developer console di Google" +msgstr "Il dominio di callback non è stato verificato. Per favore segui i passaggi per verificare il dominio nella console per sviluppatori di Google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "Formato %(format)s non trovato per il libro: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s non trovato su Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s non trovato: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 -msgid "Send to E-Reader" -msgstr "Invia al lettore elettronico" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" +msgstr "Invia all'eReader" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." -msgstr "Questo e-mail è stato spedito tramite Calibre-Web." - -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" -msgstr "E-mail di test da Calibre-Web" +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +msgid "This Email has been sent via Calibre-Web." +msgstr "Questa e-mail è stata inviata tramite Calibre-Web." #: cps/helper.py:115 -msgid "Test e-mail" -msgstr "E-mail di test" +msgid "Calibre-Web Test Email" +msgstr "E-mail di prova di Calibre-Web" -#: cps/helper.py:132 +#: cps/helper.py:116 +msgid "Test Email" +msgstr "E-mail di prova" + +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Inizia con Calibre-Web" -#: cps/helper.py:137 +#: cps/helper.py:138 #, python-format -msgid "Registration e-mail for user: %(name)s" -msgstr "E-mail di registrazione dell'utente: %(name)s" +msgid "Registration Email for user: %(name)s" +msgstr "E-mail di registrazione per l'utente: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" -msgstr "Converti %(orig)s in %(format)s e al lettore elettronico" +msgid "Convert %(orig)s to %(format)s and send to eReader" +msgstr "Converti %(orig)s in %(format)s e invia all'eReader" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to E-Reader" -msgstr "Invia %(format)s al lettore elettronico" +msgid "Send %(format)s to eReader" +msgstr "Invia %(format)s all'eReader" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to E-Reader" -msgstr "%(book)s inviato al lettore elettronico" +msgid "%(book)s send to eReader" +msgstr "%(book)s inviato all'eReader" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Il file richiesto non può essere letto. I permessi sono corretti?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "Impossibile impostare lo stato di lettura: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" -msgstr "L'eliminazione della cartella del libro %(id)s non è riuscita, il percorso ha sottocartelle: %(path)s" +msgstr "L'eliminazione della cartella del libro %(id)s non è riuscita, il percorso ha delle sottocartelle: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "L'eliminazione del libro %(id)s non è riuscita: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Eliminazione del libro %(id)s unicamente dal database. Il percorso del libro nel database non è valido: %(path)s" -#: cps/helper.py:450 -#, fuzzy, python-format +#: cps/helper.py:447 +#, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" -msgstr "La modifica del titolo da '%(src)s' a '%(dest)s' è terminata con l'errore: %(error)s" +msgstr "La modifica dell'autore da '%(src)s' a '%(dest)s' è terminata con l'errore: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "File %(file)s non trovato su Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "La modifica del titolo da '%(src)s' a '%(dest)s' è terminata con l'errore: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "Errore nel rinominare il file nel percorso: {}" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" -msgstr "Non ho trovato la cartella %(path)s del libro su Google Drive" +msgstr "Percorso del libro %(path)s non trovato su Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "Ho trovato un account creato in precedenza con questo indirizzo e-mail." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "Trovato un account esistente per questo indirizzo e-mail" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Questo nome di utente è già utilizzato" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" -msgstr "L'e-mail non è scritto in un formato valido" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "Formato dell'indirizzo e-mail non valido" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "La password non è conforme alle regole di convalida della password" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "Il modulo Python 'advocate' non è installato, ma è necessario per caricare le copertine" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Errore nello scaricare la copertina" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" -msgstr "Errore di formato della copertina" +msgstr "Errore nel formato della copertina" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "Non sei autorizzato ad accedere a localhost o alla rete locale per caricare le copertine" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" -msgstr "Errore nel creare la cartella per la copertina" +msgstr "Errore nel creare il percorso per la copertina" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Il file della copertina non è in un formato immagine valido o non può essere salvato" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Solamente i file nei formati jpg/jpeg/png/webp/bmp sono supportati per le copertine" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "Contenuto del file di copertina non valido" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Solamente i file nei formati jpg/jpeg sono supportati per le copertine" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Non ho trovato il file binario di UnRar" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "Errore nell'eseguire UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 msgid "Cover" msgstr "Copertina" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "Metti in coda tutti i libri per il backup dei metadati" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" -msgstr "Per favore accedi a Calibe-Web non da localhost per ottenere un api-endpoint valido per il lettore kobo" +msgstr "Per favore accedi a Calibe-Web non da localhost per ottenere un api_endpoint valido per il lettore kobo" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configurazione di Kobo" @@ -815,10 +826,10 @@ msgstr "Configurazione di Kobo" msgid "Register with %(provider)s" msgstr "Registra con %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" -msgstr "ora sei connesso come: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" +msgstr "Tutto OK! Ora sei connesso come: %(nickname)s" #: cps/oauth_bb.py:148 #, python-format @@ -827,17 +838,17 @@ msgstr "Collegamento a %(oauth)s avvenuto con successo" #: cps/oauth_bb.py:155 msgid "Login failed, No User Linked With OAuth Account" -msgstr "Accesso non riuscito, non c'è un utente collegato all'account OAuth" +msgstr "Accesso non riuscito, non c'è nessun utente collegato all'account OAuth" #: cps/oauth_bb.py:197 #, python-format msgid "Unlink to %(oauth)s Succeeded" -msgstr "Scollegamento da %(oauth)s avvenuto con successo" +msgstr "Scollegamento da %(oauth)s riuscito" #: cps/oauth_bb.py:202 #, python-format msgid "Unlink to %(oauth)s Failed" -msgstr "Scollegamento da %(oauth)s non riuscito" +msgstr "Scollegamento da %(oauth)s non riuscito" #: cps/oauth_bb.py:205 #, python-format @@ -846,19 +857,19 @@ msgstr "Non collegato a %(oauth)s" #: cps/oauth_bb.py:261 msgid "Failed to log in with GitHub." -msgstr "Accesso con GitHub non è riuscito." +msgstr "Impossibile accedere con GitHub." #: cps/oauth_bb.py:267 msgid "Failed to fetch user info from GitHub." -msgstr "Il recupero delle informazioni dell'utente da GitHub non è riuscito." +msgstr "Impossibile recuperare le informazioni utente da GitHub." #: cps/oauth_bb.py:279 msgid "Failed to log in with Google." -msgstr "L'accesso con Google non è riuscito." +msgstr "Impossibile accedere con Google." #: cps/oauth_bb.py:285 msgid "Failed to fetch user info from Google." -msgstr "Il recupero delle informazioni dell'utente da Google non è riuscito." +msgstr "Impossibile recuperare le informazioni utente da Google." #: cps/oauth_bb.py:332 msgid "GitHub Oauth error, please retry later." @@ -876,12 +887,13 @@ msgstr "Google, errore Oauth: per favore riprova più tardi." msgid "Google Oauth error: {}" msgstr "Google, errore Oauth: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Stelle" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Accesso" @@ -895,151 +907,151 @@ msgstr "Il token è scaduto" #: cps/remotelogin.py:92 msgid "Success! Please return to your device" -msgstr "Riuscito! Torna al tuo dispositivo" +msgstr "Tutto OK! Torna al tuo dispositivo" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Libri" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" -msgstr "Mostra l'opzione per la selezione dei libri più recenti" +msgstr "Mostra i libri recenti" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" -msgstr "Libri popolari" +msgstr "Libri hot" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" -msgstr "Mostra l'opzione per la selezione dei libri più popolari" +msgstr "Mostra i libri hot" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Libri scaricati" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" -msgstr "Mostra l'opzione per la visualizzazione dei libri scaricati" +msgstr "Mostra i libri scaricati" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" -msgstr "Libri meglio valutati" +msgstr "Libri più votati" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" -msgstr "Mostra l'opzione per la selezione dei libri meglio valutati" +msgstr "Mostra i libri più votati" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Libri letti" -#: cps/render_template.py:62 -msgid "Show read and unread" -msgstr "Mostra l'opzione per la selezione letto e non letto" +#: cps/render_template.py:64 +msgid "Show Read and Unread" +msgstr "Mostra i libri letti e da leggere" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" -msgstr "Libri non letti" +msgstr "Libri da leggere" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" -msgstr "Mostra l'opzione per la selezione dei libri non letti" +msgstr "Mostra da leggere" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" -msgstr "Per scoprire" +msgstr "Da scoprire" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" -msgstr "Mostra libri casualmente" +msgstr "Mostra i libri casualmente" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Categorie" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" -msgstr "Mostra l'opzione per la selezione delle categorie" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +msgid "Show Category Section" +msgstr "Mostra la sezione delle categorie" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Serie" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" -msgstr "Mostra l'opzione per la selezione delle serie" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +msgid "Show Series Section" +msgstr "Mostra la sezione delle serie" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Autori" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" -msgstr "Mostra l'opzione per la selezione degli autori" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +msgid "Show Author Section" +msgstr "Mostra la sezione degli autori" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Editori" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" -msgstr "Mostra l'opzione per la selezione degli editori" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +msgid "Show Publisher Section" +msgstr "Mostra la sezione degli editori" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Lingue" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" -msgstr "Mostra l'opzione per la selezione delle lingue" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +msgid "Show Language Section" +msgstr "Mostra la sezione delle lingue" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Valutazioni" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" -msgstr "Mostra l'opzione per la selezione delle valutazioni" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +msgid "Show Ratings Section" +msgstr "Mostra la sezione delle valutazioni" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Formati file" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" -msgstr "Mostra l'opzione per la selezione del formato dei file" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +msgid "Show File Formats Section" +msgstr "Mostra la sezione dei formati dei file" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Libri archiviati" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" -msgstr "Mostra l'opzione per la selezione dei libri archiviati" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +msgid "Show Archived Books" +msgstr "Mostra i libri archiviati" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Elenco libri" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" -msgstr "Mostra l'opzione per visualizzare i libri sottoforma di elenco" +msgstr "Mostra l'elenco dei libri" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Cerca" @@ -1062,15 +1074,15 @@ msgid "Rating >= %(rating)s" msgstr "Valutazione >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Stato di lettura = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Errore di ricerca nelle colonne personalizzate. Per favore riavvia Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Ricerca avanzata" @@ -1118,9 +1130,9 @@ msgstr "Il libro è stato rimosso dallo scaffale: %(sname)s" #: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" -msgstr "Spiacente, ma non sei autorizzato a togliere libri da questo scaffale" +msgstr "Spiacente, ma non sei autorizzato a rimuovere libri da questo scaffale" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Crea uno scaffale" @@ -1145,245 +1157,276 @@ msgstr "Lo scaffale è stato eliminato con successo" msgid "Change order of Shelf: '%(name)s'" msgstr "Modifica l'ordine dello scaffale: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "Spiacente, ma non sei autorizzato a creare scaffali pubblici" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Lo scaffale %(title)s è stato creato" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Lo scaffale %(title)s è stato modificato" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" -msgstr "C'era un errore" +msgstr "C'è stato un errore" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." -msgstr "Esiste già uno scaffale pubblico denominato '%(title)s'." +msgstr "Esiste già uno scaffale pubblico con il nome '%(title)s'." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." -msgstr "Esiste già uno scaffale privato denominato '%(title)s'." +msgstr "Esiste già uno scaffale privato con il nome '%(title)s'." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Scaffale: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Errore durante l'apertura dello scaffale. Lo scaffale non esiste o non è accessibile" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" -msgstr "Compito" +msgstr "Attività" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Attendi" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Non riuscito" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Avviato" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Finito" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "Terminato" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" -msgstr "Cancellato" +msgstr "Annullato" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Stato sconosciuto" #: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" -msgstr "Dati inattesi durante il processo di aggiornamento" +msgstr "Dati imprevisti durante la lettura delle informazioni di aggiornamento" #: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" -msgstr "Nessun aggiornamento disponibile. Hai già installata l'ultima versione" +msgstr "Nessun aggiornamento disponibile. Hai già l'ultima versione installata" #: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." -msgstr "Nuovo aggiornamento disponibile. Clicca sul pulsante sottostante per aggiornare all'ultima versione." +msgstr "È disponibile un nuovo aggiornamento. Fare clic sul pulsante in basso per aggiornare all'ultima versione" #: cps/updater.py:474 msgid "Could not fetch update information" -msgstr "Impossibile recuperare le informazioni di aggiornamento" +msgstr "Impossibile recuperare le informazioni sull'aggiornamento" #: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." -msgstr "Clicca sul pulsante per aggiornare all'ultima versione stabile." +msgstr "Fare clic sul pulsante in basso per eseguire l'aggiornamento all'ultima versione stabile." #: cps/updater.py:493 cps/updater.py:507 cps/updater.py:518 #, python-format msgid "A new update is available. Click on the button below to update to version: %(version)s" -msgstr "Nuovo aggiornamento disponibile. Clicca sul pulsante sottostante per aggiornare alla versione: %(version)s" +msgstr "È disponibile un nuovo aggiornamento. Fare clic sul pulsante in basso per aggiornare alla versione:%(version)s" #: cps/updater.py:536 msgid "No release information available" -msgstr "Non sono disponibili informazioni sulla versione" +msgstr "Nessuna informazione disponibile sulla versione" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Scopri (libri casuali)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" -msgstr "I libri più richiesti" +msgstr "Libri hot (i più scaricati)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" -msgstr "I libri scaricati da %(user)s" +msgstr "Libri scaricati da %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autore: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Editore: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Serie: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "Valutazione: nessuna" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Valutazione: %(rating)s stelle" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Formato del file: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categoria: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Lingua: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" -msgstr "Downloads" +msgstr "Scaricati" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Elenco delle valutazioni" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Elenco dei formati" -#: cps/web.py:1202 +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "Prima configura le impostazioni del server SMTP..." + +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Libro accodato con successo per essere spedito a %(kindlemail)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Tutto OK! Libro in coda per l'invio a %(eReadermail)s" -#: cps/web.py:1206 +#: cps/web.py:1243 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" -msgstr "Oops! Si è verificato un errore durante l'invio di questo libro: %(res)s" +msgid "Oops! There was an error sending book: %(res)s" +msgstr "Si è verificato un errore durante l'invio del libro: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." -msgstr "Per favore aggiorna il tuo profilo con un indirizzo e-mail Kindle a cui inviare i libri." +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "Per favore aggiorna il tuo profilo con un'e-mail eReader valida." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "Attendi un minuto per registrare l'utente successivo" + +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 +msgid "Register" +msgstr "Registrati" + +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." msgstr "Il server e-mail non è configurato, per favore contatta l'amministratore" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 -msgid "Register" -msgstr "Registra" +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." +msgstr "La tua e-mail non è consentita." -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" -msgstr "Il tuo e-mail non è autorizzato alla registrazione" +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "Tutto OK! L'e-mail di conferma è stata inviata." -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." -msgstr "Un messaggio di conferma è stato inviato al tuo recapito e-mail." - -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" -msgstr "Non posso attivare l'autenticazione LDAP" +msgstr "Impossibile attivare l'autenticazione LDAP" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "Attendi un minuto prima dell'accesso successivo" + +#: cps/web.py:1376 +#, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "ora sei connesso come: '%(nickname)s'" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" -msgstr "Fallback login come: '%(nickname)s', il server LDAP non è raggiungibile o l'utente è sconosciuto" +msgstr "Accesso di riserva come: '%(nickname)s', il server LDAP non è raggiungibile o l'utente è sconosciuto" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" -msgstr "Non posso accedere: %(message)s" +msgstr "Impossibile accedere: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "Nome utente o password errati" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" -msgstr "Una nuova password è stata inviata al tuo recapito e-mail" +msgstr "La nuova password è stata inviata al tuo indirizzo email" -#: cps/web.py:1320 +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "Si è verificato un errore sconosciuto. Per favore riprova più tardi." + +#: cps/web.py:1405 msgid "Please enter valid username to reset password" -msgstr "Per favore digita un nome di utente valido per resettare la password" +msgstr "Inserisci un nome utente valido per reimpostare la password" -#: cps/web.py:1327 +#: cps/web.py:1413 #, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Ora sei connesso come '%(nickname)s'" +msgstr "Ora sei connesso come: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Profilo di %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" -msgstr "Profilo aggiornato" +#: cps/web.py:1487 +msgid "Success! Profile Updated" +msgstr "Tutto OK! Profilo aggiornato" + +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Esiste già un account per questa e-mail." #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Ho trovato un gmail.json file senza informazione OAuth" +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s inviato all'E-Reader" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1406,7 +1449,7 @@ msgstr "Si è verificato un errore con il convertitore Kepubify: %(error)s" #: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" -msgstr "Non ho trovato il file convertito o ci sono più di un file nella cartella %(folder)s" +msgstr "Non ho trovato il file convertito o c'è più di un file nella cartella %(folder)s" #: cps/tasks/convert.py:247 #, python-format @@ -1426,75 +1469,75 @@ msgstr "Convertire" msgid "Reconnecting Calibre database" msgstr "Riconessione al database di Calibre" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "E-mail" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 msgid "Backing up Metadata" msgstr "Backup dei metadati" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" -msgstr "Generate %(count)s miniature di copertine" +msgstr "Sono state generate %(count)s miniature delle copertine" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "Miniature delle copertine" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" -msgstr "Generate {0} miniature di serie" +msgstr "Sono state generate {0} miniature delle serie" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" -msgstr "Pulire la cache delle miniature di copertine" +msgstr "Cancellazione della cache delle miniature delle copertine" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" -msgstr "Upload" +msgstr "Caricamento" #: cps/templates/admin.html:9 msgid "Users" -msgstr "Elenco utenti" +msgstr "Utenti" #: cps/templates/admin.html:13 cps/templates/login.html:9 #: cps/templates/login.html:10 cps/templates/register.html:9 #: cps/templates/user_edit.html:10 cps/templates/user_table.html:134 msgid "Username" -msgstr "Utente" +msgstr "Nome utente" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" -msgstr "Indirizzo e-mail" +msgid "Email" +msgstr "E-mail" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to E-Reader E-mail Address" -msgstr "Invia all'indirizzo e-mail del lettore elettronico" +msgid "Send to eReader Email" +msgstr "E-mail dell'eReader" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" -msgstr "Amministrazione" +msgstr "Amministratore" #: cps/templates/admin.html:18 cps/templates/login.html:13 #: cps/templates/login.html:14 cps/templates/user_edit.html:23 msgid "Password" msgstr "Password" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Download" #: cps/templates/admin.html:23 msgid "View Books" -msgstr "Vedi libri" +msgstr "Visualizza libri" #: cps/templates/admin.html:24 cps/templates/user_table.html:131 #: cps/templates/user_table.html:148 @@ -1512,17 +1555,13 @@ msgstr "Elimina" msgid "Public Shelf" msgstr "Scaffale pubblico" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Aggiungi un nuovo utente" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importa gli utenti LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" -msgstr "Configurazione server e-mail" +msgid "Email Server Settings" +msgstr "Impostazioni server e-mail" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 msgid "SMTP Hostname" @@ -1538,15 +1577,15 @@ msgstr "Crittografia" #: cps/templates/admin.html:79 cps/templates/email_edit.html:47 msgid "SMTP Login" -msgstr "Login SMTP" +msgstr "Accesso SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "E-mail da" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "Servizio e-mail" #: cps/templates/admin.html:91 @@ -1579,7 +1618,7 @@ msgstr "Libri per pagina" #: cps/templates/admin.html:133 msgid "Uploads" -msgstr "Uploads" +msgstr "Caricamenti" #: cps/templates/admin.html:137 msgid "Anonymous Browsing" @@ -1591,19 +1630,19 @@ msgstr "Registrazione pubblica" #: cps/templates/admin.html:145 msgid "Magic Link Remote Login" -msgstr "Magic Link Login remoto" +msgstr "Accesso remoto con Magic Link" #: cps/templates/admin.html:149 msgid "Reverse Proxy Login" -msgstr "Login reverse proxy" +msgstr "Accesso reverse proxy" #: cps/templates/admin.html:154 cps/templates/config_edit.html:173 msgid "Reverse Proxy Header Name" -msgstr "Nome dell'intestazione Reverse Proxy" +msgstr "Nome dell'intestazione reverse proxy" #: cps/templates/admin.html:159 msgid "Edit Calibre Database Configuration" -msgstr "Modifica la configurazione del Database di Calibre" +msgstr "Modifica la configurazione del database di Calibre" #: cps/templates/admin.html:160 msgid "Edit Basic Configuration" @@ -1618,102 +1657,104 @@ msgid "Scheduled Tasks" msgstr "Attività pianificate" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" -msgstr "Ora in cui le attività sono avviate" +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "Ora di inizio" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" -msgstr "Massima durata delle attività" +msgid "Maximum Duration" +msgstr "Durata massima" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" -msgstr "Generazione delle miniature delle copertine" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" +msgstr "Genera miniature" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" -msgstr "Generazione delle miniature delle serie" +msgstr "Genera miniature delle copertine delle serie" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" -msgstr "Ricollegare alla libreria di Calibre" - -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" -msgstr "Aggiornare la cache delle miniature delle copertine" - -#: cps/templates/admin.html:199 -msgid "Administration" -msgstr "Amministrazione" - -#: cps/templates/admin.html:200 -msgid "Download Debug Package" -msgstr "Scarica Debug Package" - -#: cps/templates/admin.html:201 -msgid "View Logs" -msgstr "Visualizza Logfile" - -#: cps/templates/admin.html:204 +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 msgid "Reconnect Calibre Database" msgstr "Ricollega il database di Calibre" -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "Genera file di backup dei metadati" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "Aggiorna la cache delle miniature" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Amministrazione" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Scarica il pacchetto di debug" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Visualizza log" + +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Riavvia Calibre-Web" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Arresta Calibre-Web" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "Informazioni sulla versione" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versione" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Dettagli" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Versione attuale" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Ricerca aggiornamenti" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Esegui l'aggiornamento" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Vuoi veramente riavviare Calibre-Web?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" -msgstr "Ok" +msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Annulla" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Vuoi veramente arrestare Calibre-Web?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Aggiornamento, non ricaricare la pagina." @@ -1763,7 +1804,7 @@ msgstr "riduci" #: cps/templates/author.html:99 msgid "More by" -msgstr "Altro da" +msgstr "Altri di" #: cps/templates/book_edit.html:11 msgid "Delete Book" @@ -1783,7 +1824,7 @@ msgstr "Converti da:" #: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 msgid "select an option" -msgstr "seleziona un formato" +msgstr "seleziona un'opzione" #: cps/templates/book_edit.html:37 msgid "Convert to:" @@ -1803,7 +1844,7 @@ msgid "Author" msgstr "Autore" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Descrizione" @@ -1828,9 +1869,9 @@ msgstr "Rimuovi" msgid "Add Identifier" msgstr "Aggiungi un identificatore" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" -msgstr "Categorie" +msgstr "Etichetta" #: cps/templates/book_edit.html:95 msgid "Series ID" @@ -1853,23 +1894,23 @@ msgid "Published Date" msgstr "Data di pubblicazione" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Editore" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Lingua" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Sì" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "No" @@ -1879,15 +1920,15 @@ msgstr "Carica formato" #: cps/templates/book_edit.html:209 msgid "View Book on Save" -msgstr "Visualizza il libro dopo la modifica" +msgstr "Visualizza il libro dopo averlo salvato" #: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 msgid "Fetch Metadata" -msgstr "Ottieni metadati" +msgstr "Recupera i metadati" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1909,8 +1950,8 @@ msgstr "Fai clic sulla copertina per caricare i metadati nel modulo" msgid "Loading..." msgstr "Caricamento in corso..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Chiudi" @@ -1925,7 +1966,7 @@ msgstr "Errore nella ricerca!" #: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." -msgstr "Nessun risultato! Prova con un altro criterio di ricerca." +msgstr "Nessun risultato trovato! Prova con un'altra parola chiave." #: cps/templates/book_table.html:12 cps/templates/book_table.html:69 #: cps/templates/user_table.html:14 cps/templates/user_table.html:77 @@ -1947,15 +1988,15 @@ msgstr "Inverti autore e titolo" #: cps/templates/book_table.html:47 msgid "Update Title Sort automatically" -msgstr "Aggiorna automaticamente l'ordinamento dei titoli" +msgstr "Aggiorna automaticamente l'ordinamento per titolo" #: cps/templates/book_table.html:51 msgid "Update Author Sort automatically" -msgstr "Aggiorna automaticamente l'ordinamento degli autori" +msgstr "Aggiorna automaticamente l'ordinamento per autore" #: cps/templates/book_table.html:63 cps/templates/book_table.html:69 msgid "Enter Title" -msgstr "Indica il titolo" +msgstr "Inserisci il titolo" #: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 #: cps/templates/shelf_edit.html:8 @@ -1964,23 +2005,23 @@ msgstr "Titolo" #: cps/templates/book_table.html:64 msgid "Enter Title Sort" -msgstr "Indica l'ordinamento del titolo" +msgstr "Inserisci l'ordinamento per titolo" #: cps/templates/book_table.html:64 msgid "Title Sort" -msgstr "Ordinamento del titolo" +msgstr "Ordina per titolo" #: cps/templates/book_table.html:65 msgid "Enter Author Sort" -msgstr "Indica l'ordinamento dell'autore" +msgstr "Inserisci l'ordinamento per autore" #: cps/templates/book_table.html:65 msgid "Author Sort" -msgstr "Ordinamento dell'autore" +msgstr "Ordina per autore" #: cps/templates/book_table.html:66 msgid "Enter Authors" -msgstr "Indica gli autori" +msgstr "Inserisci gli autori" #: cps/templates/book_table.html:67 msgid "Enter Categories" @@ -1988,15 +2029,15 @@ msgstr "Indica le categorie" #: cps/templates/book_table.html:68 msgid "Enter Series" -msgstr "Indica le serie" +msgstr "Inserisci le serie" #: cps/templates/book_table.html:69 msgid "Series Index" -msgstr "Indice delle serie" +msgstr "Numero serie" #: cps/templates/book_table.html:70 msgid "Enter Languages" -msgstr "Indica le lingue" +msgstr "Inserisci le lingue" #: cps/templates/book_table.html:71 msgid "Publishing Date" @@ -2004,11 +2045,11 @@ msgstr "Data di pubblicazione" #: cps/templates/book_table.html:72 msgid "Enter Publishers" -msgstr "Indica gli editori" +msgstr "Inserisci gli editori" #: cps/templates/book_table.html:73 msgid "Enter comments" -msgstr "Digita un commento" +msgstr "Inserisci un commento" #: cps/templates/book_table.html:73 msgid "Comments" @@ -2016,18 +2057,18 @@ msgstr "Commento" #: cps/templates/book_table.html:75 msgid "Archive Status" -msgstr "Stato dell'archivio" +msgstr "Archiviato" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" -msgstr "Stato di lettura" +msgstr "Letto" #: cps/templates/book_table.html:80 cps/templates/book_table.html:82 #: cps/templates/book_table.html:84 cps/templates/book_table.html:86 #: cps/templates/book_table.html:90 cps/templates/book_table.html:92 #: cps/templates/book_table.html:96 msgid "Enter " -msgstr "Conferma " +msgstr "Inserisci" #: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 #: cps/templates/tasks.html:36 @@ -2052,7 +2093,7 @@ msgstr "Posizione del database di Calibre" #: cps/templates/config_db.html:22 msgid "Use Google Drive?" -msgstr "Utilizza Google Drive" +msgstr "Usa Google Drive" #: cps/templates/config_db.html:27 msgid "Authenticate Google Drive" @@ -2064,7 +2105,7 @@ msgstr "Cartella di Calibre in Google Drive" #: cps/templates/config_db.html:40 msgid "Metadata Watch Channel ID" -msgstr "ID canale Watch Metadata" +msgstr "ID del canale di visualizzazione dei metadati" #: cps/templates/config_db.html:43 msgid "Revoke" @@ -2072,7 +2113,7 @@ msgstr "Revoca" #: cps/templates/config_db.html:68 msgid "New db location is invalid, please enter valid path" -msgstr "La nuova posizione del DB non è valida, per favore indica un percorso corretto" +msgstr "La nuova posizione del database non è valida, inserisci un percorso valido" #: cps/templates/config_edit.html:18 msgid "Server Configuration" @@ -2084,11 +2125,11 @@ msgstr "Porta del server" #: cps/templates/config_edit.html:28 msgid "SSL certfile location (leave it empty for non-SSL Servers)" -msgstr "Percorso del file del certificato SSL (lascia vuoto per una configurazione del server senza SSL)" +msgstr "Posizione del file del certificato SSL (lascia vuoto per una configurazione del server senza SSL)" #: cps/templates/config_edit.html:35 msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" -msgstr "Percorso del file della chiave SSL (lascia vuoto per una configurazione del server senza SSL)" +msgstr "Posizione del file della chiave SSL (lascia vuoto per una configurazione del server senza SSL)" #: cps/templates/config_edit.html:43 msgid "Update Channel" @@ -2104,23 +2145,23 @@ msgstr "Nightly" #: cps/templates/config_edit.html:50 msgid "Trusted Hosts (Comma Separated)" -msgstr "Hosts fidati (separati da virgola)" +msgstr "Host attendibili (separati da virgole)" #: cps/templates/config_edit.html:61 msgid "Logfile Configuration" -msgstr "Configurazione del Logfile" +msgstr "Configurazione del file di log" #: cps/templates/config_edit.html:77 msgid "Location and name of logfile (calibre-web.log for no entry)" -msgstr "Percorso e nome del Logfile (senza indicazioni sarà calibre-web.log)" +msgstr "Posizione e nome del file di log (se non specificato sarà calibre-web.log)" #: cps/templates/config_edit.html:82 msgid "Enable Access Log" -msgstr "Abilita l'Access Log" +msgstr "Abilita il log degli accessi" #: cps/templates/config_edit.html:85 msgid "Location and name of access logfile (access.log for no entry)" -msgstr "Percorso e nome del Logfile di accesso (senza indicazioni sarà access.log)" +msgstr "Posizione e nome del file di log degli accessi (se non specificato sarà access.log)" #: cps/templates/config_edit.html:96 msgid "Feature Configuration" @@ -2135,8 +2176,8 @@ msgid "Enable Uploads" msgstr "Abilita il caricamento" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" -msgstr "(Per favore assicurati che gli utenti abbiano anche i diritti di upload)" +msgid "(Please ensure that users also have upload permissions)" +msgstr "(per favore assicurati che gli utenti abbiano anche i permessi per caricare i file)" #: cps/templates/config_edit.html:112 msgid "Allowed Upload Fileformats" @@ -2151,20 +2192,20 @@ msgid "Enable Public Registration" msgstr "Abilita la registrazione pubblica" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" -msgstr "Utilizza l'e-mail quale nome di utente" +msgid "Use Email as Username" +msgstr "Usa l'e-mail come nome utente" #: cps/templates/config_edit.html:132 msgid "Enable Magic Link Remote Login" -msgstr "Attiva login remoto Magic Link" +msgstr "Abilita l'accesso remoto con Magic Link" #: cps/templates/config_edit.html:137 msgid "Enable Kobo sync" -msgstr "Abilita la sincronia per Kobo" +msgstr "Abilita la sincronizzazione Kobo" #: cps/templates/config_edit.html:142 msgid "Proxy unknown requests to Kobo Store" -msgstr "Richieste proxy sconosciute allo store di Kobo" +msgstr "Inoltra le richieste sconosciute al Kobo Store" #: cps/templates/config_edit.html:145 msgid "Server External Port (for port forwarded API calls)" @@ -2172,43 +2213,43 @@ msgstr "Porta esterna del server (per chiamate API alle porte inoltrate)" #: cps/templates/config_edit.html:153 msgid "Use Goodreads" -msgstr "Utilizza Goodreads" +msgstr "Usa Goodreads" #: cps/templates/config_edit.html:154 msgid "Create an API Key" -msgstr "Otteni una chiave API" +msgstr "Crea una chiave API" #: cps/templates/config_edit.html:158 msgid "Goodreads API Key" -msgstr "API di Goodreads" +msgstr "Chiave API di Goodreads" #: cps/templates/config_edit.html:162 msgid "Goodreads API Secret" -msgstr "Goodreads API Secret" +msgstr "API segreta di Goodreads" #: cps/templates/config_edit.html:169 msgid "Allow Reverse Proxy Authentication" -msgstr "Permetti l'autenticazione Reverse Proxy" +msgstr "Consenti autenticazione con reverse proxy" #: cps/templates/config_edit.html:180 msgid "Login type" -msgstr "Tipo di login" +msgstr "Tipo di accesso" #: cps/templates/config_edit.html:182 msgid "Use Standard Authentication" -msgstr "Utilizza l'autenticazione standard" +msgstr "Usa l'autenticazione standard" #: cps/templates/config_edit.html:184 msgid "Use LDAP Authentication" -msgstr "Utilizza l'autenticazione LDAP" +msgstr "Usa l'autenticazione LDAP" #: cps/templates/config_edit.html:187 msgid "Use OAuth" -msgstr "Utilizza OAuth" +msgstr "Usa OAuth" #: cps/templates/config_edit.html:194 msgid "LDAP Server Host Name or IP Address" -msgstr "Nome o indirizzo IP del server LDAP" +msgstr "Nome host o indirizzo IP del server LDAP" #: cps/templates/config_edit.html:198 msgid "LDAP Server Port" @@ -2256,11 +2297,11 @@ msgstr "Semplice" #: cps/templates/config_edit.html:242 msgid "LDAP Administrator Username" -msgstr "Nome di utente dell'amministratore LDAP" +msgstr "Nome utente amministratore LDAP" #: cps/templates/config_edit.html:248 msgid "LDAP Administrator Password" -msgstr "Password dell'amministratore LDAP" +msgstr "Password amministratore LDAP" #: cps/templates/config_edit.html:253 msgid "LDAP Distinguished Name (DN)" @@ -2268,35 +2309,35 @@ msgstr "LDAP Distinguished Name (DN)" #: cps/templates/config_edit.html:257 msgid "LDAP User Object Filter" -msgstr "LDAP User Object Filter" +msgstr "Object Filter utente LDAP" #: cps/templates/config_edit.html:262 msgid "LDAP Server is OpenLDAP?" -msgstr "Il server LDAP è un server OpenLDAP." +msgstr "Il server LDAP è OpenLDAP?" #: cps/templates/config_edit.html:264 msgid "Following Settings are Needed For User Import" -msgstr "I seguenti parametri sono necessari per importare utenti" +msgstr "Le seguenti impostazioni sono necessarie per l'importazione degli utenti" #: cps/templates/config_edit.html:266 msgid "LDAP Group Object Filter" -msgstr "LDAP Group Object Filter" +msgstr "Object Filter gruppo LDAP" #: cps/templates/config_edit.html:270 msgid "LDAP Group Name" -msgstr "LDAP Group Name" +msgstr "Nome gruppo LDAP" #: cps/templates/config_edit.html:274 msgid "LDAP Group Members Field" -msgstr "LDAP Group Members Field" +msgstr "Campo membri del gruppo LDAP" #: cps/templates/config_edit.html:278 msgid "LDAP Member User Filter Detection" -msgstr "LDAP Member User Filter Detection" +msgstr "Rilevamento filtro utente membro LDAP" #: cps/templates/config_edit.html:280 msgid "Autodetect" -msgstr "Autodetect" +msgstr "Trova automaticamente" #: cps/templates/config_edit.html:281 msgid "Custom Filter" @@ -2304,7 +2345,7 @@ msgstr "Filtro personalizzato" #: cps/templates/config_edit.html:286 msgid "LDAP Member User Filter" -msgstr "LDAP Member User Filter" +msgstr "Filtro utente membro LDAP" #: cps/templates/config_edit.html:297 #, python-format @@ -2314,16 +2355,16 @@ msgstr "Ottieni le credenziali OAuth di %(provider)s" #: cps/templates/config_edit.html:300 #, python-format msgid "%(provider)s OAuth Client Id" -msgstr "%(provider)s OAuth Client Id" +msgstr "%(provider)s ID client OAuth" #: cps/templates/config_edit.html:304 #, python-format msgid "%(provider)s OAuth Client Secret" -msgstr "%(provider)s OAuth Client Secret" +msgstr "Secret client OAuth %(provider)s" #: cps/templates/config_edit.html:320 msgid "External binaries" -msgstr "Files binari esterni" +msgstr "File binari esterni" #: cps/templates/config_edit.html:326 msgid "Path to Calibre E-Book Converter" @@ -2331,7 +2372,7 @@ msgstr "Percorso del convertitore di libri di Calibre" #: cps/templates/config_edit.html:334 msgid "Calibre E-Book Converter Settings" -msgstr "Configurazione del convertitore di libri di Calibre" +msgstr "Impostazioni del convertitore di libri di Calibre" #: cps/templates/config_edit.html:337 msgid "Path to Kepubify E-Book Converter" @@ -2341,9 +2382,53 @@ msgstr "Percorso del convertitore di libri Kepubify" msgid "Location of Unrar binary" msgstr "Percorso del file binario di UnRar" +#: cps/templates/config_edit.html:361 +msgid "Security Settings" +msgstr "Impostazioni sicurezza" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "Limita i tentativi di accesso falliti" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "Protezione sessione" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "Di base" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "Forte" + +#: cps/templates/config_edit.html:380 +msgid "User Password policy" +msgstr "Politica password utente" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "Lunghezza minima password" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "Obbliga numero" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "Obbliga caratteri minuscoli" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "Obbliga caratteri maiuscoli" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "Obbliga caratteri speciali" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" -msgstr "Configurazione aspetto biblioteca" +msgstr "Visualizza configurazione" #: cps/templates/config_view_edit.html:32 msgid "No. of Random Books to Display" @@ -2351,9 +2436,9 @@ msgstr "Numero di libri casuali da mostrare" #: cps/templates/config_view_edit.html:36 msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" -msgstr "Numero di autori da mostrare prima di nascondere (0=disabilita mascheramento)" +msgstr "Numero di autori da mostrare prima di nascondere (0=disabilita nascondere)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Tema" @@ -2363,7 +2448,7 @@ msgstr "Tema standard" #: cps/templates/config_view_edit.html:43 msgid "caliBlur! Dark Theme" -msgstr "Tema caliBlur! Dark" +msgstr "Tema caliBlur! scuro" #: cps/templates/config_view_edit.html:47 msgid "Regular Expression for Ignoring Columns" @@ -2371,7 +2456,7 @@ msgstr "Espressione regolare per ignorare le colonne" #: cps/templates/config_view_edit.html:51 msgid "Link Read/Unread Status to Calibre Column" -msgstr "Collega lo stato letto/non letto nella colonna di Calibre" +msgstr "Collega lo stato letto/da leggere nella colonna di Calibre" #: cps/templates/config_view_edit.html:60 msgid "View Restrictions based on Calibre column" @@ -2391,31 +2476,31 @@ msgstr "Utente amministratore" #: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 msgid "Allow Downloads" -msgstr "Permetti il download" +msgstr "Consenti download" #: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 msgid "Allow eBook Viewer" -msgstr "Permetti l'utilizzo del visualizzatore di libri" +msgstr "Consenti l'utilizzo del visualizzatore di libri" #: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 msgid "Allow Uploads" -msgstr "Permetti l'upload" +msgstr "Consenti caricamenti" #: cps/templates/config_view_edit.html:106 cps/templates/user_edit.html:115 msgid "Allow Edit" -msgstr "Permetti la modifica" +msgstr "Consenti modifiche" #: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 msgid "Allow Delete Books" -msgstr "Permetti l'eliminazione di libri" +msgstr "Consenti l'eliminazione di libri" #: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 msgid "Allow Changing Password" -msgstr "Permetti la modifica della password" +msgstr "Consenti la modifica della password" #: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 msgid "Allow Editing Public Shelves" -msgstr "Permetti la modifica degli scaffali pubblici" +msgstr "Consenti la modifica degli scaffali pubblici" #: cps/templates/config_view_edit.html:123 msgid "Default Language" @@ -2432,94 +2517,96 @@ msgstr "Visibilità predefinita per i nuovi utenti" #: cps/templates/config_view_edit.html:163 cps/templates/user_edit.html:84 #: cps/templates/user_table.html:154 msgid "Show Random Books in Detail View" -msgstr "Mostra libri scelti aleatoriamente nella vista dettagliata" +msgstr "Mostra i libri casuali nella visualizzazione dettagliata" #: cps/templates/config_view_edit.html:166 cps/templates/user_edit.html:87 msgid "Add Allowed/Denied Tags" -msgstr "Aggiungi categorie permesse/negate" +msgstr "Aggiungi etichetta consentiti/negati" #: cps/templates/config_view_edit.html:167 msgid "Add Allowed/Denied custom column values" -msgstr "Aggiungi valori personali permetti/nega nelle colonne" +msgstr "Aggiungi valori di colonna personalizzati consentiti/negati" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" -msgstr "Leggi nel navigatore" +msgstr "Leggi nel browser" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" -msgstr "Ascolta nel navigatore" +msgstr "Ascolta nel browser" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "Libro %(index)s di %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Pubblicato" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" -msgstr "Marca come non letto" +msgstr "Contrassegna come da leggere" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" -msgstr "Marca come letto" +msgstr "Contrassegna come letto" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Letto" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Ripristina dall'archivio" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Aggiungi all'archivio" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Archiviato" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Descrizione:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Aggiungi allo scaffale" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Pubblico)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Modifica metadati" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" -msgstr "Scegli il tipo di server" +msgid "Email Account Type" +msgstr "Tipo di account e-mail" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" -msgstr "Utilizza un account e-mail standard" +msgid "Standard Email Account" +msgstr "Account e-mail standard" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Account Gmail con verifica OAuth2" +msgid "Gmail Account" +msgstr "Account Gmail" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Configura l'account Gmail quale server e-mail" +msgid "Setup Gmail Account" +msgstr "Configura l'account Gmail" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" -msgstr "Revoca l'accesso Gmail" +msgstr "Revoca l'accesso a Gmail" #: cps/templates/email_edit.html:42 msgid "STARTTLS" @@ -2538,17 +2625,17 @@ msgid "Attachment Size Limit" msgstr "Dimensione massima dell'allegato" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" -msgstr "Salva le impostazioni e invia e-mail di test" +msgid "Save and Send Test Email" +msgstr "Salva e invia e-mail di prova" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Indietro" #: cps/templates/email_edit.html:74 msgid "Allowed Domains (Whitelist)" -msgstr "Dominii autorizzati alla registrazione (Whitelist)" +msgstr "Domini consentiti (lista bianca)" #: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 msgid "Add Domain" @@ -2561,19 +2648,19 @@ msgstr "Aggiungi" #: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 msgid "Enter domainname" -msgstr "Digita il nome di dominio" +msgstr "Inserisci il nome del dominio" #: cps/templates/email_edit.html:92 msgid "Denied Domains (Blacklist)" -msgstr "Dominii bloccati per la registrazione (Blacklist)" +msgstr "Domini bloccati (lista nera)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Prossimo" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Apri il file .kobo/Kobo eReader.conf in un editore di testi e aggiungi (o edita):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Apri il file .kobo/Kobo/Kobo eReader.conf in un editor di testo e aggiungi (o modifica):" #: cps/templates/generate_kobo_auth_url.html:11 msgid "Kobo Token:" @@ -2583,21 +2670,21 @@ msgstr "Token di Kobo:" msgid "List" msgstr "Elenco" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "L'istanza Calibre-Web non è configurata, per favore contatta l'amministratore" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Crea un rapporto di segnalazione di problema" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Ritorna alla pagina principale" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" -msgstr "Disconnetti l'utente" +msgstr "Disconnetti utente" #: cps/templates/index.html:71 msgid "Sort ascending according to download count" @@ -2619,135 +2706,135 @@ msgstr "Ordina gli autori in ordine alfabetico inverso" #: cps/templates/index.html:83 msgid "Sort ascending according to series index" -msgstr "Ordina in ordine ascendente secondo l'indice della serie" +msgstr "Ordina in ordine ascendente secondo il numero della serie" #: cps/templates/index.html:84 msgid "Sort descending according to series index" -msgstr "Ordina in ordine discendente secondo l'indice della serie" +msgstr "Ordina in ordine discendente secondo il numero della serie" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Avvio" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Libri in ordine alfabetico" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Libri ordinati alfabeticamente" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Pubblicazioni popolari in questo catalogo in base ai download." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Pubblicazioni popolari in questo catalogo in base alle valutazioni." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Libri aggiunti di recente" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Gli ultimi libri" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" -msgstr "Libri presentati aleatoriamente" +msgstr "Libri casuali" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Libri ordinati per autore" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Libri ordinati per editore" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Libri ordinati per categoria" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Libri ordinati per serie" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Libri ordinati per lingua" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Libri ordinati per valutazione" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Libri ordinati per formato" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Scaffali" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Libri organizzati in scaffali" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Home" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" -msgstr "Alterna navigazione" +msgstr "Attiva/disattiva navigazione" #: cps/templates/layout.html:47 msgid "Search Library" msgstr "Ricerca nella libreria" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Uploading..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Errore" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Caricamento riuscito, sto elaborando, per favore aspetta..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Configurazione" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Account" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" -msgstr "Logout" +msgstr "Disconnettersi" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Caricamento in corso..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Errore" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Caricamento riuscito, elaborazione in corso, attendi per favore..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Impostazioni" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Per favore non ricaricare la pagina" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Naviga" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Informazioni su" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Precedente" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Dettagli del libro" @@ -2763,7 +2850,7 @@ msgstr "Ricordami" msgid "Forgot Password?" msgstr "Password dimenticata?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Accedi con Magic Link" @@ -2793,7 +2880,7 @@ msgstr "Scarica il log di accesso" #: cps/templates/modal_dialogs.html:6 msgid "Select Allowed/Denied Tags" -msgstr "Seleziona le categorie consentite/negate" +msgstr "Seleziona le etchette consentite/negate" #: cps/templates/modal_dialogs.html:7 msgid "Select Allowed/Denied Custom Column Values" @@ -2809,7 +2896,7 @@ msgstr "Seleziona i valori personali consentiti/negati per le colonne dell'utent #: cps/templates/modal_dialogs.html:15 msgid "Enter Tag" -msgstr "Indica le categorie" +msgstr "Inserisci etichetta" #: cps/templates/modal_dialogs.html:24 msgid "Add View Restriction" @@ -2817,11 +2904,11 @@ msgstr "Aggiungi restrizioni di visualizzazione" #: cps/templates/modal_dialogs.html:50 msgid "This book format will be permanently erased from database" -msgstr "Questo formato di libro viene rimosso definitivamente dal database" +msgstr "Questo formato di libro verrà definitivamente cancellato dal database" #: cps/templates/modal_dialogs.html:51 msgid "This book will be permanently erased from database" -msgstr "Il libro verrà cancellato dal database di Calibre" +msgstr "Questo libro verrà definitivamente cancellato dal database" #: cps/templates/modal_dialogs.html:52 msgid "and hard disk" @@ -2861,7 +2948,7 @@ msgstr "Seleziona" #: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 msgid "Ok" -msgstr "Ok" +msgstr "OK" #: cps/templates/osd.xml:5 msgid "Calibre-Web eBook Catalog" @@ -2871,135 +2958,159 @@ msgstr "Catalogo Calibre-Web" msgid "epub Reader" msgstr "Lettore epub" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Chiaro" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Scuro" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "Seppia" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 msgid "Black" msgstr "Nero" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Adatta il testo quando le barre laterali sono aperte." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "Dimensioni dei caratteri" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "Lettore di fumetti" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Scorciatoie della tastiera" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Pagina precedente" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Pagina successiva" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "Visualizzazione a pagina singola" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "Visualizzazione a striscia lunga" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Adatta al meglio" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Adatta alla larghezza" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Adatta all'altezza" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" -msgstr "Scala alla dimensione originale" +msgstr "Adatta alla dimensione originale" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Ruota a destra" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Ruota a sinistra" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Capovolgi immagine" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Visualizzazione" + +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "Pagina singola" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "Striscia lunga" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Scala" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Migliore" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Larghezza" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Altezza" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Originale" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Ruota" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Capovolgi" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Orizzontale" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Verticale" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Orientamento" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Da sinistra a destra" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Da destra a sinistra" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Ripristina in alto" +msgstr "Reimposta in alto" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "Ricorda la posizione" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Barra di scorrimento" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Mostra" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Nascondi" @@ -3007,7 +3118,7 @@ msgstr "Nascondi" msgid "DJVU Reader" msgstr "Lettore DJVU" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "Lettore PDF" @@ -3024,28 +3135,24 @@ msgid "Choose a username" msgstr "Scegli un nome utente" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Il tuo indirizzo e-mail" #: cps/templates/remote_login.html:5 msgid "Magic Link - Authorise New Device" -msgstr "Magic Link - Autorizza un nuovo apparecchio" +msgstr "Magic Link - Autorizza nuovo dispositivo" #: cps/templates/remote_login.html:7 msgid "On another device, login and visit:" -msgstr "Utilizza il tuo altro apparecchio, accedi e visita" +msgstr "Su un altro dispositivo, accedi e visita:" #: cps/templates/remote_login.html:11 msgid "Once verified, you will automatically be logged in on this device." -msgstr "Una volta completato, verrai automaticamente connesso con questo dispositivo." +msgstr "Una volta verificato, accederai automaticamente a questo dispositivo." #: cps/templates/remote_login.html:14 msgid "This verification link will expire in 10 minutes." -msgstr "Il link scadrà tra 10 minuti." - -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "Genera miniature delle copertine dei libri" +msgstr "Questo link di verifica scadrà tra 10 minuti." #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" @@ -3065,49 +3172,57 @@ msgstr "Risultati per:" #: cps/templates/search_form.html:21 msgid "Published Date From" -msgstr "Data di pubblicazione da" +msgstr "Data di pubblicazione dal" #: cps/templates/search_form.html:31 msgid "Published Date To" -msgstr "Data di pubblicazione fino a" +msgstr "Data di pubblicazione fino al" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" -msgstr "Escludi categorie" +msgstr "Escludi etichette" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Escludi serie" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "Escludi scaffali" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Escludi lingue" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Estensioni" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Escludi estensioni" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Valutazione superiore a" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Valutazione inferiore a" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "Da:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "A:" @@ -3185,7 +3300,7 @@ msgstr "Utente" #: cps/templates/tasks.html:14 msgid "Task" -msgstr "Operazione" +msgstr "Attività" #: cps/templates/tasks.html:15 msgid "Status" @@ -3199,10 +3314,6 @@ msgstr "Avanzamento" msgid "Run Time" msgstr "Tempo d'esecuzione" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Ora d'inizio" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "Azioni" @@ -3221,11 +3332,11 @@ msgstr "Reimposta la password dell'utente" #: cps/templates/user_edit.html:43 msgid "Language of Books" -msgstr "Mostra libri in" +msgstr "Lingua dei libri" #: cps/templates/user_edit.html:54 msgid "OAuth Settings" -msgstr "Configurazione OAuth" +msgstr "Impostazioni OAuth" #: cps/templates/user_edit.html:56 msgid "Link" @@ -3237,7 +3348,7 @@ msgstr "Scollega" #: cps/templates/user_edit.html:64 msgid "Kobo Sync Token" -msgstr "Token Kobo Sync" +msgstr "Token di sincronizzazione Kobo" #: cps/templates/user_edit.html:66 msgid "Create/View" @@ -3249,7 +3360,7 @@ msgstr "Forza la sincronizzazione kobo completa" #: cps/templates/user_edit.html:88 msgid "Add allowed/Denied Custom Column Values" -msgstr "Aggiungi valori personali permessi/negati nelle colonne" +msgstr "Aggiungi valori personali consentiti/negati nelle colonne" #: cps/templates/user_edit.html:137 msgid "Sync only books in selected shelves with Kobo" @@ -3273,19 +3384,19 @@ msgstr "Modifica utente" #: cps/templates/user_table.html:134 msgid "Enter Username" -msgstr "Digita il nome utente" +msgstr "Inserisci nome utente" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "Digita l'indirizzo e-mail" +msgid "Enter Email" +msgstr "Inserisci e-mail" #: cps/templates/user_table.html:136 -msgid "Enter E-Reader E-mail Address" -msgstr "Digita l'e-mail del lettore elettronico" +msgid "Enter eReader Email" +msgstr "Inserisci l'e-mail dell'eReader" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" -msgstr "E-mail del lettore elettronico" +msgid "eReader Email" +msgstr "E-mail dell'eReader" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3293,31 +3404,31 @@ msgstr "Locale" #: cps/templates/user_table.html:138 msgid "Visible Book Languages" -msgstr "Lingue dei libri visualizzabili" +msgstr "Lingue dei libri visibili" #: cps/templates/user_table.html:139 msgid "Edit Allowed Tags" -msgstr "Modifica le categorie permesse" +msgstr "Modifica le etichette consentite" #: cps/templates/user_table.html:139 msgid "Allowed Tags" -msgstr "Categorie permesse" +msgstr "Etichette consentite" #: cps/templates/user_table.html:140 msgid "Edit Denied Tags" -msgstr "Modifica le categorie negate" +msgstr "Modifica le etichette negate" #: cps/templates/user_table.html:140 msgid "Denied Tags" -msgstr "Categorie negate" +msgstr "Etichette negate" #: cps/templates/user_table.html:141 msgid "Edit Allowed Column Values" -msgstr "Modifica i valori delle colonne permesse" +msgstr "Modifica i valori delle colonne consentite" #: cps/templates/user_table.html:141 msgid "Allowed Column Values" -msgstr "Valori delle colonne permesse" +msgstr "Valori delle colonne consentite" #: cps/templates/user_table.html:142 msgid "Edit Denied Column Values" @@ -3325,11 +3436,11 @@ msgstr "Modifica i valori delle colonne negate" #: cps/templates/user_table.html:142 msgid "Denied Column Values" -msgstr "Valori negati per le colonne" +msgstr "Valori delle colonne negate" #: cps/templates/user_table.html:144 msgid "Change Password" -msgstr "Modifica la password" +msgstr "Cambia la password" #: cps/templates/user_table.html:147 msgid "View" @@ -3341,13 +3452,9 @@ msgstr "Modifica gli scaffali pubblici" #: cps/templates/user_table.html:152 msgid "Sync selected Shelves with Kobo" -msgstr "Sincronizza con Kobo gli scaffali selezionati" +msgstr "Sincronizza gli scaffali selezionati con Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" -msgstr "Mostra l'opzione per la selezione dello stato letto/non letto" - -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Mostra l'opzione per presentare libri aleatoriamente" +msgid "Show Read/Unread Section" +msgstr "Mostra la sezione letto/da leggere" diff --git a/cps/translations/ja/LC_MESSAGES/messages.mo b/cps/translations/ja/LC_MESSAGES/messages.mo index e1ba4bd6..d9a36d6a 100644 Binary files a/cps/translations/ja/LC_MESSAGES/messages.mo and b/cps/translations/ja/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/ja/LC_MESSAGES/messages.po b/cps/translations/ja/LC_MESSAGES/messages.po index 693a39ed..51634bdc 100644 --- a/cps/translations/ja/LC_MESSAGES/messages.po +++ b/cps/translations/ja/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2018-02-07 02:20-0500\n" "Last-Translator: subdiox \n" "Language: ja\n" @@ -16,487 +16,497 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "統計" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "サーバーを再起動しました。ページを再読み込みしてください" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "サーバーをシャットダウンしています。ページを閉じてください" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "再接続成功" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "不明なコマンド" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "本の %(kindlemail)s への送信がキューに追加されました" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "%(email)s へのテストメール送信がキューに追加されました。結果を見るにはタスクを確認してください" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "不明" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "管理者ページ" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "基本設定" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "UI設定" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "ユーザーを編集" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "全て" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "ユーザーが見つかりません" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{}人のユーザーが削除されました" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "全て表示" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "不正なリクエスト" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "ゲストユーザーの名前は変更できません" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "ゲストユーザーはこのロールを持つことができません" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "管理者ユーザーが残っておらず、管理者ロールを削除できません" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "値はtrueかfalseのどちらかでなければなりません" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "無効なロール" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "ゲストユーザーはこの画面を表示できません" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "無効な表示" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "ゲストユーザーの言語設定は自動的に決定されるため、固定することはできません" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "有効な言語設定がありません" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "有効な本の言語がありません" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "パラメータが見つかりません" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "無効な読み取り列" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "無効な制限列" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Webの設定を更新しました" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Koboのトークンを削除してもよろしいですか?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "このドメインを削除してもよろしいですか?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "このユーザーを削除してもよろしいですか?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "この本棚を削除してもよろしいですか?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "選択したユーザーの言語設定を変更してもよろしいですか?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "選択したユーザーが表示できる本の言語を変更してもよろしいですか?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "選択したユーザーの選択したロールを変更してもよろしいですか?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "選択したユーザーの選択した制限を変更してもよろしいですか?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "選択したユーザーの選択した表示制限を変更してもよろしいですか?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "選択したユーザーの本棚同期の動作を変更してもよろしいですか?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "Calibreライブラリのパスを変更してもよろしいですか?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "Calibre-Webは新しい表紙を検索してそのサムネイルを更新しますが、これにはしばらく時間がかかるかもしれません" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "Calibre-Webの同期DBを削除して強制的にKoboリーダーと同期してもよろしいですか?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "拒否" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "許可" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{}件の同期項目を削除しました" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "タグが見つかりません" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "無効なアクションです" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.jsonがWebアプリケーション用に設定されていません" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "ログファイルの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "アクセスログファイルの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "LDAPのプロバイダ、ポート番号、DN、ユーザーIDを入力してください" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "LDAPのサービスアカウント名とパスワードを入力してください" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "LDAPのサービスアカウント名を入力してください" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAPのグループフィルタには \"%s\" というフォーマットのIDが一つ必要です" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAPのグループフィルタ内の括弧が一致しません" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAPのユーザーフィルタには \"%s\" というフォーマットのIDが一つ必要です" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAPのユーザーフィルタ内の括弧が一致しません" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAPのメンバーフィルタには \"%s\" というフォーマットのIDが一つ必要です" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "LDAPのメンバーフィルタ内の括弧が一致しません" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAPのCA証明書、証明書、キーの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "新規ユーザー追加" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "新規ユーザーを追加" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "メールサーバー設定を編集" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Gmailアカウントを認証しました" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "DBエラー: %(error)s" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "%(email)s へのテストメール送信がキューに追加されました。結果を見るにはタスクを確認してください" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "%(res)s へのテストメール送信中にエラーが発生しました" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "初めにメールアドレスを設定してください" -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "メールサーバーの設定を更新しました" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "スケジュールタスク設定を編集" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "指定したタスクの開始時刻が無効です" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "指定したタスクの期間が無効です" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "スケジュールタスクの設定を更新しました" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "不明なエラーが発生しました。あとで再試行してください。" -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "設定DBが書き込みできません" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "ユーザー %(nick)s を編集" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "ユーザー %(user)s のパスワードをリセット" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "初めにSMTPメールの設定をしてください" -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "ログファイルビューア" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "更新データを要求中" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "更新データをダウンロード中" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "更新データを展開中" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "ファイルを置換中" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "DB接続を切断" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "サーバー停止中" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "アップデート完了、OKを押してページを再読み込みしてください" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "アップデート失敗:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTPエラー" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "接続エラー" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "接続確立中にタイムアウトしました" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "エラー発生" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "更新データを一時フォルダに保存できませんでした" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "更新中にファイルを置換できませんでした" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "少なくとも1人のLDAPユーザーの抽出に失敗しました" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "少なくとも1人のLDAPユーザーの作成に失敗しました" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "エラー: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "エラー: LDAPサーバーのレスポンスでユーザーが返されません" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "DB内にLDAPユーザーが1人も見つかりません" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{}人のユーザーをインポートしました" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "DBの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "DBへの書き込みができません" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "キーファイルの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "証明書ファイルの場所が無効です。正しいパスを入力してください" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "DB設定を更新しました" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "DB設定" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "全ての項目を入力してください" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "このメールは有効なドメインからのものではありません" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "新規ユーザー追加" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "ユーザー '%(user)s' を作成しました" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "このメールアドレスかニックネームで登録されたアカウントがすでに存在します。" -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "ユーザー '%(nick)s' を削除しました" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "ゲストユーザーは削除できません" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "管理者ユーザーが残っておらず、ユーザーを削除できません" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "ユーザー '%(nick)s' を更新しました" @@ -509,122 +519,122 @@ msgstr "インストールされていません" msgid "Execution permissions missing" msgstr "実行権限がありません" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "カスタムカラムの%(column)d列目がcalibreのDBに存在しません" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "なし" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "選択した本は利用できません。ファイルが存在しないか、アクセスできません" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "ユーザーは表紙をアップロードする権限がありません" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "IDは大文字小文字を区別しません。元のIDを上書きします" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "メタデータを更新しました" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "本編集中のエラー: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "ファイル %(file)s をアップロードしました" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "変換元の形式または変換後の形式が指定されていません" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "本の %(book_format)s への変換がキューに追加されました" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "この本の変換中にエラーが発生しました: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "アップロードした本はすでにライブラリに存在します。新しくアップロードする前に変更を加えてください: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "'%(langname)s' は有効な言語ではありません" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "ファイル拡張子 '%(ext)s' をこのサーバーにアップロードすることは許可されていません" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "アップロードするファイルには拡張子が必要です" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "ファイル %(filename)s は一時フォルダに保存できませんでした" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "表紙ファイル %(file)s の移動に失敗しました: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "本の形式を削除しました" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "本を削除しました" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "本を削除する権限がありません" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "メタデータを編集" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s は有効な数字ではありません。スキップします" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "新たなファイル形式をアップロードする権限がありません" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "%(path)s の作成に失敗しました (Permission denied)。" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "ファイル %(file)s を保存できません。" -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "ファイル形式 %(ext)s が %(book)s に追加されました" @@ -637,180 +647,187 @@ msgstr "Googleドライブの設定が完了していません。Googleドライ msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "コールバックドメインが認証されていません。Google Developer Consoleでドメインを認証してください" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "ID: %(book)d の本に %(format)s フォーマットはありません" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "Googleドライブ: %(fn)s に %(format)s はありません" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s がありません: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 -msgid "Send to E-Reader" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" msgstr "E-Readerに送信" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "このメールはCalibre-Web経由で送信されました。" -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web テストメール" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "テストメール" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Calibre-Webを始める" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "ユーザー: %(name)s 用の登録メール" -#: cps/helper.py:148 cps/helper.py:154 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "%(orig)s を %(format)s に変換してからE-Readerに送信" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 -#, python-format -msgid "Send %(format)s to E-Reader" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "E-Readerに %(format)s を送信" -#: cps/helper.py:225 cps/tasks/convert.py:92 -#, python-format -msgid "%(book)s send to E-Reader" +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" msgstr "%(book)s をE-Readerに送信" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "要求されたファイルを読み込めませんでした。権限設定が正しいか確認してください。" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "読み込みステータスを設定できません: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "%(id)s の本フォルダの削除に失敗しました。そこにはサブフォルダがあります: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "本 %(id)s の削除に失敗しました: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "本 %(id)s はDBのみから削除されます。DB内の本のパスが有効ではありません: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "エラー: %(error)s により、著者名を %(src)s から %(dest)s に変更できませんでした" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "ファイル %(file)s はGoogleドライブ上にありません" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "エラー: %(error)s により、タイトルを %(src)s から %(dest)s に変更できませんでした" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "ファイル名の変更でエラーが発生しました: {}" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "本のパス %(path)s はGoogleドライブ上にありません" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "このメールアドレスで登録されたアカウントがすでに存在します" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "このユーザー名はすでに使われています" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "メールアドレスの形式が無効" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "表紙のアップロードに必要なPythonモジュール 'advocate' がインストールされていません" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "表紙のダウンロードに失敗しました" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "表紙形式エラー" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "表紙アップロードのためにlocalhostやローカルネットワークにアクセスすることは許可されていません" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "表紙ファイルの作成に失敗しました" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "表紙ファイルが有効な画像ファイルでないか、または保存できませんでした" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "表紙ファイルは jpg/jpeg/png/webp/bmp のみ対応しています" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "表紙ファイルの内容が無効です" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "表紙ファイルは jpg/jpeg のみ対応しています" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrarのバイナリファイルが見つかりません" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Unrarの実行中にエラーが発生しました" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "見つける" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "localhost以外からCalibre-Webにアクセスし、有効なKobo端末用APIエンドポイントを取得してください" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo設定" @@ -819,9 +836,9 @@ msgstr "Kobo設定" msgid "Register with %(provider)s" msgstr "%(provider)s で登録" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "%(nickname)s としてログイン中" #: cps/oauth_bb.py:148 @@ -880,12 +897,13 @@ msgstr "Google OAuth エラー、再度お試しください。" msgid "Google Oauth error: {}" msgstr "Google OAuth エラー: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "星{}" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "ログイン" @@ -901,149 +919,158 @@ msgstr "トークンが無効です" msgid "Success! Please return to your device" msgstr "成功です!端末に戻ってください" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "本" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "最近追加された本を表示" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "人気の本" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "人気の本を表示" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "ダウンロードされた本" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "ダウンロードされた本を表示" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "高評価の本" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "高評価の本を表示" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "既読の本" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "既読の本と未読の本を表示" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "未読の本" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "未読の本を表示" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "見つける" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "ランダムに本を表示" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "カテゴリ" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "カテゴリ選択を表示" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "シリーズ" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "シリーズ選択を表示" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "著者" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "著者選択を表示" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "出版社" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "出版社選択を表示" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "言語" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "言語選択を表示" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "評価" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "評価選択を表示" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "ファイル形式" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "ファイル形式選択を表示" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "アーカイブされた本" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "アーカイブされた本を表示" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "本の一覧" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "本の一覧を表示" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "検索" @@ -1066,15 +1093,15 @@ msgid "Rating >= %(rating)s" msgstr "評価 >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "既読/未読状況 = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "カスタムカラムの検索でエラーが発生しました。Calibre-Webを再起動してください" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "詳細検索" @@ -1124,7 +1151,7 @@ msgstr "本が %(sname)s から削除されました" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "申し訳ありませんが、あなたはこの本棚から本を削除することが許可されていません" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "本棚を作成する" @@ -1149,73 +1176,73 @@ msgstr "本棚を削除しました" msgid "Change order of Shelf: '%(name)s'" msgstr "'%(name)s' 内の本の順番を変更する" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "申し訳ありませんが、あなたはみんなの本棚を作成することが許可されていません" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "%(title)s を作成しました" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "%(title)s を変更しました" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "エラーが発生しました" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "'%(title)s' という名前のみんなの本棚はすでに存在します。" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "'%(title)s' という名前の本棚はすでに存在します。" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "本棚: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "本棚を開けません。この本棚は存在しないかアクセスできません" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "タスク" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "待機中" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "失敗" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "開始" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "終了" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "終了" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "キャンセル" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "不明" @@ -1248,146 +1275,185 @@ msgstr "アップデートが利用可能です。下のボタンをクリック msgid "No release information available" msgstr "リリース情報がありません" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "本を見つける (ランダムに表示)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "人気の本 (最もダウンロードされた本)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "%(user)s がダウンロードした本" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "著者: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "出版社: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "シリーズ: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "評価: なし" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "評価: 星%(rating)s" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "ファイル形式: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "カテゴリ: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "言語: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "ダウンロード数" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "評価一覧" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "ファイル形式一覧" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "本の %(kindlemail)s への送信がキューに追加されました" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "初めにSMTPメールの設定をしてください" -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "本の %(eReadermail)s への送信がキューに追加されました" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "%(res)s を送信中にエラーが発生しました" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "初めにKindleのメールアドレスを設定してください" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "メールサーバーが設定されていません。管理者に連絡してください" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "登録" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "メールサーバーが設定されていません。管理者に連絡してください" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "このメールアドレスは登録が許可されていません" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "確認メールがこのメールアドレスに送信されました。" -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "LDAP認証を有効化できません" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "%(nickname)s としてログイン中" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "代わりに '%(nickname)s' としてログインします。LDAPサーバーにアクセスできないか、ユーザーが存在しません" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "ログインできません: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "ユーザー名またはパスワードが違います" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "新しいパスワードがあなたのメールアドレスに送信されました" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "不明なエラーが発生しました。あとで再試行してください。" + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "パスワードをリセットするには、有効なユーザー名を入力してください" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "'%(nickname)s' としてログインしました" +msgstr "%(nickname)s としてログイン中" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s のプロフィール" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "プロフィールを更新しました" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "このメールアドレスで登録されたアカウントがすでに存在します" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "OAuth情報を含んだ有効なgmail.jsonファイルが見つかりません" +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s をE-Readerに送信" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1430,35 +1496,35 @@ msgstr "変換" msgid "Reconnecting Calibre database" msgstr "Calibre DBと再接続中" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "メール" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "メタデータを編集" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "表紙サムネイルを%(count)s個生成しました" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "表紙サムネイル" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "シリーズのサムネイルを{0}個生成しました" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "表紙サムネイルのキャッシュを消去中" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "アップロード" @@ -1474,14 +1540,14 @@ msgstr "ユーザー名" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "メールアドレス" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "E-Readerメールアドレス" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "管理者" @@ -1491,8 +1557,8 @@ msgstr "管理者" msgid "Password" msgstr "パスワード" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "ダウンロード" @@ -1517,16 +1583,12 @@ msgstr "削除" msgid "Public Shelf" msgstr "みんなの本棚" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "新規ユーザーを追加" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "LDAPユーザーをインポート" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "メールサーバー設定" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1547,11 +1609,12 @@ msgstr "SMTPログイン" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Fromメールアドレス" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "メールサービス" #: cps/templates/admin.html:91 @@ -1623,102 +1686,104 @@ msgid "Scheduled Tasks" msgstr "スケジュールタスク" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "タスクを開始する時間" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "最大タスク継続時間" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "本の表紙サムネイルを生成" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "シリーズの表紙サムネイルを生成" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "Calibreライブラリに再接続" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" msgstr "表紙サムネイルのキャッシュを更新" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:203 msgid "Administration" msgstr "管理" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "デバッグパッケージをダウンロード" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "ログを表示" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Calibre DBに再接続" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "再起動" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "シャットダウン" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "バージョン情報" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "バージョン" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "詳細" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "現在のバージョン" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "アップデートを確認" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "アップデートを実行" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "再起動してもよろしいですか?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "キャンセル" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "シャットダウンしてもよろしいですか?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "アップデート中です。このページをリロードしないでください" @@ -1808,7 +1873,7 @@ msgid "Author" msgstr "著者" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "詳細" @@ -1833,7 +1898,7 @@ msgstr "削除" msgid "Add Identifier" msgstr "識別子を追加" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "タグ" @@ -1858,23 +1923,23 @@ msgid "Published Date" msgstr "発売日" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "出版社" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "言語" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "既読" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "未読" @@ -1891,8 +1956,8 @@ msgid "Fetch Metadata" msgstr "メタデータを取得" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1914,8 +1979,8 @@ msgstr "カバー画像をクリックしてメタデータをフォームに読 msgid "Loading..." msgstr "読み込み中..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "閉じる" @@ -2140,7 +2205,7 @@ msgid "Enable Uploads" msgstr "アップロード機能を有効にする" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "(ユーザーにアップロード権限を与えることも忘れないでください)" #: cps/templates/config_edit.html:112 @@ -2156,7 +2221,7 @@ msgid "Enable Public Registration" msgstr "誰でも登録可能にする" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "メールアドレスをユーザー名として使う" #: cps/templates/config_edit.html:132 @@ -2346,6 +2411,52 @@ msgstr "Kepubify E-Book Converterのパス" msgid "Location of Unrar binary" msgstr "Unrarバイナリのパス" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth設定" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "パスワードをリセット" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "表示設定" @@ -2358,7 +2469,7 @@ msgstr "ランダムに表示する本の冊数" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "非表示にする前に表示する著者数 (0=非表示にしない)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "テーマ" @@ -2447,80 +2558,84 @@ msgstr "許可/拒否タグを追加" msgid "Add Allowed/Denied custom column values" msgstr "許可/拒否カスタムカラムを追加" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "ブラウザで読む" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "ブラウザで聞く" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "%(range)s 第%(index)s巻" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "発売日" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "未読に設定" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "既読に設定" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "既読" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "アーカイブから復元" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "アーカイブに追加" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "アーカイブ済み" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "詳細:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "本棚に追加" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(公開)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "メタデータを編集" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "サーバーの種類を選択" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "標準のメールアカウントを使用" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "OAuth2認証を用いたGmailアカウント" +#, fuzzy +msgid "Gmail Account" +msgstr "サーバーの種類を選択" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Gmailアカウントをメールサーバーとして設定" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2543,10 +2658,11 @@ msgid "Attachment Size Limit" msgstr "添付ファイルのサイズ制限" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "保存してテストメールを送信" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "戻る" @@ -2572,13 +2688,13 @@ msgstr "ドメイン名を入力" msgid "Denied Domains (Blacklist)" msgstr "拒否するドメイン名 (ブラックリスト)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "次" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr ".kobo/Kobo eReader.confファイルをテキストエディタで開いて追加(編集)してください:" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr ".kobo/Kobo/Kobo eReader.confファイルをテキストエディタで開いて追加(編集)してください:" #: cps/templates/generate_kobo_auth_url.html:11 msgid "Kobo Token:" @@ -2588,19 +2704,19 @@ msgstr "Koboトークン:" msgid "List" msgstr "一覧" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Calibre-Webインスタンスが未設定です。管理者に連絡してください" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Issueを作成" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "ホームに戻る" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "ユーザーをログアウト" @@ -2630,80 +2746,80 @@ msgstr "巻数が小さい順にソート" msgid "Sort descending according to series index" msgstr "巻数が大きい順にソート" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "開始" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "五十音順の本" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "五十音順にソートされた本" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "ダウンロード数に基づいた、この出版社が出している有名な本" -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "評価に基づいた、この出版社が出している有名な本" -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "最近追加された本" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "最新の本" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "ランダム" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "著者名順" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "出版社順" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "カテゴリ順" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "シリーズ順" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "言語順" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "評価順" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "ファイル形式順" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "本棚" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "本棚に整理された本" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "ホーム" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "ナビゲーションを実行" @@ -2711,48 +2827,48 @@ msgstr "ナビゲーションを実行" msgid "Search Library" msgstr "ライブラリ内を検索" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "アップロード中..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "エラー" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "アップロード完了。現在処理中ですのでお待ち下さい..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "設定" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "アカウント" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "ログアウト" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "アップロード中..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "エラー" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "アップロード完了。現在処理中ですのでお待ち下さい..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "設定" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "ページを更新しないでください" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "閲覧" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "このサイトについて" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "前" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "本の詳細" @@ -2768,7 +2884,7 @@ msgstr "アカウント情報を記憶する" msgid "Forgot Password?" msgstr "パスワードを忘れた場合" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "マジックリンクでログイン" @@ -2876,135 +2992,160 @@ msgstr "Calibre-WebのeBookカタログ" msgid "epub Reader" msgstr "EPUBリーダー" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "ライト" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "ダーク" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "セピア" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 msgid "Black" msgstr "ブラック" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "サイドバーが開いているとき、テキストを再度流し込みます。" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "コミックリーダー" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "キーボードショートカット" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "前のページ" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "次のページ" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "最適なサイズにする" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "横に合わせる" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "縦に合わせる" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "オリジナルのサイズにする" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "右に回転する" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "左に回転する" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "画像を反転する" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "管理者ページ" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "スケール" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "最適" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "横に合わせる" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "縦に合わせる" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "オリジナル" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "回転" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "反転" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "水平方向" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "垂直方向" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "読む方向" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "左から右" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "右から左" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "一番上にリセット" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "位置を維持" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "スクロールバー" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "表示" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "非表示" @@ -3012,7 +3153,7 @@ msgstr "非表示" msgid "DJVU Reader" msgstr "DJVUリーダー" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "PDFリーダー" @@ -3029,7 +3170,7 @@ msgid "Choose a username" msgstr "ユーザー名を入力してください" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "メールアドレス" #: cps/templates/remote_login.html:5 @@ -3048,10 +3189,6 @@ msgstr "一度承認されると、自動的にこの端末でログインされ msgid "This verification link will expire in 10 minutes." msgstr "この確認リンクの有効期限は10分です。" -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "本の表紙サムネイルを生成" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "シリーズの表紙サムネイルを生成" @@ -3076,43 +3213,51 @@ msgstr "発売日(〜から)" msgid "Published Date To" msgstr "発売日(〜まで)" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "除外するタグ" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "除外するシリーズ" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "除外する本棚" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "除外する言語" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "拡張子" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "除外する拡張子" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "評価(〜以上)" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "評価(〜以下)" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "〜から:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "〜まで:" @@ -3204,10 +3349,6 @@ msgstr "進捗" msgid "Run Time" msgstr "稼働時間" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "開始時刻" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "アクション" @@ -3281,15 +3422,18 @@ msgid "Enter Username" msgstr "ユーザー名を入力してください" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "メールアドレスを入力してください" +#, fuzzy +msgid "Enter Email" +msgstr "テストメール" #: cps/templates/user_table.html:136 -msgid "Enter E-Reader E-mail Address" -msgstr "E-Readerメールアドレスを入力してください" +#, fuzzy +msgid "Enter eReader Email" +msgstr "E-Readerメールアドレス" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" +#, fuzzy +msgid "eReader Email" msgstr "E-Readerメール" #: cps/templates/user_table.html:137 @@ -3349,10 +3493,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "選択した本棚をKoboと同期" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "既読/未読の選択を表示" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "ランダムに本を表示" - diff --git a/cps/translations/km/LC_MESSAGES/messages.mo b/cps/translations/km/LC_MESSAGES/messages.mo index 5f11291b..31c1b417 100644 Binary files a/cps/translations/km/LC_MESSAGES/messages.mo and b/cps/translations/km/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/km/LC_MESSAGES/messages.po b/cps/translations/km/LC_MESSAGES/messages.po index d86abb3e..6eac2f85 100644 --- a/cps/translations/km/LC_MESSAGES/messages.po +++ b/cps/translations/km/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2018-08-27 17:06+0700\n" "Last-Translator: \n" "Language: km_KH\n" @@ -17,494 +17,504 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "ស្ថិតិ" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "ម៉ាស៊ីន server បានដំណើរការម្តងទៀត សូមបើកទំព័រជាថ្មី" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "កំពុងបិទម៉ាស៊ីន server សូមបិទផ្ទាំងនេះ" -#: cps/admin.py:156 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:159 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "សៀវភៅបានចូលជួរសម្រាប់ផ្ញើទៅ %(kindlemail)s ដោយជោគជ័យ" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "សៀវភៅបានចូលជួរសម្រាប់ផ្ញើទៅ %(eReadermail)s ដោយជោគជ័យ" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "មិនដឹង" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "ទំព័ររដ្ឋបាល" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "ការកំណត់សាមញ្ញ" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "ការកំណត់ផ្ទាំងប្រើប្រាស់" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "អ្នកប្រើប្រាស់រដ្ឋបាល" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "បង្ហាញទាំងអស់" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "តើអ្នកពិតជាចង់លុបធ្នើនេះមែនទេ?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "បន្ថែមអ្នកប្រើប្រាស់ថ្មី" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "ប្តូរការកំណត់ SMTP" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "" -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "កែប្រែអ្នកប្រើប្រាស់ %(nick)s" -#: cps/admin.py:1411 +#: cps/admin.py:1436 #, python-format -msgid "Password for user %(user)s reset" +msgid "Success! Password for user %(user)s reset" msgstr "" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "សូមកំណត់អ៊ីមែល SMTP ជាមុនសិន" -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "កំពុងស្នើសុំឯកសារបច្ចុប្បន្នភាព" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "កំពុងទាញយកឯកសារបច្ចុប្បន្នភាព" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "កំពុងពន្លាឯកសារបច្ចុប្បន្នភាព" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "ទំនាក់ទំនងទៅមូលដ្ឋានទិន្នន័យត្រូវបានផ្តាច់" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "ការធ្វើបច្ចុប្បន្នភាពបានបញ្ចប់ សូមចុច okay រួចបើកទំព័រជាថ្មី" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "ទំនាក់ទំនងទៅមូលដ្ឋានទិន្នន័យត្រូវបានផ្តាច់" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "ការកំណត់មុខងារ" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "សូមបំពេញចន្លោះទាំងអស់!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "បន្ថែមអ្នកប្រើប្រាស់ថ្មី" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "បានបង្កើតអ្នកប្រើប្រាស់ ‘%(user)s’" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "" -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "អ្នកប្រើប្រាស់ ‘%(nick)s’ ត្រូវបានលុប" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "អ្នកប្រើប្រាស់ ‘%(nick)s’ ត្រូវបានកែប្រែ" @@ -517,122 +527,122 @@ msgstr "មិនបានតម្លើង" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "គ្មាន" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "ឯកសារប្រភេទ '%(ext)s' មិនត្រូវបានអនុញ្ញាតឲអាប់ឡូដទៅម៉ាស៊ីន server នេះទេ" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "ឯកសារដែលត្រូវអាប់ឡូដត្រូវមានកន្ទុយឯកសារ" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "កែប្រែទិន្នន័យមេតា" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "មិនអាចបង្កើតទីតាំង %(path)s (ពុំមានសិទ្ធិ)។" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "មិនអាចរក្សាទុកឯកសារ %(file)s ។" -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "ឯកសារទម្រង់ %(ext)s ត្រូវបានបន្ថែមទៅ %(book)s" @@ -645,180 +655,183 @@ msgstr "" msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Callback domain មិនទាន់បានផ្ទៀងផ្ទាត់ឲប្រើទេ សូមធ្វើតាមជំហានដើម្បីផ្ទៀងផ្ទាត់ domain នៅក្នុង Google Developer Console" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "ផ្ញើទៅ Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." -msgstr "" - -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +msgid "This Email has been sent via Calibre-Web." msgstr "" #: cps/helper.py:115 -msgid "Test e-mail" +msgid "Calibre-Web Test Email" msgstr "" -#: cps/helper.py:132 +#: cps/helper.py:116 +msgid "Test Email" +msgstr "" + +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "" -#: cps/helper.py:137 +#: cps/helper.py:138 #, python-format -msgid "Registration e-mail for user: %(name)s" +msgid "Registration Email for user: %(name)s" msgstr "" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 -#, python-format -msgid "Send %(format)s to E-Reader" -msgstr "" - -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "Send %(format)s to eReader" msgstr "ផ្ញើទៅ Kindle" -#: cps/helper.py:230 +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" +msgstr "ផ្ញើទៅ Kindle" + +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "ឯកសារដែលបានស្នើសុំមិនអាចបើកបានទេ។ អាចនឹងខុសសិទ្ធិប្រើប្រាស់ទេដឹង?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "ប្តូរចំណងជើងពី “%(src)s” ទៅជា “%(dest)s” បរាជ័យដោយបញ្ហា: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "ឯកសារ %(file)s រកមិនឃើញក្នុង Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "ប្តូរចំណងជើងពី “%(src)s” ទៅជា “%(dest)s” បរាជ័យដោយបញ្ហា: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "ទីតាំងសៀវភៅ %(path)s រកមិនឃើញក្នុង Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "ស្រាវជ្រាវ" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -827,9 +840,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "ឥឡូវអ្នកបានចូលដោយមានឈ្មោះថា៖ ‘%(nickname)s’" #: cps/oauth_bb.py:148 @@ -888,12 +901,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "ចូលប្រើប្រាស់" @@ -909,149 +923,158 @@ msgstr "វត្ថុតាងហួសពេលកំណត់" msgid "Success! Please return to your device" msgstr "ជោគជ័យ! សូមវិលមកឧបករណ៍អ្នកវិញ" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "បង្ហាញសៀវភៅមកថ្មី" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "សៀវភៅដែលមានប្រជាប្រិយភាព" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "បង្ហាញសៀវភៅដែលមានប្រជាប្រិយភាព" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "សៀវភៅដែលមានការវាយតម្លៃល្អជាងគេ" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "បង្ហាញសៀវភៅដែលមានការវាយតម្លៃល្អជាងគេ" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "សៀវភៅដែលបានអានរួច" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "បង្ហាញអានរួច និងមិនទាន់អាន" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "សៀវភៅដែលមិនទាន់បានអាន" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "ស្រាវជ្រាវ" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "បង្ហាញសៀវភៅចៃដន្យ" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "ប្រភេទនានា" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "បង្ហាញជម្រើសប្រភេទ" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "ស៊េរី" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "បង្ហាញជម្រើសស៊េរី" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "អ្នកនិពន្ធ" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "បង្ហាញជម្រើសអ្នកនិពន្ធ" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" -msgstr "" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" +msgstr "បង្ហាញជម្រើសស៊េរី" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "ភាសានានា" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "បង្ហាញផ្នែកភាសា" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" -msgstr "" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" +msgstr "បង្ហាញជម្រើសស៊េរី" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" -msgstr "" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" +msgstr "បង្ហាញជម្រើសស៊េរី" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" -msgstr "" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "បង្ហាញសៀវភៅមកថ្មី" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "ស្វែងរក" @@ -1075,14 +1098,14 @@ msgstr "ការវាយតម្លៃ >= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "ស្វែងរកកម្រិតខ្ពស់" @@ -1133,7 +1156,7 @@ msgstr "សៀវភៅត្រូវបានដកចេញពីធ្នើ msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "បង្កើតធ្នើ" @@ -1159,73 +1182,73 @@ msgstr "" msgid "Change order of Shelf: '%(name)s'" msgstr "ប្តូរលំដាប់ធ្នើ៖ ‘%(name)s’" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "ធ្នើឈ្មោះ %(title)s ត្រូវបានបង្កើត" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "ធ្នើឈ្មោះ %(title)s ត្រូវបានប្តូរ" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "មានបញ្ហា" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "ធ្នើ៖ ‘%(name)s’" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "មានបញ្ហាពេលបើកធ្នើ។ ពុំមានធ្នើ ឬមិនអាចបើកបាន" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "កិច្ចការនានា" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "កំពុងរង់ចាំ" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "បានបរាជ័យ" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "បានចាប់ផ្តើម" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "បានបញ្ចប់" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "" @@ -1258,146 +1281,181 @@ msgstr "" msgid "No release information available" msgstr "" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "ស្រាវជ្រាវ (សៀវភៅចៃដន្យ)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "សៀវភៅដែលត្រូវបានទាញយកច្រើនជាងគេ" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "ស៊េរី៖ %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "ប្រភេទ៖ %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "ភាសា៖ %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "ឯកសារ DLS" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "សៀវភៅបានចូលជួរសម្រាប់ផ្ញើទៅ %(kindlemail)s ដោយជោគជ័យ" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "សូមកំណត់អ៊ីមែល SMTP ជាមុនសិន" -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "សៀវភៅបានចូលជួរសម្រាប់ផ្ញើទៅ %(eReadermail)s ដោយជោគជ័យ" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "មានបញ្ហានៅពេលផ្ញើសៀវភៅនេះ៖ %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "ចុះឈ្មោះ" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." msgstr "" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "" -#: cps/web.py:1278 +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "" + +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "ឥឡូវអ្នកបានចូលដោយមានឈ្មោះថា៖ ‘%(nickname)s’" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "ខុសឈ្មោះអ្នកប្រើប្រាស់ ឬលេខសម្ងាត់" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1320 +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "" + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" -msgstr "" +msgstr "ខុសឈ្មោះអ្នកប្រើប្រាស់ ឬលេខសម្ងាត់" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "" +msgstr "ឥឡូវអ្នកបានចូលដោយមានឈ្មោះថា៖ ‘%(nickname)s’" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "ព័ត៌មានសង្ខេបរបស់ %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "ព័ត៌មានសង្ខេបបានកែប្រែ" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "ផ្ញើទៅ Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1440,35 +1498,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "កែប្រែទិន្នន័យមេតា" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "អាប់ឡូដ" @@ -1484,15 +1542,15 @@ msgstr "ឈ្មោះហៅក្រៅ" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "ឧបករណ៍ Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "រដ្ឋបាល" @@ -1502,8 +1560,8 @@ msgstr "រដ្ឋបាល" msgid "Password" msgstr "លេខសម្ងាត់" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "ទាញយក" @@ -1528,16 +1586,12 @@ msgstr "លុប" msgid "Public Shelf" msgstr "" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1558,11 +1612,11 @@ msgstr "អ្នកចូលប្រើ SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "ពីអ៊ីមែល" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1635,102 +1689,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "កិច្ចការរដ្ឋបាល" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "ភ្ជាប់ទៅ database Calibre ម្តងទៀត" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "រកមើលបច្ចុប្បន្នភាព" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "ធ្វើបច្ចុប្បន្នភាព" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "បាទ/ចាស" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "កំពុងធ្វើបច្ចុប្បន្នភាព សូមកុំបើកទំព័រជាថ្មី" @@ -1820,7 +1876,7 @@ msgid "Author" msgstr "អ្នកនិពន្ធ" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "ពិពណ៌នា" @@ -1845,7 +1901,7 @@ msgstr "" msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Tag" @@ -1870,23 +1926,23 @@ msgid "Published Date" msgstr "ថ្ងៃបោះពុម្ភ" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "អ្នកបោះពុម្ភ" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "ភាសា" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "បាទ/ចាស" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "ទេ" @@ -1903,8 +1959,8 @@ msgid "Fetch Metadata" msgstr "មើលទិន្នន័យមេតា" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1927,8 +1983,8 @@ msgstr "ចុចលើគម្របដើម្បីបញ្ចូលទិ msgid "Loading..." msgstr "កំពុងដំណើរការ..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "បិទ" @@ -2154,7 +2210,7 @@ msgid "Enable Uploads" msgstr "" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2170,7 +2226,7 @@ msgid "Enable Public Registration" msgstr "អនុញ្ញាតការចុះឈ្មោះសាធារណៈ" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2360,6 +2416,50 @@ msgstr "" msgid "Location of Unrar binary" msgstr "" +#: cps/templates/config_edit.html:361 +msgid "Security Settings" +msgstr "" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +msgid "User Password policy" +msgstr "" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "មើលការកំណត់" @@ -2372,7 +2472,7 @@ msgstr "ចំនួនសៀវភៅចៃដន្យដើម្បីបង msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "ការតុបតែង" @@ -2463,79 +2563,81 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "អានក្នុងកម្មវិធី browser" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "អាន" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "ពិពណ៌នា" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "បន្ថែមទៅធ្នើ" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "កែប្រែទិន្នន័យមេតា" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" +msgid "Gmail Account" msgstr "" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2559,10 +2661,11 @@ msgid "Attachment Size Limit" msgstr "" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "រក្សាទុកការកំណត់រួចផ្ញើអ៊ីមែលសាកល្បង" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "មកក្រោយ" @@ -2588,12 +2691,12 @@ msgstr "" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "បន្ទាប់" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2604,19 +2707,19 @@ msgstr "" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2646,80 +2749,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "ចាប់ផ្តើម" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "ការបោះពុម្ភផ្សាយដែលមានប្រជាប្រិយភាពពីកាតាឡុកនេះផ្អែកលើការទាញយក" -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "ការបោះពុម្ភផ្សាយដែលមានប្រជាប្រិយភាពពីកាតាឡុកនេះផ្អែកលើការវាយតម្លៃ" -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "សៀវភៅចុងក្រោយគេ" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "សៀវភៅចៃដន្យ" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "សៀវភៅរៀបតាមលំដាប់អ្នកនិពន្ធ" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "សៀវភៅរៀបតាមលំដាប់ប្រភេទ" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "សៀវភៅរៀបតាមលំដាប់ស៊េរី" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "បិទ/បើកការរុករក" @@ -2727,48 +2830,48 @@ msgstr "បិទ/បើកការរុករក" msgid "Search Library" msgstr "" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "កំពុងអាប់ឡូត..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "" - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "ការកំណត់" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "ចេញពីការប្រើប្រាស់" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "កំពុងអាប់ឡូត..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "" + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "ការកំណត់" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "រុករក" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "អំពី" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "មុន" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "ព័ត៌មានលម្អិតរបស់សៀវភៅ" @@ -2784,7 +2887,7 @@ msgstr "ចងចាំខ្ញុំ" msgid "Forgot Password?" msgstr "" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "ចូលប្រើប្រាស់ដោយ magic link" @@ -2893,136 +2996,161 @@ msgstr "" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "មកក្រោយ" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "សេរេអត្ថបទនៅពេលបើកផ្ទាំងចំហៀង។" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "ទំព័ររដ្ឋបាល" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3030,7 +3158,7 @@ msgstr "" msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -3048,7 +3176,7 @@ msgid "Choose a username" msgstr "ជ្រើសរើសឈ្មោះអ្នកប្រើប្រាស់" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "អាសយដ្ឋានអ៊ីមែលរបស់អ្នក" #: cps/templates/remote_login.html:5 @@ -3067,10 +3195,6 @@ msgstr "ក្រោយពីនេះ អ្នកនឹងត្រូវប msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3095,44 +3219,52 @@ msgstr "ថ្ងៃបោះពុម្ភចាប់ពី" msgid "Published Date To" msgstr "ថ្ងៃបោះពុម្ភរហូតដល់" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "លើកលែង tag" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "លើកលែងស៊េរី" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "លើកលែងស៊េរី" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "លើកលែងភាសា" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "ការវាយតម្លៃលើសពី" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "ការវាយតម្លៃតិចជាង" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3224,10 +3356,6 @@ msgstr "ដំណើរការ" msgid "Run Time" msgstr "រយៈពេលដែលបានចាប់ផ្តើម" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "ពេលចាប់ផ្តើម" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3304,17 +3432,18 @@ msgstr "ជ្រើសរើសឈ្មោះអ្នកប្រើប្រ #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "អាសយដ្ឋានអ៊ីមែលរបស់អ្នក" - -#: cps/templates/user_table.html:136 -#, fuzzy -msgid "Enter E-Reader E-mail Address" +msgid "Enter Email" msgstr "ឧបករណ៍ Kindle" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" -msgstr "" +#, fuzzy +msgid "Enter eReader Email" +msgstr "ឧបករណ៍ Kindle" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "eReader Email" +msgstr "ឧបករណ៍ Kindle" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3376,10 +3505,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "បង្ហាញជម្រើសស៊េរី" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "បង្ហាញសៀវភៅចៃដន្យ" - diff --git a/cps/translations/ko/LC_MESSAGES/messages.mo b/cps/translations/ko/LC_MESSAGES/messages.mo index cb672ba2..fc4abeb7 100644 Binary files a/cps/translations/ko/LC_MESSAGES/messages.mo and b/cps/translations/ko/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/ko/LC_MESSAGES/messages.po b/cps/translations/ko/LC_MESSAGES/messages.po index c6379467..ac395626 100644 --- a/cps/translations/ko/LC_MESSAGES/messages.po +++ b/cps/translations/ko/LC_MESSAGES/messages.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2022-01-10 11:30+0900\n" "Last-Translator: 내맘대로의 EPUBGUIDE.NET \n" "Language: ko\n" @@ -15,487 +15,497 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "통계" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "서버 다시 시작으로 새로고침 필요" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "서버를 종료하는 중, 창을 닫아야 함" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "재연결 성공" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "성공적으로 DB를 다시 연결하였습니다." + +#: cps/admin.py:162 msgid "Unknown command" msgstr "알 수 없는 명령" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "성공적으로 %(kindlemail)s에 보내기 예약이 되었습니다" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "%(email)s에 테스트를 위한 이메일을 보냄. 결과 확인 필요" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "알 수 없음" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "관리자 페이지" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "기본 설정" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "UI 설정" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "사용자 관리" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "모두" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "사용자를 찾을 수 없음" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} 사용자를 성공적으로 삭제함" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "모두 보기" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "잘못된 요청" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Guest 이름은 수정할 수 없음" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Guest는 이 권한을 사용할 수 없음" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "관리자 계정이 하나 뿐일 때는 관리자를 삭제할 수 없음" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "값으로 rue 또는 false만 설정 가능" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "잘못된 권한" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Guest는 이 view를 사용할 수 없음" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "잘못된 view" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Guest의 로케일은 자동으로 결정되며 설정할 수 없음" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "유효한 로케일이 아님" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "제공된 책의 언어가 유효하지 않음" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "매개변수를 찾을 수 없음" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "잘못된 읽기 열" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "잘못된 제한된 열" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web 설정이 업데이트 됨" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Kobo Token을 삭제하시겠습니까?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "이 도메인을 삭제하시겠습니까?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "이 사용자를 삭제하시겠습니까?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "이 서재를 삭제하시겠습니까?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "선택한 사용자의 언어를 변경하시겠습니까?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "선택한 사용자에 대해 표시되는 책 언어를 변경하시겠습니까?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "선택한 사용자에 대해 선택한 권한을 변경하시겠습니까?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "선택한 사용자에 대해 선택한 제한을 변경하시겠습니까?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "선택한 사용자에 대해 선택한 가시성 제한을 변경하시겠습니까?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "선택한 사용자의 실행기 동기화 동작을 변경하시겠습니까?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "캘리버 서재의 언어를 변경하시겠습니까?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" -msgstr "" +msgstr "Calibre-Web은 업데이트된 표지를 검색하고 표지 섬네일 업데이트합니다. 시간이 오래 걸릴 수 있습니다." -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "Kobo Reader와 전체 동기화를 강제 실행하기 위해 Calibre-Web의 동기화 데이터베이스를 삭제하시겠습니까?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "거부됨" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "허용됨" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} 동기화 항목이 삭제됨" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "태그를 찾을 수 없음" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "잘못된 액션" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json이 Web 응용프로그램에 대해 설정되지 않음" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "로그 파일 위치가 오류. 올바른 경로 입력 필요" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "액세스 로그 파일 위치가 올바르지 않음. 올바른 경로 입력 필요" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "LDAP 공급자, 포트, DN 및 사용자 개체 식별자를 입력" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "LDAP 서비스 계정 및 비밀번호를 입력하십시오" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "LDAP 서비스 계정을 입력하십시오" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP 그룹 개체 필터에는 하나의 \"%s\" 형식 식별자가 필요함" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP 그룹 개체 필터에 일치하지 않는 괄호가 있음" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP 사용자 개체 필터에는 하나의 \"%s\" 형식 식별자 필요" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP 사용자 개체 필터에 일치하지 않는 괄호가 있음" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP 구성원 사용자 필터에는 하나의 \"%s\" 형식 식별자 필요" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "LDAP 구성원 사용자 필터에 일치하지 않는 괄호가 있음" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "유요하지 않은 LDAP CACertificate, 인증서 또는 키 위치. 올바른 경로를 입력 필요" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "새 사용자 추가" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "사용자 추가" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "이메일 서버 설정 편집" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Gmail 계정 인증 성공" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Gmail 계정 인증에 성공하였습니다." -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "데이터베이스 오류: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "%(email)s에 테스트를 위한 이메일을 보냄. 결과 확인 필요" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "테스트 이메일을 보내는 동안 오류가 발생했습니다: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "먼저 이메일 주소를 구성하십시오..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "이메일 서버 설정 업데이트됨" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" -msgstr "" +msgstr "예약 작업 설정 편집" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" -msgstr "" +msgstr "지정된 작업의 시작 시간이 잘못 설정되었습니다." -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" -msgstr "" +msgstr "지정된 작업의 기간이 잘못 설정되었습니다." -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" -msgstr "" +msgstr "예약된 작업 설정을 업데이트 하였습니다." -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "알 수없는 오류가 발생했습니다. 나중에 다시 시도 해주십시오." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" -msgstr "" +msgstr "저장할 수 없는 설정 DB입니다." -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "사용자 %(nick)s 편집" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "사용자 %(user)s의 비밀번호 재설정" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "먼저 SMTP 메일 설정을 구성하십시오..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "로그 파일 뷰어" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "업데이트 패키지 요청" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "업데이트 패키지 다운로드" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "업데이트 패키지 압축 풀기" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "파일 교체" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "데이터베이스 연결이 닫힙니다" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "서버 중지" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "업데이트가 완료되었습니다. 확인을 누르고 페이지를 새로고침하세요" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "업데이트 실패:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP 오류" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "연결 오류" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "연결 설정 중 시간 초과" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "일반 오류" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "임시 디렉토리에 업데이트 파일을 저장할 수 없습니다" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "업데이트하는 동안 파일을 교체할 수 없습니다" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "하나 이상의 LDAP 사용자를 추출하지 못했습니다" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "하나 이상의 LDAP 사용자를 생성하지 못했습니다" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "오류: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "오류: LDAP 서버의 응답으로 사용자가 반환되지 않았습니다" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "데이터베이스에서 하나 이상의 LDAP 사용자를 찾을 수 없습니다" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} 사용자 가져오기 성공" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "올바르지 않은 DB 위치. 올바른 경로 입력 필요" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "쓰기 권한이 없는 DB" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "올바르지 않은 키 파일 위치. 올바른 경로 입력 필요" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "올바르지 않은 인증서 파일 위치. 올바른 경로 입력 필요" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "비밀번호 길이는 1에서 40 사이여야 합니다." + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "데이터베이스 설정이 업데이트 되었습니다" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "데이터베이스 구성" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "모든 필드를 채워주십시오!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "유효한 도메인에서 온 이메일이 아니" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "새 사용자 추가" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "사용자 '%(user)s'이(가) 생성됨" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "동일한 이메일 주소 또는 이름이 이미 등록되어 있습니다." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "사용자 '%(nick)s'이(가) 삭제됨" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "게스트 사용자는 삭제할 수 없습니다" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "관리자 계정이 하나 뿐일 때는 관리자 권한을 삭제할 수 없음" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" -msgstr "" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "이메일은 반드시 입력해야 하며 유효한 이메일이어야 합니다." -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "사용자 '%(nick)s'가 업데이트 됨" @@ -508,122 +518,122 @@ msgstr "설치되지 않음" msgid "Execution permissions missing" msgstr "실행 권한 누락" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "사용자 정의 열 번호 %(column)d이(가) calibre 데이터베이스에 없습니다" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "None" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "선택한 책 제목을 사용할 수 없습니다. 파일이 존재하지 않거나 액세스할 수 없습니다" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" -msgstr "" +msgstr "표지를 업로드 할 수 있는 권한이 없는 사용자입니다." -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "식별자는 대소문자를 구분하지 않으며 이전 식별자를 덮어씁니다" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "메타데이터가 성공적으로 업데이트되었습니다" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "책 편집 중 오류 발생: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "파일 %(file)s 업로드됨" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "변환을 위한 소스 또는 대상 형식이 누락되었습니다" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "책이 %(book_format)s(으)로 변환하기 위해 대기 중입니다" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "이 책을 변환하는 동안 오류가 발생했습니다: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "업로드한 책이 라이브러리에 있을 수 있음. 새로 업로드하기 전에 확인 필요: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "'%(langname)s'은(는) 유효한 언어가 아닙니다" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "파일 확장자 '%(ext)s'은(는) 이 서버에 업로드할 수 없습니다" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "업로드할 파일에는 확장자가 있어야 합니다" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "파일 %(filename)s을(를) 임시 디렉토리에 저장할 수 없습니다" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "표지 파일%(file)s를 이동하지 못했습니다.:%(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "책 형식이 성공적으로 삭제되었습니다" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "책이 성공적으로 삭제되었습니다" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" -msgstr "" +msgstr "책을 삭제할 수 있는 권한이 없습니다." -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "메타데이터 편집" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s은(는) 유효한 숫자가 아닙니다. 건너뜁니다" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" -msgstr "" +msgstr "추가 파일 유형을 업로드 할 권한이 없는 사용자입니다." -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "%(path)s 경로를 생성하지 못했습니다(권한이 없음)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "%(file)s 파일을 저장하지 못했습니다." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "파일 형식 %(ext)s이(가) %(book)s에 추가되었습니다" @@ -636,182 +646,189 @@ msgstr "Google 드라이브 설정이 완료되지 않았습니다. Google 드 msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "콜백 도메인이 확인되지 않았습니다. 단계에 따라 Google 개발자 콘솔에서 도메인을 확인하세요" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "책 ID에 대한 %(format)s 형식을 찾을 수 없음: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s을(를) Google 드라이브에서 찾을 수 없음: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s을(를) 찾을 수 없음: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "킨들로 보내기" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "이 이메일은 Calibre Web을 통해 전송되었습니다." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web 테스트 이메일" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "테스트 이메일" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Calibre-Web 시작하기" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "사용자 등록 이메일: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "%(orig)s를 %(format)s로 변환하고 킨들로 보내기" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "킨들에 %(format)s 보내기" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "%(book)s을 킨들로 보내기" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "요청한 파일을 읽을 수 없습니다. 올바른 권한인가요?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "읽기 상태를 설정할 수 없음: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "책 %(id)s에 대한 책 폴더를 삭제하지 못했습니다. 경로에 하위 폴더가 있습니다: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "%(id)s 도서 삭제 실패: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "데이터베이스에서만 책 %(id)s 을(를) 삭제 중, 데이터베이스의 책 경로가 유효하지 않음: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "제목 이름을 '%(src)s'에서 '%(dest)s'(으)로 변경하지 못했습니다. 오류: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Google 드라이브에서 %(file)s 파일을 찾을 수 없습니다" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "제목 이름을 '%(src)s'에서 '%(dest)s'(으)로 변경하지 못했습니다. 오류: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "경로에서 파일 이름을 바꾸는 중 오류가 발생: {}" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Google 드라이브에서 책 경로 %(path)s을(를) 찾을 수 없습니다" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "등록되어 있는 이메일 주소입니다" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "다른 계정에서 사용하고 있는 이메일 주소입니다." -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "등록되어 있는 username입니다" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "이메일 주소 형식이 잘못되었습니다" -#: cps/helper.py:815 -msgid "Python module 'advocate' is not installed but is needed for cover uploads" -msgstr "" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "규칙에 어긋나는 비밀번호입니다." -#: cps/helper.py:825 +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "표지 업로드에 필요한 Python 모듈 'advocate'이 설치되지 않았습니다." + +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "표지 다운로드 중 오류 발생" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "표지 형식 오류" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" -msgstr "" +msgstr "표지 업로드를 위해 localhost 또는 로컬 네트워크에 액세스할 수 없습니다." -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "표지 경로 생성 실패" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "표지 파일이 유효한 이미지 파일이 아니거나 저장할 수 없습니다" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "표지는 jpg/jpeg/png/webp/bmp 파일만 지원됩니다" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "잘못된 표지 파일 콘텐츠" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "표지 파일로 jpg/jpeg 파일만 지원됩니다" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar 바이너리 파일을 찾을 수 없습니다" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "UnRar 실행 오류" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "발견" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" -msgstr "" +msgstr "메타데이터 백업을 위해 모든 도서를 대기열에 추가" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "코보(kobo) 장치에 대한 유효한 api_endpoint를 얻으려면 로컬 호스트가 아닌 곳에서 calibre-web에 액세스하십시오" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo 설정" @@ -820,9 +837,9 @@ msgstr "Kobo 설정" msgid "Register with %(provider)s" msgstr "%(provider)s에 등록" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "다음 사용자로 로그인했습니다: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -881,12 +898,13 @@ msgstr "Google 인증 오류입니다. 나중에 다시 시도하세요." msgid "Google Oauth error: {}" msgstr "Google 인증 오류: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Stars" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "로그인" @@ -902,149 +920,158 @@ msgstr "토큰이 만료되었습니다" msgid "Success! Please return to your device" msgstr "성공! 기기로 돌아가주세요" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "책" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "최근 책 보기" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "인기있는 책" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "주목받는 책 보기" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "다운로드된 책" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "다운로드된 책 보기" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "평점이 높은 책" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "평점이 높은 책 보기" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "읽은 책" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "읽은 책과 읽지 않은 책 보기" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "읽지 않은 책" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "읽지 않은 책 보기" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "발견" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "무작위 추천" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "카테고리" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "카테고리별 보기" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "시리즈" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "시리즈별 보기" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "저자" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "저자별 보기" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "출판사" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "출판사별 보기" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "언어" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "언어별 보기" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "평점" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "평점별 보기" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "파일 유형" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "파일 유형별 보기" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "보관된 책" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "보관된 책 보기" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "책 목록" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "책 목록 보기" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "검색" @@ -1067,15 +1094,15 @@ msgid "Rating >= %(rating)s" msgstr "평점 >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "읽은 상태 = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "사용자 정의 열을 검색하는 동안 오류가 발생했습니다. Calibre-Web을 다시 시작하십시오" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "상세 검색" @@ -1125,7 +1152,7 @@ msgstr "책이 책장에서 삭제됨: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "죄송합니다. 이 서가에서 책을 삭제할 권한이 없습니다" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "책장 추가" @@ -1139,7 +1166,7 @@ msgstr "책장 편집" #: cps/shelf.py:229 msgid "Error deleting Shelf" -msgstr "" +msgstr "서제를 삭제하는 동안 오류 발생" #: cps/shelf.py:231 #, fuzzy @@ -1151,73 +1178,73 @@ msgstr "책이 성공적으로 삭제되었습니다" msgid "Change order of Shelf: '%(name)s'" msgstr "책장 순서 변경: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "죄송합니다. 이 공개 책장을 만들 권한이 없습니다" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "%(title)s 책장이 추가됨" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "%(title)s 책장이 변경됨" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "오류가 발생하였습니다" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "이름이 '%(title)s'인 공개 책장이 이미 있습니다." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "이름이 '%(title)s'인 개인 책장이 이미 있습니다." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "책장: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "책장을 여는 동안 오류가 발생했습니다. 책장이 존재하지 않거나 접근할 수 없습니다" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "작업" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "대기중" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "실패" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "시작됨" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "종료" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" -msgstr "" +msgstr "종료됨" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "취소됨" #: cps/tasks_status.py:74 -msgid "Cancelled" -msgstr "" - -#: cps/tasks_status.py:76 msgid "Unknown Status" msgstr "알 수 없는 상태" @@ -1250,146 +1277,185 @@ msgstr "최신 안정 버전 %(version)s으로 업데이트하려면 아래 버 msgid "No release information available" msgstr "출시 정보가 없습니다" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "발견(무작위 도서)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "인기있는 책(가장 많이 다운로드됨)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "%(user)s이(가) 다운로드한 책" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "저자: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "출판사: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "시리즈: %(serie)s" -#: cps/web.py:611 -msgid "Rating: None" -msgstr "" - #: cps/web.py:620 +msgid "Rating: None" +msgstr "평가: 없음음" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "평가: %(rating)s 별" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "파일 유형: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "카테고리: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "언어: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "다운로드" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "평점 목록" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "파일 유형 목록" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "성공적으로 %(kindlemail)s에 보내기 예약이 되었습니다" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "먼저 SMTP 메일 설정을 구성하십시오..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "성공적으로 %(eReadermail)s에 보내기 예약이 되었습니다" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "책을 보내는 중에 오류 발생: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Kindle로 보내는 유효한 이메일 주소로 프로필을 업데이트하십시오." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "이메일 서버가 구성되지 않았습니다. 관리자에게 문의하십시오!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "1분 이상 지난 후 다음 사용자를 등록하세요." -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "등록" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "이메일 서버가 구성되지 않았습니다. 관리자에게 문의하십시오!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "이메일을 등록할 수 없습니다" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "확인을 위한 이메일이 발송되었습니다." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "LDAP 인증을 활성화할 수 없습니다" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "1분 이상 지난 후 로그인을 하세요." + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "다음 사용자로 로그인했습니다: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "대체 로그인: '%(nickname)s', LDAP 서버에 연결할 수 없음 또는 사용자를 알 수 없음" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "로그인 실패: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "잘못된 사용자명 또는 비밀번호" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "새 비밀번호가 이메일로 전송되었습니다" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "알 수없는 오류가 발생했습니다. 나중에 다시 시도 해주십시오." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "비밀번호를 재설정하려면 유효한 사용자 이름을 입력하십시오" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "다음 사용자로 로그인: '%(nickname)s" +msgstr "다음 사용자로 로그인했습니다: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s 프로필" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "프로필이 업데이트 됨" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "등록되어 있는 이메일 주소입니다" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "인증 정보가 포함된 유효한 gmail.json 파일을 찾을 수 없습니다" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s을 킨들로 보내기" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1426,41 +1492,41 @@ msgstr "오류로 인한 Calibre 실패: %(error)s" #: cps/tasks/convert.py:275 msgid "Convert" -msgstr "" +msgstr "변환" #: cps/tasks/database.py:28 msgid "Reconnecting Calibre database" -msgstr "" +msgstr "Calibre DB를 다시 연결합니다." -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" -msgstr "" +msgstr "이메일일" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "메타데이터 편집" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" -msgstr "" +msgstr "%(count)개의 표지 섬네일을 생성하였습니다." -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" -msgstr "" +msgstr "표지 섬네일" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" -msgstr "" +msgstr "{0} 시리즈 섬네일을 생성하였습니다." -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" -msgstr "" +msgstr "표지 섬네일 캐시를 삭제합니다." #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "업로드" @@ -1476,15 +1542,15 @@ msgstr "사용자명" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "이메일 주소" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "킨들로 보내기 이메일 주소" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "관리자" @@ -1494,8 +1560,8 @@ msgstr "관리자" msgid "Password" msgstr "비밀번호" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "다운로드" @@ -1520,16 +1586,12 @@ msgstr "삭제" msgid "Public Shelf" msgstr "공개 책장" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "사용자 추가" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "LDAP 사용자 가져오기" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "이메일 서버 설정" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1550,12 +1612,13 @@ msgstr "SMTP Login" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" -msgstr "From E-mail" +msgid "From Email" +msgstr "From Email" #: cps/templates/admin.html:90 -msgid "E-Mail Service" -msgstr "E-Mail Service" +#, fuzzy +msgid "Email Service" +msgstr "EMail Service" #: cps/templates/admin.html:91 msgid "Gmail via Oauth2" @@ -1623,107 +1686,109 @@ msgstr "UI 환경 설정 편집" #: cps/templates/admin.html:167 msgid "Scheduled Tasks" -msgstr "" +msgstr "예약된 작업" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" -msgstr "" +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "시작 시간" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" -msgstr "" +msgid "Maximum Duration" +msgstr "최대 기간" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" -msgstr "" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" +msgstr "섬네일 생성성" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" -msgstr "" +msgstr "시리즈 표지 섬네일 생성" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" -msgstr "" - -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" -msgstr "" - -#: cps/templates/admin.html:199 -msgid "Administration" -msgstr "관리" - -#: cps/templates/admin.html:200 -msgid "Download Debug Package" -msgstr "Debug Package 다운로드" - -#: cps/templates/admin.html:201 -msgid "View Logs" -msgstr "로그 보기" - -#: cps/templates/admin.html:204 +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 msgid "Reconnect Calibre Database" msgstr "Calibre DB 다시 연결" -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "메타 정보 백업 파일 생성" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "섬네일 캐시 새로 고침침" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "관리" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Debug Package 다운로드" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "로그 보기" + +#: cps/templates/admin.html:211 msgid "Restart" msgstr "재시작" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "종료" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" -msgstr "" +msgstr "버전 정보" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "버전" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "세부 정보" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "현재 버전" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "업데이트 확인" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "업데이트 실행" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "재시작을 하시겠습니까?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "예" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "취소" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "종료를 하시겠습니까?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" -msgstr "Встановлення оновлень, будь-ласка, не оновлюйте сторінку" +msgstr "업데이트 중입니다. 이 페이지를 새로고침 하지 마세요." #: cps/templates/author.html:15 msgid "via" @@ -1811,7 +1876,7 @@ msgid "Author" msgstr "저자" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "책 소개" @@ -1836,7 +1901,7 @@ msgstr "삭제" msgid "Add Identifier" msgstr "식별자 추가" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "태그" @@ -1861,23 +1926,23 @@ msgid "Published Date" msgstr "출간일" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "출판사" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "언어" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "예" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "아니오" @@ -1894,8 +1959,8 @@ msgid "Fetch Metadata" msgstr "메타정보 가져오기" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1917,8 +1982,8 @@ msgstr "표지를 클릭하여 양식에 메타데이터 로드" msgid "Loading..." msgstr "불러오는 중..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "닫기" @@ -2024,7 +2089,7 @@ msgstr "코멘트" #: cps/templates/book_table.html:75 msgid "Archive Status" -msgstr "" +msgstr "아카이브 상태태" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" @@ -2068,7 +2133,7 @@ msgstr "구글 드라이브 인증" #: cps/templates/config_db.html:32 msgid "Google Drive Calibre folder" -msgstr "Google Drive Calibre 폴더" +msgstr "구글 드라이브 Calibre 폴더" #: cps/templates/config_db.html:40 msgid "Metadata Watch Channel ID" @@ -2143,7 +2208,7 @@ msgid "Enable Uploads" msgstr "업로드 활성화" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "(사용자에게 업로드 권한도 있는지 확인하십시오)" #: cps/templates/config_edit.html:112 @@ -2159,7 +2224,7 @@ msgid "Enable Public Registration" msgstr "공개 등록 활성화" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "이메일을 사용자 이름으로 사용" #: cps/templates/config_edit.html:132 @@ -2349,6 +2414,52 @@ msgstr "Kepubify 전자책 변환기 경로" msgid "Location of Unrar binary" msgstr "Unrar 바이너리의 위치" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth 설정" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "로그인 시도 제한" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "세션 보호" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "기본" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "강함함" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "사용자 비밀번호 정책" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "최소 비밀번호 길이" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "반드시 숫자 입력" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "반드시 소문자 입력" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "반드시 대문자 입력" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "반드시 특수문자 입력력" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "환경 설정 보기" @@ -2361,7 +2472,7 @@ msgstr "랜덤 보기시 표시할 책 수" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "숨기기 전에 표시할 저자 수(0=숨기기 비활성화)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "테마" @@ -2450,80 +2561,84 @@ msgstr "허용/거부 태그 추가" msgid "Add Allowed/Denied custom column values" msgstr "허용/거부 사용자 정의 열 값 추가" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "부라우저에서 보기" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "브라우저에서 듣기" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "책 %(index)s의 %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "출간일" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "읽지 않은 상태로 표시" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "읽은 상태로 표시" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "읽기" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "아카이브에서 복원" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "아카이브에 추가" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "보관됨" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "설명:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "서재에 추가" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(공개)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" -msgstr "메타저오 편집" +msgstr "메타정보보 편집" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "서버 유형 선택" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "표준 이메일 계정 사용" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "OAuth2 인증이 있는 Gmail 계정" +#, fuzzy +msgid "Gmail Account" +msgstr "Gmail 계정" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Gmail 계정을 이메일 서버로 설정" +msgid "Setup Gmail Account" +msgstr "Gmail 계정 설정정" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2546,10 +2661,11 @@ msgid "Attachment Size Limit" msgstr "첨부 파일 크기 제한" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "저장 후 테스트 이메일 보내기" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "뒤로" @@ -2575,13 +2691,13 @@ msgstr "도메인 입력" msgid "Denied Domains (Blacklist)" msgstr "거부 도메인(블랙리스트)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "다음" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "텍스트 편집기에서 .kobo/Kobo eReader.conf 파일을 열고 다음을 추가(또는 편집):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "텍스트 편집기에서 .kobo/Kobo/Kobo eReader.conf 파일을 열고 다음을 추가(또는 편집):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2590,21 +2706,21 @@ msgstr "코보 연동 토큰" #: cps/templates/grid.html:21 msgid "List" -msgstr "" +msgstr "목록" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Calibre-Web Instance가 구성되지 않았습니다. 관리자에게 문의" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "이슈 생성" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "홈으로" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "로그아웃" @@ -2634,80 +2750,80 @@ msgstr "시리즈 인덱스에 따라 오름차순 정렬" msgid "Sort descending according to series index" msgstr "시리즈 인덱스에 따라 내림차순 정렬" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "시작" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "가나다(알파벳) 순" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "가나다(알파벳)순으로 정렬한 책" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "다운로드 기준 인기 도서." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "별점 기준 인기 도서." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "최근 추가된 도서" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "최신 도서" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "랜덤 정렬" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "저자별 정렬" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "출판사별 정렬" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "카테고리별 정렬" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "시리즈별 정렬" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "언어별 정렬" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "평점별 정렬" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "파일 종류별 정렬" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "서재" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "서재별 정렬" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "홈" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "탐색 활성화" @@ -2715,54 +2831,54 @@ msgstr "탐색 활성화" msgid "Search Library" msgstr "검색" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "업로드 중..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "오류" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "업로드 완료, 처리 중입니다. 잠시만 기다려 주십시오..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "설정" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "계정" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "로그아웃" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "업로드 중..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "오류" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "업로드 완료, 처리 중입니다. 잠시만 기다려 주십시오..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "설정" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "페이지를 새로고침 하지 마세요" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "탐색" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "서재 정보" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "이전" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "책 상세정보" #: cps/templates/list.html:22 msgid "Grid" -msgstr "" +msgstr "그리드드" #: cps/templates/login.html:18 msgid "Remember Me" @@ -2772,7 +2888,7 @@ msgstr "로그인 유지" msgid "Forgot Password?" msgstr "비밀번호를 잊으셨나요?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Magic Link로 로그인" @@ -2880,136 +2996,161 @@ msgstr "Calibre-Web 책 목록" msgid "epub Reader" msgstr "epub 리더" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "밝게" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "어둡게" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" -msgstr "" +msgstr "세피아" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "뒤로" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "사이드바가 열려 있을 때 텍스트 다시 배열." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "글자 크기기" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "코믹 리더" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "키보드 단축키" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "이전 페이지" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "다음 페이지" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "한 페이지 보기기" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "Long Strip Display" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "최적 크기" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "폭 조절" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "높이 조절" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "기본 크기" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "오른쪽으로 회전" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "왼쪽으로 회전" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "이미지 뒤집기" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "화면" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "관리자 페이지" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "Long Strip" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "크기" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "최적" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "폭" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "높이" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "기본" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "회전" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "뒤집기" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "수평" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "수직" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "방향" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "왼쪽에서 오른쪽" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "오른쪽에서 왼쪽" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "맨 위로 재설정" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "위치 기억" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "스크롤바" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "보기" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "숨기기" @@ -3017,7 +3158,7 @@ msgstr "숨기기" msgid "DJVU Reader" msgstr "DJVU 리더" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "PDF 리더" @@ -3034,7 +3175,7 @@ msgid "Choose a username" msgstr "사용자 이름 선택" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "이메일 주소" #: cps/templates/remote_login.html:5 @@ -3053,13 +3194,9 @@ msgstr "승인이 되면 이 장치에 자동으로 로그인됩니다." msgid "This verification link will expire in 10 minutes." msgstr "이 확인 링크는 10분 후에 만료됩니다." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" -msgstr "" +msgstr "시리즈 섬네일 표지 생성" #: cps/templates/search.html:6 msgid "No Results Found" @@ -3081,43 +3218,51 @@ msgstr "출간일(부터)" msgid "Published Date To" msgstr "출간일(까지)" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "태그 제외" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "시리즈 제외" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "서재 제외" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "언어 제외" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "확장자" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "확장자 제외" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "평점(이상)" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "평점(이하)" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "부터:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "까지:" @@ -3183,7 +3328,7 @@ msgstr "시스템 통계" #: cps/templates/stats.html:33 msgid "Program" -msgstr "" +msgstr "프로그램램" #: cps/templates/stats.html:34 msgid "Installed Version" @@ -3209,21 +3354,17 @@ msgstr "Progress" msgid "Run Time" msgstr "실행 시간" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "시작 시간" - #: cps/templates/tasks.html:20 msgid "Actions" -msgstr "" +msgstr "Actions" #: cps/templates/tasks.html:40 msgid "This task will be cancelled. Any progress made by this task will be saved." -msgstr "" +msgstr "이 작업을 취소합니다. 이 작업의 모든 진행사항은 반영됩니다." #: cps/templates/tasks.html:41 msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." -msgstr "" +msgstr "이 작업이 예약된 작업이라면, 다음 예약 시간에 다시 실행됩니다." #: cps/templates/user_edit.html:20 msgid "Reset user Password" @@ -3286,17 +3427,18 @@ msgid "Enter Username" msgstr "사용자 이름" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "이메일 주소 입력" +#, fuzzy +msgid "Enter Email" +msgstr "테스트 이메일" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "킨들 이메일 주소 입력" +msgid "Enter eReader Email" +msgstr "킨들로 보내기 이메일 주소" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "테스트 이메일" #: cps/templates/user_table.html:137 @@ -3356,10 +3498,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "선택한 서재를 코보와 동기화" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "읽음/읽지 않음 선택 표시" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "랜덤 보기 표시" - diff --git a/cps/translations/nl/LC_MESSAGES/messages.mo b/cps/translations/nl/LC_MESSAGES/messages.mo index 58f4b596..745a4124 100644 Binary files a/cps/translations/nl/LC_MESSAGES/messages.mo and b/cps/translations/nl/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/nl/LC_MESSAGES/messages.po b/cps/translations/nl/LC_MESSAGES/messages.po index 36400b8b..5f9907ee 100644 --- a/cps/translations/nl/LC_MESSAGES/messages.po +++ b/cps/translations/nl/LC_MESSAGES/messages.po @@ -8,506 +8,516 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web (GPLV3)\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" -"PO-Revision-Date: 2020-12-12 08:20+0100\n" -"Last-Translator: Marcel Maas \n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" +"PO-Revision-Date: 2023-12-20 22:00+0100\n" +"Last-Translator: Michiel Cornelissen \n" "Language: nl\n" "Language-Team: ed.driesen@telenet.be\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statistieken" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "De server is herstart, vernieuw de pagina" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Bezig met het afsluiten van de server, sluit het venster" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Opnieuw verbinden gelukt" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "Gelukt! Database opnieuw verbonden" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Onbekende opdracht" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Het boek is in de wachtrij geplaatst om te worden verstuurd aan %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Test E-Mail wordt verzonden naar %(email)s, controleer de taken voor het resultaat" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Onbekend" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Systeembeheer" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Basisconfiguratie" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Uiterlijk aanpassen" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Systeembeheerder" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Alles" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Gebruiker niet gevonden" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} gebruikers succesvol verwijderd" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Alle talen" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Misvormd verzoek" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Gast naam kan niet worden veranderd" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Gast kan deze rol niet hebben" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Kan systeembeheerder rol niet verwijderen van de laatste systeembeheerder" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "Waarde moet Waar of Onwaar zijn" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ongeldige rol" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Gast kan dit niet bekijken" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Ongeldige waarde" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Gasts locale is automatisch bepaald en kan niet handmatig worden ingesteld" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Geen geldige locale is opgegeven" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Geen geldige boek taal is opgegeven" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parameter is niet gevonden" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Ongeldige gelezen kolom" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Ongeldige beperkte kolom" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web-configuratie bijgewerkt" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Wil je je Kobo Token echt verwijderen?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Wil je dit domein echt verwijderen?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Wil je deze gebruiker echt verwijderen?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Weet je zeker dat je deze boekenplank wilt verwijderen?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Weet je zeker dat je de locales van de geselecteerde gebruiker(s) wil veranderen?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "Weet je zeker dat je de zichtbare talen voor de geselecteerde gebruiker(s) wil veranderen?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Weet je zeker dat je de geselecteerde rol van de geselecteerde gebruiker(s) wil veranderen?" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Weet je zeker dat je de geselecteerde beperkingen voor de geselecteerde gebruikers(s) wil verwijderen?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "Weet je zeker dat je de geselecteerde zichtbaarheidsbeperkingen voor de geselecteerde gebruiker(s) wil veranderen?" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Weet je zeker dat je de synchronisatiegedrag van boekenplanken voor de geselecteerde gebruiker(s) wil veranderen?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Weet je zeker dat je de locatie van de Calibre-bibliotheek wil veranderen?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" -msgstr "" +msgstr "Calibre-web gaat zoeken naar bijgewerkte omslagen en miniaturen bijwerken, dit kan even duren?" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" -msgstr "" +msgstr "Weet u zeker dat u de volledige Calibre-Web synchronisatiedatabase wilt verwijderen om een volledige synchronisatie met uw Kobo Reader te forceren?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Weigeren" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Toestaan" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" -msgstr "" +msgstr "{} synchronisatie objecten verwijderd" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Tag niet gevonden" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Ongeldige actie" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json is niet geconfigureerd voor webapplicatie" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "De locatie van het logbestand is onjuist, voer een geldige locatie in" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "De locatie vam het toegangslog is onjuist, voer een geldige locatie in" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Voer alsjeblieft een LDAP Provider, Port, DN en User Object Identifier in" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "Voer een geldig LDAP Service Account en wachtwoord in" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Voer een LDAP Service Account in" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP Groep Object Filter Moet Een \"%s\" Formaat Identificiatie hebben" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP Groep Object Filter heeft een niet-gebalanceerd haakje" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP Gebruiker Object Filter moet \"%s\" Formaat Identificatie hebben" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP Gebruiker Filter heeft een niet-gebalanceerd haakje" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP Lid Gebruiker Filter moet een \"%s\" Formaat Identificatie hebben" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "LDAP Lid Gebruiker Filter heeft een niet-gebalanceerd haakje" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CACertficaat, Certificaat of Sleutel Locatie is ongeldig. Voer alsjeblieft een geldig pad in." -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Gebruiker toevoegen" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "SMTP-instellingen bewerken" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Gmail Account succesvol geverifieerd" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Gelukt! Gmail account geverifieerd." -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Database fout: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "Test E-Mail wordt verzonden naar %(email)s, controleer de taken voor het resultaat" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Fout opgetreden bij het versturen van de test-e-mail: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Gelieve eerst je e-mail adres configureren..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "E-mailserver-instellingen bijgewerkt" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" -msgstr "" +msgstr "Bewerk instellingen van geplande taken" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" -msgstr "" +msgstr "De starttijd van de taak is ongeldig" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" -msgstr "" +msgstr "De duur van de taak is ongeldig" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" -msgstr "" +msgstr "Instellingen van geplande taken bijgewerkt" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Onbekende fout opgetreden. Probeer het later nog eens." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" -msgstr "" +msgstr "Instellingen database is niet schrijfbaar." -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Gebruiker '%(nick)s' bewerken" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Wachtwoord voor gebruiker %(user)s is hersteld" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Stel eerst SMTP-mail in..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Logbestand lezer" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Update opvragen" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Update downloaden" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Update uitpakken" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Update toepassen" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Databaseverbindingen zijn gesloten" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Bezig met stoppen van Calibre-Web" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Update voltooid, klik op 'Oké' en vernieuw de pagina" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Update mislukt:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP-fout" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Verbindingsfout" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Time-out tijdens maken van verbinding" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Algemene fout" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Geüpload bestand kon niet opgeslagen worden in de tijdelijke map" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" -msgstr "" +msgstr "Bestanden kunnen niet vervangen worden tijdens een update" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Mislukt om minstens een LDAP gebruiker aan te maken" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Het is niet gelukt tenminste een LDAP gebruiker aan te maken" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Fout: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Fout: No user returned in response of LDAP server" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Minstens een LDAP Gebruiker is niet gevonden in de Database" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Gebruiker succesvol geïmporteerd" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "Database niet gevonden, voer de juiste locatie in" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "Kan niet schrijven naar database" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "SSL-sleutellocatie is niet geldig, voer een geldig pad in" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "SSL-certificaatlocatie is niet geldig, voer een geldig pad in" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "Het wachtwoord moet tussen de 1 en 40 tekens lang zijn" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "E-mailserver-instellingen bijgewerkt" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Databaseconfiguratie" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Vul alle velden in!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "Het e-mailadres bevat geen geldige domeinnaam" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Gebruiker toevoegen" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Gebruiker '%(user)s' aangemaakt" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Bestaand account met dit e-mailadres of deze gebruikersnaam aangetroffen." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Gebruiker '%(nick)s' verwijderd" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Kan Gast gebruiker niet verwijderen" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Kan laatste systeembeheerder niet verwijderen" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" -msgstr "" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "E-mail kan niet leeg zijn en moet geldig zijn" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Gebruiker '%(nick)s' bijgewerkt" @@ -520,122 +530,122 @@ msgstr "niet geïnstalleerd" msgid "Execution permissions missing" msgstr "Kan programma niet uitvoeren" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Aangepaste kolom Nr.%(column)d bestaat niet in de Calibre Database" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Geen" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Oeps! Geselecteerd boek is niet beschikbaar. Bestand bestaat niet of is niet toegankelijk" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" -msgstr "" +msgstr "Gebruiker mist rechten om de omslag te uploaden" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Identificatoren zijn niet hoofdlettergevoelig, overschrijf huidige identificatoren" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "De metagegevens zijn bijgewerkt" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" -msgstr "" +msgstr "Fout tijdens bijwerken van boek: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Bestand %(file)s geüpload" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Bron- of doelformaat ontbreekt voor conversie" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Het boek is in de wachtrij geplaatst voor conversie naar %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Er is een fout opgetreden bij het converteren van dit boek: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Geüpload boek staat mogelijk al in de bibliotheek, controleer alvorens door te gaan: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s is geen geldige taal" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "De bestandsextensie '%(ext)s' is niet toegestaan op deze server" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Het te uploaden bestand moet voorzien zijn van een extensie" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Bestand %(filename)s kon niet opgeslagen worden in de tijdelijke map" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Omslag %(file)s niet verplaatst: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Het boekformaat is verwijderd" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Het boek is verwijderd" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" -msgstr "" +msgstr "U mist rechten om boeken te verwijderen" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "metagegevens bewerken" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s is geen geldig nummer, sla het over" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" -msgstr "" +msgstr "Gebruiker mist rechten om extra bestandsformaten te uploaden" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Kan de locatie '%(path)s' niet aanmaken (niet gemachtigd)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Kan %(file)s niet opslaan." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Bestandsformaat %(ext)s toegevoegd aan %(book)s" @@ -648,183 +658,189 @@ msgstr "Het instellen van Google Drive is niet afgerond, heractiveer Google Driv msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Het callback-domein is niet geverifieerd. Volg de stappen in de Google-ontwikkelaarsconsole om het domein te verifiëren" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s formaat niet gevonden voor boek met id: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s niet aangetroffen op Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s niet gevonden %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Versturen naar Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Deze e-mail is verstuurd via Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web - test-e-mail" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Test-e-mail" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Aan de slag met Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Registratie-e-mailadres van gebruiker: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "%(orig)s converteren naar %(format)s en versturen naar Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "%(format)s versturen naar Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "%(book)s verzonden naar Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Het opgevraagde bestand kan niet worden gelezen. Ben je hiertoe gemachtigd?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" -msgstr "" +msgstr "Gelezen/ongelezen status kan niet aangepast worden: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Het verwijderen van de boekenmap voor boek %(id)s is mislukt, het pad heeft submappen: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Verwijderen van boek %(id)s mislukt: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, fuzzy, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Verwijder boek %(id)s alleen uit database, boek pad is ongeldig: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Kan de titel '%(src)s' niet wijzigen in '%(dest)s': %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Bestand '%(file)s' niet aangetroffen op Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Kan de titel '%(src)s' niet wijzigen in '%(dest)s': %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" -msgstr "" +msgstr "Fout bij hernoemen bestand op bestandslocatie: {}" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Boeken locatie '%(path)s' niet aangetroffen op Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Bestaand account met dit e-mailadres aangetroffen." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "Bestaand account gevondne met dit e-mailadres" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Deze gebruikersnaam is al in gebruik" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Ongeldig E-Mail adres" -#: cps/helper.py:815 -msgid "Python module 'advocate' is not installed but is needed for cover uploads" -msgstr "" +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "Het wachtwoord voldoet niet aan de validatieregels" -#: cps/helper.py:825 +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "Pythonmodule 'advocate' is niet geïnstalleerd maar is nodig omslag uploads" + +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Fout bij downloaden omslag" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Onjuist omslagformaat" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" -msgstr "" +msgstr "Toegang tot localhost of het lokale netwerk niet toegestaant voor omslag uploaden" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Locatie aanmaken voor omslag mislukt" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Omslag-bestand is geen afbeelding of kon niet opgeslagen worden" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Alleen jpg/jpeg/png/webp/bmp bestanden worden ondersteund als omslag" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" -msgstr "" +msgstr "Ongeldig omslagbestand" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Alleen jpg/jpeg bestanden zijn toegestaan als omslag" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar executable niet gevonden" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Fout bij het uitvoeren van Unrar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Willekeurige boeken" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" -msgstr "" +msgstr "Voeg alle boeken toe aan de wachtrij voor het maken van een metagegevens backup" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Je kunt Calibre-Web niet vanaf de lokale computer openen om een geldige api_endpoint te krijgen voor je kobo toestel" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo Instellen" @@ -833,9 +849,9 @@ msgstr "Kobo Instellen" msgid "Register with %(provider)s" msgstr "Aanmelden bij %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "je bent ingelogd als: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -894,12 +910,13 @@ msgstr "Google OAuth fout, probeer het later nog eens." msgid "Google Oauth error: {}" msgstr "Google OAuth foutmelding: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} sterren" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Inloggen" @@ -915,149 +932,158 @@ msgstr "Toegangssleutel is verlopen" msgid "Success! Please return to your device" msgstr "Gelukt! Ga terug naar je apparaat" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Boeken" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Recent toegevoegde boeken tonen" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Populaire boeken" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Populaire boeken tonen" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Gedownloade boeken" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Gedownloade boeken tonen" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Best beoordeelde boeken" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Best beoordeelde boeken tonen" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Gelezen boeken" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Gelezen/Ongelezen boeken tonen" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Ongelezen boeken" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Ongelezen boeken tonen" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Willekeurige boeken" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Willekeurige boeken tonen" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Categorieën" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Categoriekeuze tonen" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Boekenreeksen" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Boekenreeksenkeuze tonen" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Auteurs" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Auteurkeuze tonen" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Uitgevers" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Uitgeverskeuze tonen" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Talen" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Taalkeuze tonen" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Beoordelingen" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Beoordelingen tonen" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Bestandsformaten" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Bestandsformaten tonen" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Gearchiveerde boeken" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Gearchiveerde boeken tonen" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Boekenlijst" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Boekenlijst tonen" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Zoeken" @@ -1080,15 +1106,15 @@ msgid "Rating >= %(rating)s" msgstr "Beoordeling >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Lees Status = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Fout tijdens het zoeken van aangepaste kolommen, start Calibre-Web opnieuw op" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Geavanceerd zoeken" @@ -1113,7 +1139,7 @@ msgstr "Het boek is toegevoegd aan boekenplank: %(sname)s" #: cps/shelf.py:108 msgid "You are not allowed to add a book to the shelf" -msgstr "" +msgstr "U heeft niet voldoende rechten om een boek aan deze boekenplank toe te voegen" #: cps/shelf.py:126 #, python-format @@ -1137,9 +1163,9 @@ msgstr "Het boek is verwijderd van boekenplank: %(sname)s" #: cps/shelf.py:200 msgid "Sorry you are not allowed to remove a book from this shelf" -msgstr "" +msgstr "U heeft niet voldoende rechten om een boek van deze boekenplank te verwijderen" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Boekenplank maken" @@ -1154,7 +1180,7 @@ msgstr "Pas een boekenplank aan" #: cps/shelf.py:229 msgid "Error deleting Shelf" -msgstr "" +msgstr "Fout bij verwijderen boekenplank!" #: cps/shelf.py:231 #, fuzzy @@ -1166,73 +1192,73 @@ msgstr "Het boek is verwijderd" msgid "Change order of Shelf: '%(name)s'" msgstr "Volgorde van boekenplank veranderen: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" -msgstr "" +msgstr "Je mist rechten om een openbare boekenplank te maken " -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Boekenplank '%(title)s' aangemaakt" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Boekenplank '%(title)s' is aangepast" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Er is een fout opgetreden" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Een openbare boekenplank met de naam '%(title)s' bestaat al." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Een persoonlijke boekenplank met de naam '%(title)s' bestaat al." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Boekenplank: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Kan boekenplank niet openen: de boekenplank bestaat niet of is ontoegankelijk" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Taken" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Wachten" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Mislukt" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Gestart" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Voltooid" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" -msgstr "" +msgstr "Beëindigd" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Geannuleerd" #: cps/tasks_status.py:74 -msgid "Cancelled" -msgstr "" - -#: cps/tasks_status.py:76 msgid "Unknown Status" msgstr "Onbekende status" @@ -1265,146 +1291,186 @@ msgstr "Er is een update beschikbaar. Klik op de knop hieronder om te updaten na msgid "No release information available" msgstr "Geen update-informatie beschikbaar" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Verkennen (willekeurige boeken)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Populaire boeken (meest gedownload)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Gedownloade boeken door %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Auteur: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Uitgever: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Reeks: %(serie)s" -#: cps/web.py:611 -msgid "Rating: None" -msgstr "" - #: cps/web.py:620 +msgid "Rating: None" +msgstr "Beoordeling: geen" + +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Beoordeling: %(rating)s sterren" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Bestandsformaat: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categorie: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Taal: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Downloads" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Beoordelingen" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Alle bestandsformaten" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Het boek is in de wachtrij geplaatst om te worden verstuurd aan %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Stel eerst SMTP-mail in..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Het boek is in de wachtrij geplaatst om te worden verstuurd aan %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Fout opgetreden bij het versturen van dit boek: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Stel je kindle-e-mailadres in..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "E-mailserver is niet geconfigureerd, neem contact op met de beheerder!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "Wacht alstublieft één minuut voor het registreren van de volgende gebruiker" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Registreren" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "E-mailserver is niet geconfigureerd, neem contact op met de beheerder!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Dit e-mailadres mag niet worden gebruikt voor registratie" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Er is een bevestigings-e-mail verstuurd naar je e-mailadres." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Kan de LDAP authenticatie niet activeren" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "Wacht alstublieft één minuut voor de volgende inlogpoging" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "je bent ingelogd als: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Terugvallen op login: '%(nickname)s', LDAP Server is onbereikbaar, of de gebruiker is onbekend" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Inloggen mislukt: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Verkeerde gebruikersnaam of wachtwoord" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Een nieuw wachtwoord is verzonden naar je e-mailadres" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Onbekende fout opgetreden. Probeer het later nog eens." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Geef een geldige gebruikersnaam op om je wachtwoord te herstellen" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Je bent ingelogd als: '%(nickname)s'" +msgstr "je bent ingelogd als: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)ss profiel" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Profiel bijgewerkt" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Bestaand account met dit e-mailadres aangetroffen." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Geen geldig gmail.json bestand gevonden met OAuth informatie" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s verzonden naar Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1441,41 +1507,41 @@ msgstr "Calibre mislukt met foutmelding: %(error)s" #: cps/tasks/convert.py:275 msgid "Convert" -msgstr "" +msgstr "Overzetten" #: cps/tasks/database.py:28 msgid "Reconnecting Calibre database" -msgstr "" +msgstr "Opnieuw verbinding aan het maken met Calibre database" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" -msgstr "" +msgstr "E-mail" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "metagegevens bewerken" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" -msgstr "" +msgstr "%{count}s omslagminiaturen gegenereerd" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" -msgstr "" +msgstr "Omslag miniaturen" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" -msgstr "" +msgstr "{0} serieminiaturen gegenereerd" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" -msgstr "" +msgstr "Cache met omslagminiaturen aan het opschonen" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Uploaden" @@ -1491,15 +1557,15 @@ msgstr "Gebruikersnaam" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "E-mailadres" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Kindle-e-mailadres" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Beheer" @@ -1509,8 +1575,8 @@ msgstr "Beheer" msgid "Password" msgstr "Wachtwoord" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Downloaden" @@ -1535,16 +1601,12 @@ msgstr "Verwijderen" msgid "Public Shelf" msgstr "Openbare boekenplank" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Gebruiker toevoegen" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "LDAP gebruikers importeren" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "SMTP-serverinstellingen" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1565,12 +1627,13 @@ msgstr "SMTP-gebruikersnaam" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Van e-mail" #: cps/templates/admin.html:90 -msgid "E-Mail Service" -msgstr "E-Mail Service" +#, fuzzy +msgid "Email Service" +msgstr "EMail Service" #: cps/templates/admin.html:91 msgid "Gmail via Oauth2" @@ -1639,105 +1702,107 @@ msgstr "Bewerk gebruikersinterface configuratie" #: cps/templates/admin.html:167 msgid "Scheduled Tasks" -msgstr "" +msgstr "Geplande taken" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" -msgstr "" +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "Starttijd" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" -msgstr "" +msgid "Maximum Duration" +msgstr "Maximale duur" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" -msgstr "" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" +msgstr "Genereer miniaturen" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" -msgstr "" +msgstr "Genereer serie miniaturen" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" -msgstr "" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Opnieuw verbinding maken met Calibre database" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" -msgstr "" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "Genereer backupbestanden voor metagegevens" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "Ververs cache met omslagminiaturen" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Systeembeheer" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Download foutopsporingspakket" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Logboeken bekijken" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Opnieuw verbinden met Calibre database" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Calibre-Web herstarten" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Calibre-Web stoppen" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" -msgstr "" +msgstr "Versie informatie" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versie" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Details" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Huidige versie" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Controleren op updates" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Update uitvoeren" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Weet je zeker dat je Calibre-Web wilt herstarten?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Oké" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Annuleren" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Weet je zeker dat je Calibre-Web wilt stoppen?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Bezig met bijwerken, vernieuw de pagina niet" @@ -1827,7 +1892,7 @@ msgid "Author" msgstr "Auteur" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Omschrijving" @@ -1852,7 +1917,7 @@ msgstr "Verwijderen" msgid "Add Identifier" msgstr "Identificator toevoegen" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Labels" @@ -1877,23 +1942,23 @@ msgid "Published Date" msgstr "Publicatiedatum" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Uitgever" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Taal" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Ja" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Nee" @@ -1910,8 +1975,8 @@ msgid "Fetch Metadata" msgstr "Metagegevens ophalen" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1934,8 +1999,8 @@ msgstr "Klik op de omslag om de metagegevens in het formulier te laden" msgid "Loading..." msgstr "Bezig met laden..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Sluiten" @@ -2038,11 +2103,11 @@ msgstr "Voer domeinnaam in" #: cps/templates/book_table.html:73 msgid "Comments" -msgstr "" +msgstr "Opmerkingen" #: cps/templates/book_table.html:75 msgid "Archive Status" -msgstr "" +msgstr "Archiefstatus" #: cps/templates/book_table.html:77 cps/templates/search_form.html:42 msgid "Read Status" @@ -2132,7 +2197,7 @@ msgstr "Bèta" #: cps/templates/config_edit.html:50 msgid "Trusted Hosts (Comma Separated)" -msgstr "" +msgstr "Vertrouwde hosts (komma gescheiden)" #: cps/templates/config_edit.html:61 msgid "Logfile Configuration" @@ -2156,15 +2221,15 @@ msgstr "Geavanceerde opties" #: cps/templates/config_edit.html:104 msgid "Convert non-English characters in title and author while saving to disk" -msgstr "" +msgstr "Zet niet Engelse tekens in titel en auteur om tijdens het opslaan" #: cps/templates/config_edit.html:108 msgid "Enable Uploads" msgstr "Uploaden inschakelen" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" -msgstr "" +msgid "(Please ensure that users also have upload permissions)" +msgstr "(Zorg dat gebruikers uploadrechten hebben)" #: cps/templates/config_edit.html:112 msgid "Allowed Upload Fileformats" @@ -2179,7 +2244,7 @@ msgid "Enable Public Registration" msgstr "Openbare registratie inschakelen" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Gebruik e-mail als inlognaam" #: cps/templates/config_edit.html:132 @@ -2369,6 +2434,52 @@ msgstr "Pad naar Kepubify E-book Converteerder" msgid "Location of Unrar binary" msgstr "Locatie van Unrar-programma" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth Instellingen" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "Beperk aantal mislukte inlogpogingen" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "Sessiebescherming" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "Basis" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "Sterk" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Gebruikerswachtwoord herstellen" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "Minimale wachtwoordlengte" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "Forceer getal" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "Forceer kleine letter" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "Forceer hoofdletter" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "Forceer speciaal teken" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Instellingen bekijken" @@ -2381,7 +2492,7 @@ msgstr "Aantal te tonen willekeurige boeken" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Aantal te tonen auteurs alvorens te verbergen (0=nooit verbergen)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Thema" @@ -2472,80 +2583,84 @@ msgstr "Voeg toegestane/geweigerde tags toe" msgid "Add Allowed/Denied custom column values" msgstr "Voeg toegestane/geweigerde aangepaste kolomwaarden toe" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Lezen in webbrowser" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Luisteren in webbrowser" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, fuzzy, python-format msgid "Book %(index)s of %(range)s" msgstr "Boek %(index)s van %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Gepubliceerd" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Markeren als ongelezen" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Markeren als gelezen" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Gelezen" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Terughalen uit archief" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Toevoegen aan archief" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Gearchiveerd" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Beschrijving:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Toevoegen aan boekenplank" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Openbaar)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Metagegevens bewerken" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Kies Server Type" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Gebruik Standaard E-Mail Account" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Gmail Account met OAuth2 Verificatie" +#, fuzzy +msgid "Gmail Account" +msgstr "Kies Server Type" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Gmail Account opzetten als E-Mail Server" +msgid "Setup Gmail Account" +msgstr "Gmail account instellen" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2568,10 +2683,11 @@ msgid "Attachment Size Limit" msgstr "Bijlage bestandsgrootte limiet" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Opslaan en test-e-mail versturen" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Annuleren" @@ -2597,13 +2713,13 @@ msgstr "Voer domeinnaam in" msgid "Denied Domains (Blacklist)" msgstr "Geweigerde domeinen voor registratie" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Volgende" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Open het .kobo/Kobo eReader.conf bestand in een teksteditor en voeg toe (of bewerk):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Open het .kobo/Kobo/Kobo eReader.conf bestand in een teksteditor en voeg toe (of bewerk):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2612,32 +2728,32 @@ msgstr "Kobo Sync Token" #: cps/templates/grid.html:21 msgid "List" -msgstr "" +msgstr "Lijst" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "E-mailserver is niet geconfigureerd, neem contact op met de beheerder!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Probleem melden" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Terug naar startpagina" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "Gebruiker uitloggen" #: cps/templates/index.html:71 msgid "Sort ascending according to download count" -msgstr "" +msgstr "Sorteer oplopend volgens aantal downloads" #: cps/templates/index.html:72 msgid "Sort descending according to download count" -msgstr "" +msgstr "Sorteer aflopend volgens aantal downloads" #: cps/templates/index.html:78 cps/templates/search.html:35 #: cps/templates/shelf.html:24 @@ -2657,80 +2773,80 @@ msgstr "Sorteer oplopend volgens de serie index" msgid "Sort descending according to series index" msgstr "Sorteer aflopend volgens de serie index" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Starten" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Alfabetische Boeken" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Boeken Alfabetisch gesorteerd" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Populaire publicaties uit deze catalogus, gebaseerd op Downloads." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Populaire publicaties uit deze catalogus, gebaseerd op Beoordeling." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Recent toegevoegde boeken" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Nieuwe boeken" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Willekeurige boeken" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Boeken gesorteerd op auteur" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Boeken gesorteerd op uitgever" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Boeken gesorteerd op categorie" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Boeken gesorteerd op reeks" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Boeken gesorteerd op taal" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Boeken gesorteerd op beoordeling" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Boeken gesorteerd op bestandsformaat" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Boekenplanken" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Boeken georganiseerd op boekenplanken" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Startpagina" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Navigatie aanpassen" @@ -2738,54 +2854,54 @@ msgstr "Navigatie aanpassen" msgid "Search Library" msgstr "Zoek in bibliotheek" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Bezig met uploaden..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Fout" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Uploaden voltooid, bezig met verwerken..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Instellingen" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Account" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Afmelden" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Bezig met uploaden..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Fout" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Uploaden voltooid, bezig met verwerken..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Instellingen" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Deze pagina niet vernieuwen" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Verkennen" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Informatie" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Vorige" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Boekgegevens" #: cps/templates/list.html:22 msgid "Grid" -msgstr "" +msgstr "Raster" #: cps/templates/login.html:18 msgid "Remember Me" @@ -2795,7 +2911,7 @@ msgstr "Gegevens opslaan" msgid "Forgot Password?" msgstr "Wachtwoord Vergeten?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Inloggen met magische koppeling" @@ -2905,137 +3021,162 @@ msgstr "Calibre-Web - e-boekcatalogus" msgid "epub Reader" msgstr "PDF lezer" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Licht" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Donker" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" -msgstr "" +msgstr "Sepia" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Annuleren" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Tekstindeling automatisch aanpassen als het zijpaneel geopend is." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "Lettertypegrootte" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "Comic Reader" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Sneltoetsen" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Vorige pagina" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Volgende pagina" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "Weergave van één pagina" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Optimaal inpassen" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Aanpassen aan breedte" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Aanpassen aan hoogte" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Ware grootte" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Rechtsom draaien" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Linksom draaien" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Afbeelding omdraaien" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Weergeven" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Systeembeheer" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Schaal" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Beste" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Breedte" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Hoogte" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Ware grootte" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Draaien" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Omdraaien" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Horizontaal" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Verticaal" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Richting" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Links-naar-rechts" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Rechts-naar-links" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Terugzetten naar bovenkant" +msgstr "Terug naar boven" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Positie onthouden" +msgstr "Onthoud positie" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Schuifbalk" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Toon" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Verberg" @@ -3044,7 +3185,7 @@ msgstr "Verberg" msgid "DJVU Reader" msgstr "PDF lezer" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "PDF lezer" @@ -3063,7 +3204,7 @@ msgid "Choose a username" msgstr "Kies een gebruikersnaam" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Je e-mailadres" #: cps/templates/remote_login.html:5 @@ -3082,13 +3223,9 @@ msgstr "Na controle wordt je automatisch op dit apparaat ingelogd." msgid "This verification link will expire in 10 minutes." msgstr "De link vervalt na 10 minuten." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" -msgstr "" +msgstr "Genereer serie omslagminiaturen" #: cps/templates/search.html:6 msgid "No Results Found" @@ -3110,44 +3247,52 @@ msgstr "Publicatiedatum van" msgid "Published Date To" msgstr "Publicatiedatum tot" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Labels uitsluiten" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Boekenreeksen uitsluiten" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Boekenreeksen uitsluiten" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Talen uitsluiten" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Extenties" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Extenties uitsluiten" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Met beoordeling hoger dan" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Met beoordeling lager dan" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "Van:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Tot:" @@ -3239,21 +3384,17 @@ msgstr "Voortgang" msgid "Run Time" msgstr "Looptijd" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Begintijd" - #: cps/templates/tasks.html:20 msgid "Actions" -msgstr "" +msgstr "Acties" #: cps/templates/tasks.html:40 msgid "This task will be cancelled. Any progress made by this task will be saved." -msgstr "" +msgstr "Deze taak wordt geannuleerd. De voortgang van deze taak wordt opgeslagen." #: cps/templates/tasks.html:41 msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." -msgstr "" +msgstr "Als dit een geplande taak is wordt deze opnieuw uitgevoerd tijdens de volgende geplande tijd." #: cps/templates/user_edit.html:20 msgid "Reset user Password" @@ -3285,7 +3426,7 @@ msgstr "Aanmaken/Bekijken" #: cps/templates/user_edit.html:70 msgid "Force full kobo sync" -msgstr "" +msgstr "Forceer volledige Kobo synchronisatie." #: cps/templates/user_edit.html:88 msgid "Add allowed/Denied Custom Column Values" @@ -3316,17 +3457,18 @@ msgid "Enter Username" msgstr "Voer gebruikersnaam in" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "Voer e-mailadres in" +#, fuzzy +msgid "Enter Email" +msgstr "Test-e-mail" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "Voer Kindle-e-mailadres in" +msgid "Enter eReader Email" +msgstr "Kindle-e-mailadres" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Test-e-mail" #: cps/templates/user_table.html:137 @@ -3389,10 +3531,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "Synchroniseer geselecteerde boekenplanken met Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "Toon gelezen/niet gelezen selectie" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Willekeurige boeken tonen" - diff --git a/cps/translations/no/LC_MESSAGES/messages.mo b/cps/translations/no/LC_MESSAGES/messages.mo new file mode 100644 index 00000000..07fe003e Binary files /dev/null and b/cps/translations/no/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/no/LC_MESSAGES/messages.po b/cps/translations/no/LC_MESSAGES/messages.po new file mode 100644 index 00000000..69652fb1 --- /dev/null +++ b/cps/translations/no/LC_MESSAGES/messages.po @@ -0,0 +1,3570 @@ +# Norwegian translations for Calibre-Web. +# Copyright (C) 2022 Vegard Fladby +# This file is distributed under the same license as the Calibre-Web +# project. +# FIRST AUTHOR Vegard Fladby, 2022. +msgid "" +msgstr "" +"Project-Id-Version: Calibre-Web\n" +"Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" +"PO-Revision-Date: 2023-01-06 11:00+0000\n" +"Last-Translator: Vegard Fladby \n" +"Language: no\n" +"Language-Team: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.13.1\n" + +#: cps/about.py:84 +msgid "Statistics" +msgstr "Statistikk" + +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." +msgstr "Server startet på nytt. Last inn siden på nytt" + +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." +msgstr "Utfører avslutning av server, vennligst lukk vinduet" + +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 +msgid "Unknown command" +msgstr "Ukjent kommando" + +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Test e-post i kø for sending til %(email)s, sjekk Oppgaver for resultat" + +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 +msgid "Unknown" +msgstr "Ukjent" + +#: cps/admin.py:231 +msgid "Admin page" +msgstr "Admin side" + +#: cps/admin.py:251 +msgid "Basic Configuration" +msgstr "Grunnleggende konfigurasjon" + +#: cps/admin.py:289 +msgid "UI Configuration" +msgstr "UI-konfigurasjon" + +#: cps/admin.py:323 cps/templates/admin.html:51 +msgid "Edit Users" +msgstr "Rediger brukere" + +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 +#: cps/templates/list.html:13 +msgid "All" +msgstr "Alle" + +#: cps/admin.py:394 cps/admin.py:1405 +msgid "User not found" +msgstr "Bruker ikke funnet" + +#: cps/admin.py:408 +msgid "{} users deleted successfully" +msgstr "{} brukere ble slettet" + +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 +#: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 +msgid "Show All" +msgstr "Vis alt" + +#: cps/admin.py:452 cps/admin.py:458 +msgid "Malformed request" +msgstr "Feil utformet forespørsel" + +#: cps/admin.py:470 cps/admin.py:2023 +msgid "Guest Name can't be changed" +msgstr "Gjestenavn kan ikke endres" + +#: cps/admin.py:482 +msgid "Guest can't have this role" +msgstr "Gjesten kan ikke ha denne rollen" + +#: cps/admin.py:494 cps/admin.py:1977 +msgid "No admin user remaining, can't remove admin role" +msgstr "Ingen administratorbruker igjen, kan ikke fjerne administratorrollen" + +#: cps/admin.py:498 cps/admin.py:512 +msgid "Value has to be true or false" +msgstr "Verdien må være sann eller usann" + +#: cps/admin.py:500 +msgid "Invalid role" +msgstr "Ugyldig rolle" + +#: cps/admin.py:504 +msgid "Guest can't have this view" +msgstr "Gjestene kan ikke ha denne utsikten" + +#: cps/admin.py:514 +msgid "Invalid view" +msgstr "Ugyldig visning" + +#: cps/admin.py:517 +msgid "Guest's Locale is determined automatically and can't be set" +msgstr "Gjestenes lokalitet bestemmes automatisk og kan ikke angis" + +#: cps/admin.py:521 +msgid "No Valid Locale Given" +msgstr "Ingen gyldig lokalitet gitt" + +#: cps/admin.py:532 +msgid "No Valid Book Language Given" +msgstr "Ikke oppgitt gyldig bokspråk" + +#: cps/admin.py:534 cps/editbooks.py:453 +msgid "Parameter not found" +msgstr "Parameter ikke funnet" + +#: cps/admin.py:571 +msgid "Invalid Read Column" +msgstr "Ugyldig lesekolonne" + +#: cps/admin.py:577 +msgid "Invalid Restricted Column" +msgstr "Ugyldig begrenset kolonne" + +#: cps/admin.py:597 cps/admin.py:1848 +msgid "Calibre-Web configuration updated" +msgstr "Calibre-Web-konfigurasjonen er oppdatert" + +#: cps/admin.py:609 +msgid "Do you really want to delete the Kobo Token?" +msgstr "Vil du virkelig slette Kobo-tokenet?" + +#: cps/admin.py:611 +msgid "Do you really want to delete this domain?" +msgstr "Vil du virkelig slette dette domenet?" + +#: cps/admin.py:613 +msgid "Do you really want to delete this user?" +msgstr "Vil du virkelig slette denne brukeren?" + +#: cps/admin.py:615 +msgid "Are you sure you want to delete this shelf?" +msgstr "Er du sikker på at du vil slette denne hyllen?" + +#: cps/admin.py:617 +msgid "Are you sure you want to change locales of selected user(s)?" +msgstr "Er du sikker på at du vil endre lokaliteter for valgte bruker(e)?" + +#: cps/admin.py:619 +msgid "Are you sure you want to change visible book languages for selected user(s)?" +msgstr "Er du sikker på at du vil endre synlige bokspråk for valgte bruker(e)?" + +#: cps/admin.py:621 +msgid "Are you sure you want to change the selected role for the selected user(s)?" +msgstr "Er du sikker på at du vil endre den valgte rollen for den(e) valgte brukeren?" + +#: cps/admin.py:623 +msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" +msgstr "Er du sikker på at du vil endre de valgte begrensningene for den(e) valgte brukeren?" + +#: cps/admin.py:625 +msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" +msgstr "Er du sikker på at du vil endre de valgte synlighetsbegrensningene for valgte bruker(e)?" + +#: cps/admin.py:628 +msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" +msgstr "Er du sikker på at du vil endre atferden for hyllesynkronisering for de(n) valgte brukeren(e)?" + +#: cps/admin.py:630 +msgid "Are you sure you want to change Calibre library location?" +msgstr "Er du sikker på at du vil endre plassering av Caliber-biblioteket?" + +#: cps/admin.py:632 +msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" +msgstr "Calibre-Web vil søke etter oppdaterte omslag og oppdatere omslagsminiatyrbilder, kan dette ta litt tid?" + +#: cps/admin.py:635 +msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +msgstr "Er du sikker på at du vil slette Calibre-Webs synkroniseringsdatabase for å tvinge frem en full synkronisering med Kobo Reader?" + +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 +#: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 +#: cps/templates/user_table.html:58 +msgid "Deny" +msgstr "Benekte" + +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 +#: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 +#: cps/templates/user_table.html:61 +msgid "Allow" +msgstr "Tillate" + +#: cps/admin.py:921 +msgid "{} sync entries deleted" +msgstr "{} synkroniseringsoppføringer slettet" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Merket ble ikke funnet" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Ugyldig handling" + +#: cps/admin.py:1111 +msgid "client_secrets.json Is Not Configured For Web Application" +msgstr "client_secrets.json er ikke konfigurert for webapplikasjon" + +#: cps/admin.py:1156 +msgid "Logfile Location is not Valid, Please Enter Correct Path" +msgstr "Loggfilplasseringen er ikke gyldig, skriv inn riktig bane" + +#: cps/admin.py:1162 +msgid "Access Logfile Location is not Valid, Please Enter Correct Path" +msgstr "Plasseringen av tilgangsloggfilen er ikke gyldig, skriv inn riktig bane" + +#: cps/admin.py:1196 +msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" +msgstr "Angi en LDAP-leverandør, port, DN og brukerobjektidentifikator" + +#: cps/admin.py:1202 +msgid "Please Enter a LDAP Service Account and Password" +msgstr "Vennligst skriv inn en LDAP-tjenestekonto og passord" + +#: cps/admin.py:1205 +msgid "Please Enter a LDAP Service Account" +msgstr "Angi en LDAP-tjenestekonto" + +#: cps/admin.py:1210 +#, python-format +msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" +msgstr "LDAP-gruppeobjektfilter må ha én \"%s\"-formatidentifikator" + +#: cps/admin.py:1212 +msgid "LDAP Group Object Filter Has Unmatched Parenthesis" +msgstr "LDAP-gruppeobjektfilter har uovertruffen parentes" + +#: cps/admin.py:1216 +#, python-format +msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" +msgstr "LDAP-brukerobjektfilter må ha én \"%s\"-formatidentifikator" + +#: cps/admin.py:1218 +msgid "LDAP User Object Filter Has Unmatched Parenthesis" +msgstr "LDAP-brukerobjektfilter har uovertruffen parentes" + +#: cps/admin.py:1225 +#, python-format +msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" +msgstr "LDAP-medlemsbrukerfilter må ha én \"%s\"-formatidentifikator" + +#: cps/admin.py:1227 +msgid "LDAP Member User Filter Has Unmatched Parenthesis" +msgstr "LDAP-medlemsbrukerfilter har uovertruffen parentes" + +#: cps/admin.py:1234 +msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" +msgstr "LDAP CA-sertifikat, sertifikat eller nøkkelplassering er ikke gyldig. Angi riktig bane" + +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Legg til ny bruker" + +#: cps/admin.py:1274 cps/templates/admin.html:100 +#, fuzzy +msgid "Edit Email Server Settings" +msgstr "Rediger e-postserverinnstillinger" + +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" + +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 +#, fuzzy, python-format +msgid "Oops! Database Error: %(error)s." +msgstr "Databasefeil: %(error)s." + +#: cps/admin.py:1323 +#, python-format +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +msgstr "Test e-post i kø for sending til %(email)s, sjekk Oppgaver for resultat" + +#: cps/admin.py:1326 +#, python-format +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "Det oppsto en feil ved sending av test-e-posten: %(res)s" + +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "Vennligst konfigurer e-postadressen din først..." + +#: cps/admin.py:1330 +#, fuzzy +msgid "Email Server Settings updated" +msgstr "E-postserverinnstillinger oppdatert" + +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "Rediger innstillinger for planlagte oppgaver" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "Ugyldig starttidspunkt for spesifisert oppgave" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "Ugyldig varighet for spesifisert oppgave" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Innstillinger for planlagte oppgaver er oppdatert" + +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +#, fuzzy +msgid "Oops! An unknown error occurred. Please try again later." +msgstr "En ukjent feil oppstod. Prøv igjen senere." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "Innstillinger DB er ikke skrivbar" + +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "Rediger bruker %(nick)s" + +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" +msgstr "Passord for bruker %(user)s tilbakestilling" + +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." +msgstr "Vennligst konfigurer SMTP-postinnstillingene først..." + +#: cps/admin.py:1453 +msgid "Logfile viewer" +msgstr "Loggfilviser" + +#: cps/admin.py:1519 +msgid "Requesting update package" +msgstr "Ber om oppdateringspakke" + +#: cps/admin.py:1520 +msgid "Downloading update package" +msgstr "Laster ned oppdateringspakken" + +#: cps/admin.py:1521 +msgid "Unzipping update package" +msgstr "Pakker ut oppdateringspakken" + +#: cps/admin.py:1522 +msgid "Replacing files" +msgstr "Erstatter filer" + +#: cps/admin.py:1523 +msgid "Database connections are closed" +msgstr "Databaseforbindelser er stengt" + +#: cps/admin.py:1524 +msgid "Stopping server" +msgstr "Stopper server" + +#: cps/admin.py:1525 +msgid "Update finished, please press okay and reload page" +msgstr "Oppdatering fullført, vennligst trykk OK og last inn siden på nytt" + +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 +msgid "Update failed:" +msgstr "Oppdatering mislyktes:" + +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +msgid "HTTP Error" +msgstr "HTTP-feil" + +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 +msgid "Connection error" +msgstr "Tilkoblingsfeil" + +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 +msgid "Timeout while establishing connection" +msgstr "Tidsavbrudd under etablering av tilkobling" + +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 +msgid "General error" +msgstr "Generell feil" + +#: cps/admin.py:1530 +msgid "Update file could not be saved in temp dir" +msgstr "Oppdateringsfilen kunne ikke lagres i temp dir" + +#: cps/admin.py:1531 +msgid "Files could not be replaced during update" +msgstr "Filer kunne ikke erstattes under oppdatering" + +#: cps/admin.py:1555 +msgid "Failed to extract at least One LDAP User" +msgstr "Kunne ikke pakke ut minst én LDAP-bruker" + +#: cps/admin.py:1600 +msgid "Failed to Create at Least One LDAP User" +msgstr "Kunne ikke opprette minst én LDAP-bruker" + +#: cps/admin.py:1613 +#, python-format +msgid "Error: %(ldaperror)s" +msgstr "Feil: %(ldaperror)s" + +#: cps/admin.py:1617 +msgid "Error: No user returned in response of LDAP server" +msgstr "Feil: Ingen bruker ble returnert som svar fra LDAP-serveren" + +#: cps/admin.py:1650 +msgid "At Least One LDAP User Not Found in Database" +msgstr "Minst én LDAP-bruker ikke funnet i databasen" + +#: cps/admin.py:1652 +msgid "{} User Successfully Imported" +msgstr "{} Bruker ble importert" + +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "DB-plassering er ikke gyldig, skriv inn riktig bane" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "DB er ikke skrivbar" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "Nøkkelfilplasseringen er ikke gyldig. Angi riktig bane" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "Sertifikatfilplasseringen er ikke gyldig, vennligst skriv inn riktig bane" + +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "Databaseinnstillinger oppdatert" + +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Databasekonfigurasjon" + +#: cps/admin.py:1894 cps/web.py:1270 +#, fuzzy +msgid "Oops! Please complete all fields." +msgstr "Vennligst fyll ut alle feltene!" + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "E-post er ikke fra gyldig domene" + +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Legg til ny bruker" + +#: cps/admin.py:1920 +#, python-format +msgid "User '%(user)s' created" +msgstr "Bruker '%(user)s' opprettet" + +#: cps/admin.py:1926 +#, fuzzy +msgid "Oops! An account already exists for this Email. or name." +msgstr "Fant en eksisterende konto for denne e-postadressen eller navnet." + +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Brukeren '%(nick)s' slettet" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Kan ikke slette gjestebruker" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "Ingen administratorbruker igjen, kan ikke slette bruker" + +#: cps/admin.py:2017 cps/web.py:1445 +#, fuzzy +msgid "Email can't be empty and has to be a valid Email" +msgstr "E-postadresse kan ikke være tom og må være en gyldig e-post" + +#: cps/admin.py:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Bruker '%(nick)s' oppdatert" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "ikke installert" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Utførelsestillatelser mangler" + +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 +#, python-format +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "Egendefinert kolonnenr.%(column)d finnes ikke i caliber-databasen" + +#: cps/db.py:993 cps/templates/config_edit.html:204 +#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 +msgid "None" +msgstr "Ingen" + +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +#, fuzzy +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" +msgstr "Oops! Den valgte boktittelen er utilgjengelig. Filen eksisterer ikke eller er ikke tilgjengelig" + +#: cps/editbooks.py:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" +msgstr "Brukeren har ingen rettigheter til å laste opp cover" + +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +msgstr "Identifikatorer skiller ikke mellom store og små bokstaver, overskriver gammel identifikator" + +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Metadata ble oppdatert" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" +msgstr "Feil ved redigering av bok: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Fil %(file)s lastet opp" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Kilde- eller målformat for konvertering mangler" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "Boken ble satt i kø for konvertering til %(book_format)s" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "Det oppsto en feil ved konvertering av denne boken: %(res)s" + +#: cps/editbooks.py:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " +msgstr "Opplastet bok finnes sannsynligvis i biblioteket, vurder å endre før du laster opp ny: " + +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "'%(langname)s' er ikke et gyldig språk" + +#: cps/editbooks.py:741 cps/editbooks.py:1179 +#, python-format +msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" +msgstr "Filtypen «%(ext)s» er ikke tillatt å lastes opp til denne serveren" + +#: cps/editbooks.py:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "Filen som skal lastes opp må ha en utvidelse" + +#: cps/editbooks.py:753 +#, python-format +msgid "File %(filename)s could not saved to temp dir" +msgstr "Filen %(filename)s kunne ikke lagres i midlertidig dir" + +#: cps/editbooks.py:773 +#, python-format +msgid "Failed to Move Cover File %(file)s: %(error)s" +msgstr "Kunne ikke flytte omslagsfil %(file)s: %(error)s" + +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Bokformatet er slettet" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Boken ble slettet" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "Du mangler tillatelser til å slette bøker" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "redigere metadata" + +#: cps/editbooks.py:992 +#, python-format +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s er ikke et gyldig tall, hopper over" + +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "Brukeren har ingen rettigheter til å laste opp flere filformater" + +#: cps/editbooks.py:1195 +#, python-format +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Kunne ikke opprette banen %(path)s (Tillatelse nektet)." + +#: cps/editbooks.py:1200 +#, python-format +msgid "Failed to store file %(file)s." +msgstr "Kunne ikke lagre filen %(file)s." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Filformat %(ext)s lagt til %(book)s" + +#: cps/gdrive.py:58 +msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" +msgstr "Google Disk-konfigurasjonen er ikke fullført. Prøv å deaktivere og aktivere Google Disk på nytt" + +#: cps/gdrive.py:95 +msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" +msgstr "Tilbakeringingsdomene er ikke bekreftet. Følg fremgangsmåten for å bekrefte domenet i Googles utviklerkonsoll" + +#: cps/helper.py:81 +#, python-format +msgid "%(format)s format not found for book id: %(book)d" +msgstr "%(format)s format ikke funnet for bok-ID: %(book)d" + +#: cps/helper.py:88 cps/tasks/convert.py:75 +#, python-format +msgid "%(format)s not found on Google Drive: %(fn)s" +msgstr "%(format)s ikke funnet på Google Disk: %(fn)s" + +#: cps/helper.py:93 +#, python-format +msgid "%(format)s not found: %(fn)s" +msgstr "%(format)s ikke funnet: %(fn)s" + +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +#, fuzzy +msgid "Send to eReader" +msgstr "Send til E-Reader" + +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." +msgstr "Denne e-posten er sendt via Calibre-Web." + +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" +msgstr "Calibre-Web test e-post" + +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" +msgstr "Test e-post" + +#: cps/helper.py:133 +msgid "Get Started with Calibre-Web" +msgstr "Kom i gang med Calibre-Web" + +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" +msgstr "Registrerings-e-post for bruker: %(name)s" + +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +msgid "Convert %(orig)s to %(format)s and send to eReader" +msgstr "Konverter %(orig)s til %(format)s og send til E-Reader" + +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" +msgstr "Send %(format)s til E-Reader" + +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" +msgstr "%(book)s sendes til E-Reader" + +#: cps/helper.py:227 +msgid "The requested file could not be read. Maybe wrong permissions?" +msgstr "Den forespurte filen kunne ikke leses. Kanskje feil tillatelser?" + +#: cps/helper.py:342 +msgid "Read status could not set: {}" +msgstr "Lesestatus kunne ikke angis: {}" + +#: cps/helper.py:365 +#, python-format +msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" +msgstr "Sletting av bokmappe for bok %(id)s mislyktes, banen har undermapper: %(path)s" + +#: cps/helper.py:371 +#, python-format +msgid "Deleting book %(id)s failed: %(message)s" +msgstr "Sletting av bok %(id)s mislyktes: %(message)s" + +#: cps/helper.py:382 +#, python-format +msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" +msgstr "Sletter bok %(id)s kun fra databasen, bokbanen i databasen er ikke gyldig: %(path)s" + +#: cps/helper.py:447 +#, python-format +msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Endre navn på forfatter fra: '%(src)s' til '%(dest)s' mislyktes med feil: %(error)s" + +#: cps/helper.py:519 cps/helper.py:528 +#, python-format +msgid "File %(file)s not found on Google Drive" +msgstr "Fil %(file)s ikke funnet på Google Disk" + +#: cps/helper.py:562 +#, python-format +msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Endre navn på tittel fra: '%(src)s' til '%(dest)s' mislyktes med feil: %(error)s" + +#: cps/helper.py:582 +msgid "Error in rename file in path: {}" +msgstr "Feil i endre navn på fil i banen: {}" + +#: cps/helper.py:600 +#, python-format +msgid "Book path %(path)s not found on Google Drive" +msgstr "Finner ikke bokbane %(path)s på Google Disk" + +#: cps/helper.py:665 +#, fuzzy +msgid "Found an existing account for this Email address" +msgstr "Fant en eksisterende konto for denne e-postadressen" + +#: cps/helper.py:673 +msgid "This username is already taken" +msgstr "Dette brukernavnet er allerede tatt" + +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" +msgstr "Ugyldig format for e-postadresse" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "Python-modulen 'advocate' er ikke installert, men er nødvendig for omslagsopplastinger" + +#: cps/helper.py:862 +msgid "Error Downloading Cover" +msgstr "Feil ved nedlasting av cover" + +#: cps/helper.py:865 +msgid "Cover Format Error" +msgstr "Omslagsformatfeil" + +#: cps/helper.py:868 +msgid "You are not allowed to access localhost or the local network for cover uploads" +msgstr "Du har ikke tilgang til localhost eller det lokale nettverket for coveropplastinger" + +#: cps/helper.py:878 +msgid "Failed to create path for cover" +msgstr "Kunne ikke opprette bane for dekning" + +#: cps/helper.py:894 +msgid "Cover-file is not a valid image file, or could not be stored" +msgstr "Cover-filen er ikke en gyldig bildefil, eller kunne ikke lagres" + +#: cps/helper.py:905 +msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" +msgstr "Bare jpg/jpeg/png/webp/bmp-filer støttes som coverfile" + +#: cps/helper.py:917 +msgid "Invalid cover file content" +msgstr "Ugyldig omslagsfilinnhold" + +#: cps/helper.py:921 +msgid "Only jpg/jpeg files are supported as coverfile" +msgstr "Bare jpg/jpeg-filer støttes som coverfile" + +#: cps/helper.py:973 +msgid "Unrar binary file not found" +msgstr "Unrar binær fil ikke funnet" + +#: cps/helper.py:984 +msgid "Error executing UnRar" +msgstr "Feil ved kjøring av UnRar" + +#: cps/helper.py:1077 +msgid "Cover" +msgstr "Dekke" + +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "Sett alle bøker i kø for sikkerhetskopiering av metadata" + +#: cps/kobo_auth.py:90 +msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" +msgstr "Gå til Calibre-Web fra ikke-lokale vert for å få gyldig api_endpoint for kobo-enhet" + +#: cps/kobo_auth.py:116 +msgid "Kobo Setup" +msgstr "Kobo oppsett" + +#: cps/oauth_bb.py:77 +#, python-format +msgid "Register with %(provider)s" +msgstr "Registrer deg hos %(provider)s" + +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 +#, fuzzy, python-format +msgid "Success! You are now logged in as: %(nickname)s" +msgstr "du er nå logget på som: '%(nickname)s'" + +#: cps/oauth_bb.py:148 +#, python-format +msgid "Link to %(oauth)s Succeeded" +msgstr "Link til %(oauth)s lyktes" + +#: cps/oauth_bb.py:155 +msgid "Login failed, No User Linked With OAuth Account" +msgstr "Pålogging mislyktes, ingen bruker koblet til OAuth-konto" + +#: cps/oauth_bb.py:197 +#, python-format +msgid "Unlink to %(oauth)s Succeeded" +msgstr "Fjern koblingen til %(oauth)s" + +#: cps/oauth_bb.py:202 +#, python-format +msgid "Unlink to %(oauth)s Failed" +msgstr "Fjern koblingen til %(oauth)s mislyktes" + +#: cps/oauth_bb.py:205 +#, python-format +msgid "Not Linked to %(oauth)s" +msgstr "Ikke koblet til %(oauth)s" + +#: cps/oauth_bb.py:261 +msgid "Failed to log in with GitHub." +msgstr "Kunne ikke logge på med GitHub." + +#: cps/oauth_bb.py:267 +msgid "Failed to fetch user info from GitHub." +msgstr "Kunne ikke hente brukerinformasjon fra GitHub." + +#: cps/oauth_bb.py:279 +msgid "Failed to log in with Google." +msgstr "Kunne ikke logge på med Google." + +#: cps/oauth_bb.py:285 +msgid "Failed to fetch user info from Google." +msgstr "Kunne ikke hente brukerinformasjon fra Google." + +#: cps/oauth_bb.py:332 +msgid "GitHub Oauth error, please retry later." +msgstr "GitHub Oauth-feil, prøv igjen senere." + +#: cps/oauth_bb.py:335 +msgid "GitHub Oauth error: {}" +msgstr "GitHub Oauth-feil: {}" + +#: cps/oauth_bb.py:356 +msgid "Google Oauth error, please retry later." +msgstr "Google Oauth-feil, prøv igjen senere." + +#: cps/oauth_bb.py:359 +msgid "Google Oauth error: {}" +msgstr "Google Oauth-feil: {}" + +#: cps/opds.py:274 +msgid "{} Stars" +msgstr "{} Stjerner" + +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 +msgid "Login" +msgstr "Logg Inn" + +#: cps/remotelogin.py:74 cps/remotelogin.py:108 +msgid "Token not found" +msgstr "Token ikke funnet" + +#: cps/remotelogin.py:83 cps/remotelogin.py:116 +msgid "Token has expired" +msgstr "Token har utløpt" + +#: cps/remotelogin.py:92 +msgid "Success! Please return to your device" +msgstr "Suksess! Gå tilbake til enheten din" + +#: cps/render_template.py:42 cps/web.py:414 +msgid "Books" +msgstr "Bøker" + +#: cps/render_template.py:44 +msgid "Show recent books" +msgstr "Vis nyere bøker" + +#: cps/render_template.py:45 cps/templates/index.xml:26 +msgid "Hot Books" +msgstr "Hot bøker" + +#: cps/render_template.py:47 +msgid "Show Hot Books" +msgstr "Vis populære bøker" + +#: cps/render_template.py:49 cps/render_template.py:54 +msgid "Downloaded Books" +msgstr "Nedlastede bøker" + +#: cps/render_template.py:51 cps/render_template.py:56 +#: cps/templates/user_table.html:167 +msgid "Show Downloaded Books" +msgstr "Vis nedlastede bøker" + +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 +msgid "Top Rated Books" +msgstr "Topprangerte bøker" + +#: cps/render_template.py:61 cps/templates/user_table.html:161 +msgid "Show Top Rated Books" +msgstr "Vis best rangerte bøker" + +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 +msgid "Read Books" +msgstr "Lese bøker" + +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" +msgstr "Vis lest og ulest" + +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 +msgid "Unread Books" +msgstr "Uleste bøker" + +#: cps/render_template.py:68 +msgid "Show unread" +msgstr "Vis ulest" + +#: cps/render_template.py:69 +msgid "Discover" +msgstr "Oppdage" + +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 +msgid "Show Random Books" +msgstr "Vis tilfeldige bøker" + +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 +msgid "Categories" +msgstr "Kategorier" + +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" +msgstr "Vis kategorivalg" + +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 +msgid "Series" +msgstr "Serie" + +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" +msgstr "Vis serieutvalg" + +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 +msgid "Authors" +msgstr "Forfattere" + +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" +msgstr "Vis forfattervalg" + +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 +msgid "Publishers" +msgstr "Forlag" + +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" +msgstr "Vis utgivervalg" + +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 +msgid "Languages" +msgstr "Språk" + +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" +msgstr "Vis språkvalg" + +#: cps/render_template.py:89 cps/templates/index.xml:105 +msgid "Ratings" +msgstr "Vurderinger" + +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" +msgstr "Vis vurderingsvalg" + +#: cps/render_template.py:92 cps/templates/index.xml:113 +msgid "File formats" +msgstr "Filformater" + +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" +msgstr "Vis valg av filformater" + +#: cps/render_template.py:96 cps/web.py:776 +msgid "Archived Books" +msgstr "Arkiverte bøker" + +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Vis arkiverte bøker" + +#: cps/render_template.py:101 cps/web.py:807 +msgid "Books List" +msgstr "Bøker Liste" + +#: cps/render_template.py:103 cps/templates/user_table.html:168 +msgid "Show Books List" +msgstr "Vis bokliste" + +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 +#: cps/templates/layout.html:46 cps/templates/layout.html:49 +#: cps/templates/search_form.html:227 +msgid "Search" +msgstr "Søk" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Publisert etter " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Publisert før " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Vurdering <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Vurdering >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Lesestatus = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "Feil ved søk etter egendefinerte kolonner. Start Calibre-Web på nytt" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Avansert søk" + +#: cps/shelf.py:49 cps/shelf.py:103 +msgid "Invalid shelf specified" +msgstr "Ugyldig hylle er angitt" + +#: cps/shelf.py:55 +msgid "Sorry you are not allowed to add a book to that shelf" +msgstr "Beklager at du ikke har lov til å legge til en bok i den hyllen" + +#: cps/shelf.py:64 +#, python-format +msgid "Book is already part of the shelf: %(shelfname)s" +msgstr "Boken er allerede en del av hyllen: %(shelfname)s" + +#: cps/shelf.py:89 +#, python-format +msgid "Book has been added to shelf: %(sname)s" +msgstr "Boken er lagt til i hyllen: %(sname)s" + +#: cps/shelf.py:108 +msgid "You are not allowed to add a book to the shelf" +msgstr "Du har ikke lov til å legge en bok i hyllen" + +#: cps/shelf.py:126 +#, python-format +msgid "Books are already part of the shelf: %(name)s" +msgstr "Bøker er allerede en del av hyllen: %(name)s" + +#: cps/shelf.py:138 +#, python-format +msgid "Books have been added to shelf: %(sname)s" +msgstr "Bøker er lagt til i hyllen: %(sname)s" + +#: cps/shelf.py:145 +#, python-format +msgid "Could not add books to shelf: %(sname)s" +msgstr "Kunne ikke legge til bøker i hyllen: %(sname)s" + +#: cps/shelf.py:191 +#, python-format +msgid "Book has been removed from shelf: %(sname)s" +msgstr "Boken er fjernet fra hyllen: %(sname)s" + +#: cps/shelf.py:200 +msgid "Sorry you are not allowed to remove a book from this shelf" +msgstr "Beklager at du ikke har lov til å fjerne en bok fra denne hyllen" + +#: cps/shelf.py:210 cps/templates/layout.html:157 +msgid "Create a Shelf" +msgstr "Lag en hylle" + +#: cps/shelf.py:218 +msgid "Sorry you are not allowed to edit this shelf" +msgstr "Beklager at du ikke har lov til å redigere denne hyllen" + +#: cps/shelf.py:220 +msgid "Edit a shelf" +msgstr "Rediger en hylle" + +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Feil ved sletting av hylle" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Hylle slettet" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Endre rekkefølgen på hylle: '%(name)s'" + +#: cps/shelf.py:316 +msgid "Sorry you are not allowed to create a public shelf" +msgstr "Beklager at du ikke har lov til å opprette en offentlig hylle" + +#: cps/shelf.py:333 +#, python-format +msgid "Shelf %(title)s created" +msgstr "Hylle %(title)s opprettet" + +#: cps/shelf.py:336 +#, python-format +msgid "Shelf %(title)s changed" +msgstr "Hylle %(title)s endret" + +#: cps/shelf.py:350 +msgid "There was an error" +msgstr "det var en feil" + +#: cps/shelf.py:372 +#, python-format +msgid "A public shelf with the name '%(title)s' already exists." +msgstr "En offentlig hylle med navnet '%(title)s' eksisterer allerede." + +#: cps/shelf.py:383 +#, python-format +msgid "A private shelf with the name '%(title)s' already exists." +msgstr "En privat hylle med navnet '%(title)s' eksisterer allerede." + +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "Hylle: '%(name)s'" + +#: cps/shelf.py:469 +msgid "Error opening shelf. Shelf does not exist or is not accessible" +msgstr "Feil ved åpning av hylle. Hylle finnes ikke eller er ikke tilgjengelig" + +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Oppgaver" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Venter" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Mislyktes" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Startet" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Ferdig" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Endte" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "avbrutt" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Ukjent status" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 +msgid "Unexpected data while reading update information" +msgstr "Uventede data under lesing av oppdateringsinformasjon" + +#: cps/updater.py:438 cps/updater.py:550 +msgid "No update available. You already have the latest version installed" +msgstr "Ingen oppdatering tilgjengelig. Du har allerede den nyeste versjonen installert" + +#: cps/updater.py:456 +msgid "A new update is available. Click on the button below to update to the latest version." +msgstr "En ny oppdatering er tilgjengelig. Klikk på knappen nedenfor for å oppdatere til siste versjon." + +#: cps/updater.py:474 +msgid "Could not fetch update information" +msgstr "Kunne ikke hente oppdateringsinformasjon" + +#: cps/updater.py:484 +msgid "Click on the button below to update to the latest stable version." +msgstr "Klikk på knappen nedenfor for å oppdatere til siste stabile versjon." + +#: cps/updater.py:493 cps/updater.py:507 cps/updater.py:518 +#, python-format +msgid "A new update is available. Click on the button below to update to version: %(version)s" +msgstr "En ny oppdatering er tilgjengelig. Klikk på knappen nedenfor for å oppdatere til versjon: %(version)s" + +#: cps/updater.py:536 +msgid "No release information available" +msgstr "Ingen utgivelsesinformasjon tilgjengelig" + +#: cps/templates/index.html:6 cps/web.py:441 +msgid "Discover (Random Books)" +msgstr "Discover (tilfeldige bøker)" + +#: cps/web.py:477 +msgid "Hot Books (Most Downloaded)" +msgstr "Hot Books (mest nedlastede)" + +#: cps/web.py:508 +#, python-format +msgid "Downloaded books by %(user)s" +msgstr "Lastet ned bøker av %(user)s" + +#: cps/web.py:541 +#, python-format +msgid "Author: %(name)s" +msgstr "Forfatter: %(name)s" + +#: cps/web.py:577 +#, python-format +msgid "Publisher: %(name)s" +msgstr "Utgiver: %(name)s" + +#: cps/web.py:605 +#, python-format +msgid "Series: %(serie)s" +msgstr "Serie: %(serie)s" + +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Vurdering: Ingen" + +#: cps/web.py:629 +#, python-format +msgid "Rating: %(rating)s stars" +msgstr "Rangering: %(rating)s stjerner" + +#: cps/web.py:645 +#, python-format +msgid "File format: %(format)s" +msgstr "Filformat: %(format)s" + +#: cps/web.py:682 +#, python-format +msgid "Category: %(name)s" +msgstr "Kategori: %(name)s" + +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Språk: %(name)s" + +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "Nedlastinger" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "Rangeringsliste" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Liste over filformater" + +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Vennligst konfigurer SMTP-postinnstillingene først..." + +#: cps/web.py:1240 +#, fuzzy, python-format +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Boken ble satt i kø for sending til %(eReadermail)s" + +#: cps/web.py:1243 +#, fuzzy, python-format +msgid "Oops! There was an error sending book: %(res)s" +msgstr "Oops! Det oppsto en feil ved sending av denne boken: %(res)s" + +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "Vennligst oppdater profilen din med en gyldig Send til Kindle-e-postadresse." + +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" + +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 +msgid "Register" +msgstr "Registrere" + +#: cps/web.py:1266 cps/web.py:1313 +#, fuzzy +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "E-postserveren er ikke konfigurert, kontakt administratoren din!" + +#: cps/web.py:1299 +#, fuzzy +msgid "Oops! Your Email is not allowed." +msgstr "Din e-post kan ikke registreres" + +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "" + +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy +msgid "Cannot activate LDAP authentication" +msgstr "Kan ikke aktivere LDAP-autentisering" + +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "du er nå logget på som: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format +msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" +msgstr "Reservepålogging som: '%(nickname)s', LDAP-serveren er ikke tilgjengelig, eller brukeren er ukjent" + +#: cps/web.py:1388 +#, fuzzy, python-format +msgid "Could not login: %(message)s" +msgstr "Kunne ikke logge på: %(message)s" + +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy +msgid "Wrong Username or Password" +msgstr "Vennligst skriv inn gyldig brukernavn for å tilbakestille passordet" + +#: cps/web.py:1399 +#, fuzzy +msgid "New Password was send to your email address" +msgstr "Nytt passord ble sendt til e-postadressen din" + +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "En ukjent feil oppstod. Prøv igjen senere." + +#: cps/web.py:1405 +#, fuzzy +msgid "Please enter valid username to reset password" +msgstr "Vennligst skriv inn gyldig brukernavn for å tilbakestille passordet" + +#: cps/web.py:1413 +#, fuzzy, python-format +msgid "You are now logged in as: '%(nickname)s'" +msgstr "du er nå logget på som: '%(nickname)s'" + +#: cps/web.py:1471 cps/web.py:1521 +#, fuzzy, python-format +msgid "%(name)s's Profile" +msgstr "%(name)s sin profil" + +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" +msgstr "Profil oppdatert" + +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "" + +#: cps/services/gmail.py:58 +msgid "Found no valid gmail.json file with OAuth information" +msgstr "Fant ingen gyldig gmail.json-fil med OAuth-informasjon" + +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s sendes til E-Reader" + +#: cps/tasks/convert.py:153 +#, python-format +msgid "Calibre ebook-convert %(tool)s not found" +msgstr "Caliber ebook-convert %(tool)s ble ikke funnet" + +#: cps/tasks/convert.py:186 +#, python-format +msgid "%(format)s format not found on disk" +msgstr "%(format)s format ikke funnet på disken" + +#: cps/tasks/convert.py:190 +msgid "Ebook converter failed with unknown error" +msgstr "Ebook-konvertering mislyktes med ukjent feil" + +#: cps/tasks/convert.py:202 +#, python-format +msgid "Kepubify-converter failed: %(error)s" +msgstr "Kepubify-konvertering mislyktes: %(error)s" + +#: cps/tasks/convert.py:224 +#, python-format +msgid "Converted file not found or more than one file in folder %(folder)s" +msgstr "Konvertert fil ikke funnet eller mer enn én fil i mappen %(folder)s" + +#: cps/tasks/convert.py:247 +#, python-format +msgid "Ebook-converter failed: %(error)s" +msgstr "Ebook-konvertering mislyktes: %(error)s" + +#: cps/tasks/convert.py:270 +#, python-format +msgid "Calibre failed with error: %(error)s" +msgstr "Caliber mislyktes med feil: %(error)s" + +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Konvertere" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Kobler til Caliber-databasen på nytt" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "E-post" + +#: cps/tasks/metadata_backup.py:46 +msgid "Backing up Metadata" +msgstr "Sikkerhetskopierer metadata" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "Genererte %(count)s forsideminiatyrbilder" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "Forsideminiatyrbilder" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "Genererte {0} serieminiatyrbilder" + +#: cps/tasks/thumbnail.py:454 +msgid "Clearing cover thumbnail cache" +msgstr "Tømmer cache for miniatyrbilde for omslag" + +#: cps/tasks/upload.py:38 cps/templates/admin.html:20 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Laste opp" + +#: cps/templates/admin.html:9 +msgid "Users" +msgstr "Brukere" + +#: cps/templates/admin.html:13 cps/templates/login.html:9 +#: cps/templates/login.html:10 cps/templates/register.html:9 +#: cps/templates/user_edit.html:10 cps/templates/user_table.html:134 +msgid "Username" +msgstr "Brukernavn" + +#: cps/templates/admin.html:14 cps/templates/register.html:14 +#: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 +#, fuzzy +msgid "Email" +msgstr "E-post" + +#: cps/templates/admin.html:15 cps/templates/user_edit.html:28 +#, fuzzy +msgid "Send to eReader Email" +msgstr "Send til E-Reader E-postadresse" + +#: cps/templates/admin.html:17 cps/templates/layout.html:91 +#: cps/templates/user_table.html:143 +msgid "Admin" +msgstr "Admin" + +#: cps/templates/admin.html:18 cps/templates/login.html:13 +#: cps/templates/login.html:14 cps/templates/user_edit.html:23 +msgid "Password" +msgstr "Passord" + +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 +#: cps/templates/user_table.html:146 +msgid "Download" +msgstr "nedlasting" + +#: cps/templates/admin.html:23 +msgid "View Books" +msgstr "Se bøker" + +#: cps/templates/admin.html:24 cps/templates/user_table.html:131 +#: cps/templates/user_table.html:148 +msgid "Edit" +msgstr "Redigere" + +#: cps/templates/admin.html:25 cps/templates/book_edit.html:17 +#: cps/templates/book_table.html:100 cps/templates/modal_dialogs.html:63 +#: cps/templates/modal_dialogs.html:116 cps/templates/user_edit.html:67 +#: cps/templates/user_table.html:149 +msgid "Delete" +msgstr "Slett" + +#: cps/templates/admin.html:26 +msgid "Public Shelf" +msgstr "Offentlig hylle" + +#: cps/templates/admin.html:55 +msgid "Import LDAP Users" +msgstr "Importer LDAP-brukere" + +#: cps/templates/admin.html:62 +#, fuzzy +msgid "Email Server Settings" +msgstr "Innstillinger for e-postserver" + +#: cps/templates/admin.html:67 cps/templates/email_edit.html:31 +msgid "SMTP Hostname" +msgstr "SMTP vertsnavn" + +#: cps/templates/admin.html:71 cps/templates/email_edit.html:35 +msgid "SMTP Port" +msgstr "SMTP-port" + +#: cps/templates/admin.html:75 cps/templates/email_edit.html:39 +msgid "Encryption" +msgstr "Kryptering" + +#: cps/templates/admin.html:79 cps/templates/email_edit.html:47 +msgid "SMTP Login" +msgstr "SMTP-pålogging" + +#: cps/templates/admin.html:83 cps/templates/admin.html:94 +#: cps/templates/email_edit.html:55 +#, fuzzy +msgid "From Email" +msgstr "Fra e-post" + +#: cps/templates/admin.html:90 +#, fuzzy +msgid "Email Service" +msgstr "E-posttjeneste" + +#: cps/templates/admin.html:91 +msgid "Gmail via Oauth2" +msgstr "Gmail via Oauth2" + +#: cps/templates/admin.html:106 +msgid "Configuration" +msgstr "Konfigurasjon" + +#: cps/templates/admin.html:109 +msgid "Calibre Database Directory" +msgstr "Caliber Database Directory" + +#: cps/templates/admin.html:113 cps/templates/config_edit.html:68 +msgid "Log Level" +msgstr "Loggnivå" + +#: cps/templates/admin.html:117 +msgid "Port" +msgstr "Havn" + +#: cps/templates/admin.html:122 +msgid "External Port" +msgstr "Ekstern port" + +#: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 +msgid "Books per Page" +msgstr "Bøker per side" + +#: cps/templates/admin.html:133 +msgid "Uploads" +msgstr "Opplastinger" + +#: cps/templates/admin.html:137 +msgid "Anonymous Browsing" +msgstr "Anonym surfing" + +#: cps/templates/admin.html:141 +msgid "Public Registration" +msgstr "Offentlig registrering" + +#: cps/templates/admin.html:145 +msgid "Magic Link Remote Login" +msgstr "Magic Link ekstern pålogging" + +#: cps/templates/admin.html:149 +msgid "Reverse Proxy Login" +msgstr "Omvendt proxy-pålogging" + +#: cps/templates/admin.html:154 cps/templates/config_edit.html:173 +msgid "Reverse Proxy Header Name" +msgstr "Omvendt proxy-overskriftsnavn" + +#: cps/templates/admin.html:159 +msgid "Edit Calibre Database Configuration" +msgstr "Rediger Caliber-databasekonfigurasjon" + +#: cps/templates/admin.html:160 +msgid "Edit Basic Configuration" +msgstr "Rediger grunnleggende konfigurasjon" + +#: cps/templates/admin.html:161 +msgid "Edit UI Configuration" +msgstr "Rediger UI-konfigurasjon" + +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Planlagte oppgaver" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "" + +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +#, fuzzy +msgid "Maximum Duration" +msgstr "Maksimal oppgavevarighet" + +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +#, fuzzy +msgid "Generate Thumbnails" +msgstr "Generer miniatyrbilder av bokomslag" + +#: cps/templates/admin.html:182 +msgid "Generate series cover thumbnails" +msgstr "Generer serieomslagsminiatyrbilder" + +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Koble til Caliber-databasen på nytt" + +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +#, fuzzy +msgid "Refresh Thumbnail Cache" +msgstr "Oppdater thumbnail cover Cache" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Administrasjon" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Last ned feilsøkingspakken" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Vis logger" + +#: cps/templates/admin.html:211 +msgid "Restart" +msgstr "Omstart" + +#: cps/templates/admin.html:212 +msgid "Shutdown" +msgstr "Skru av" + +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Versjonsinformasjon" + +#: cps/templates/admin.html:225 +msgid "Version" +msgstr "Versjon" + +#: cps/templates/admin.html:226 +msgid "Details" +msgstr "Detaljer" + +#: cps/templates/admin.html:232 +#, fuzzy +msgid "Current Version" +msgstr "Gjeldende versjon" + +#: cps/templates/admin.html:239 +msgid "Check for Update" +msgstr "Se etter oppdatering" + +#: cps/templates/admin.html:240 +msgid "Perform Update" +msgstr "Utfør oppdatering" + +#: cps/templates/admin.html:253 +msgid "Are you sure you want to restart?" +msgstr "Er du sikker på at du vil starte på nytt?" + +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 +msgid "OK" +msgstr "OK" + +#: cps/templates/admin.html:259 cps/templates/admin.html:273 +#: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 +#: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 +#: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 +#: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 +#: cps/templates/user_edit.html:144 +msgid "Cancel" +msgstr "Avbryt" + +#: cps/templates/admin.html:271 +msgid "Are you sure you want to shutdown?" +msgstr "Er du sikker på at du vil slå av?" + +#: cps/templates/admin.html:283 +msgid "Updating, please do not reload this page" +msgstr "Oppdaterer, vennligst ikke last inn denne siden på nytt" + +#: cps/templates/author.html:15 +msgid "via" +msgstr "via" + +#: cps/templates/author.html:23 +msgid "In Library" +msgstr "I biblioteket" + +#: cps/templates/author.html:26 cps/templates/index.html:74 +#: cps/templates/search.html:31 cps/templates/shelf.html:20 +msgid "Sort according to book date, newest first" +msgstr "Sorter etter bokdato, nyeste først" + +#: cps/templates/author.html:27 cps/templates/index.html:75 +#: cps/templates/search.html:32 cps/templates/shelf.html:21 +msgid "Sort according to book date, oldest first" +msgstr "Sorter etter bokdato, eldste først" + +#: cps/templates/author.html:28 cps/templates/index.html:76 +#: cps/templates/search.html:33 cps/templates/shelf.html:22 +msgid "Sort title in alphabetical order" +msgstr "Sorter tittelen i alfabetisk rekkefølge" + +#: cps/templates/author.html:29 cps/templates/index.html:77 +#: cps/templates/search.html:34 cps/templates/shelf.html:23 +msgid "Sort title in reverse alphabetical order" +msgstr "Sorter tittelen i omvendt alfabetisk rekkefølge" + +#: cps/templates/author.html:30 cps/templates/index.html:80 +#: cps/templates/search.html:37 cps/templates/shelf.html:26 +msgid "Sort according to publishing date, newest first" +msgstr "Sorter etter publiseringsdato, nyeste først" + +#: cps/templates/author.html:31 cps/templates/index.html:81 +#: cps/templates/search.html:38 cps/templates/shelf.html:27 +msgid "Sort according to publishing date, oldest first" +msgstr "Sorter etter publiseringsdato, eldste først" + +#: cps/templates/author.html:56 cps/templates/author.html:115 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 +msgid "reduce" +msgstr "redusere" + +#: cps/templates/author.html:99 +msgid "More by" +msgstr "Mer av" + +#: cps/templates/book_edit.html:11 +msgid "Delete Book" +msgstr "Slett bok" + +#: cps/templates/book_edit.html:14 +msgid "Delete formats:" +msgstr "Slett formater:" + +#: cps/templates/book_edit.html:25 +msgid "Convert book format:" +msgstr "Konverter bokformat:" + +#: cps/templates/book_edit.html:30 +msgid "Convert from:" +msgstr "Konverter fra:" + +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 +msgid "select an option" +msgstr "Velg et alternativ" + +#: cps/templates/book_edit.html:37 +msgid "Convert to:" +msgstr "Konvertere til:" + +#: cps/templates/book_edit.html:46 +msgid "Convert book" +msgstr "Konverter bok" + +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 +msgid "Book Title" +msgstr "Boktittel" + +#: cps/templates/book_edit.html:63 cps/templates/book_edit.html:271 +#: cps/templates/book_edit.html:289 cps/templates/search_form.html:12 +msgid "Author" +msgstr "Forfatter" + +#: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 +msgid "Description" +msgstr "Beskrivelse" + +#: cps/templates/book_edit.html:73 +msgid "Identifiers" +msgstr "Identifikatorer" + +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +msgid "Identifier Type" +msgstr "Identifikatortype" + +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +msgid "Identifier Value" +msgstr "Identifikatorverdi" + +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 +#: cps/templates/user_table.html:24 +msgid "Remove" +msgstr "Ta bort" + +#: cps/templates/book_edit.html:83 +msgid "Add Identifier" +msgstr "Legg til identifikator" + +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 +msgid "Tags" +msgstr "Tagger" + +#: cps/templates/book_edit.html:95 +msgid "Series ID" +msgstr "Serie-ID" + +#: cps/templates/book_edit.html:99 +msgid "Rating" +msgstr "Vurdering" + +#: cps/templates/book_edit.html:104 +msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" +msgstr "Hent omslag fra URL (JPEG - Bilde vil bli lastet ned og lagret i databasen)" + +#: cps/templates/book_edit.html:108 +msgid "Upload Cover from Local Disk" +msgstr "Last opp cover fra lokal disk" + +#: cps/templates/book_edit.html:113 +msgid "Published Date" +msgstr "Publiseringsdato" + +#: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 +msgid "Publisher" +msgstr "Forlegger" + +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 +msgid "Language" +msgstr "Språk" + +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 +msgid "Yes" +msgstr "Ja" + +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 +msgid "No" +msgstr "Nei" + +#: cps/templates/book_edit.html:201 +msgid "Upload Format" +msgstr "Last opp format" + +#: cps/templates/book_edit.html:209 +msgid "View Book on Save" +msgstr "Se bok på Lagre" + +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 +msgid "Fetch Metadata" +msgstr "Hent metadata" + +#: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 +#: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 +#: cps/templates/user_edit.html:142 +msgid "Save" +msgstr "Lagre" + +#: cps/templates/book_edit.html:233 +msgid "Keyword" +msgstr "Nøkkelord" + +#: cps/templates/book_edit.html:234 +msgid "Search keyword" +msgstr "Søk nøkkelord" + +#: cps/templates/book_edit.html:240 +msgid "Click the cover to load metadata to the form" +msgstr "Klikk på omslaget for å laste metadata til skjemaet" + +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 +msgid "Loading..." +msgstr "Laster inn..." + +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 +#: cps/templates/user_edit.html:163 +msgid "Close" +msgstr "Lukk" + +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 +msgid "Source" +msgstr "Kilde" + +#: cps/templates/book_edit.html:287 +msgid "Search error!" +msgstr "Søkefeil!" + +#: cps/templates/book_edit.html:288 +msgid "No Result(s) found! Please try another keyword." +msgstr "Ingen resultater! Prøv et annet søkeord." + +#: cps/templates/book_table.html:12 cps/templates/book_table.html:69 +#: cps/templates/user_table.html:14 cps/templates/user_table.html:77 +#: cps/templates/user_table.html:100 +msgid "This Field is Required" +msgstr "Dette feltet er obligatorisk" + +#: cps/templates/book_table.html:37 +msgid "Merge selected books" +msgstr "Slå sammen valgte bøker" + +#: cps/templates/book_table.html:38 cps/templates/user_table.html:124 +msgid "Remove Selections" +msgstr "Fjern valg" + +#: cps/templates/book_table.html:41 +msgid "Exchange author and title" +msgstr "Bytt forfatter og tittel" + +#: cps/templates/book_table.html:47 +msgid "Update Title Sort automatically" +msgstr "Oppdater tittelsortering automatisk" + +#: cps/templates/book_table.html:51 +msgid "Update Author Sort automatically" +msgstr "Oppdater forfattersortering automatisk" + +#: cps/templates/book_table.html:63 cps/templates/book_table.html:69 +msgid "Enter Title" +msgstr "Skriv inn tittel" + +#: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 +#: cps/templates/shelf_edit.html:8 +msgid "Title" +msgstr "Tittel" + +#: cps/templates/book_table.html:64 +msgid "Enter Title Sort" +msgstr "Skriv inn tittelsortering" + +#: cps/templates/book_table.html:64 +msgid "Title Sort" +msgstr "Tittelsortering" + +#: cps/templates/book_table.html:65 +msgid "Enter Author Sort" +msgstr "Skriv inn forfattersortering" + +#: cps/templates/book_table.html:65 +msgid "Author Sort" +msgstr "Forfatter Sort" + +#: cps/templates/book_table.html:66 +msgid "Enter Authors" +msgstr "Skriv inn forfattere" + +#: cps/templates/book_table.html:67 +msgid "Enter Categories" +msgstr "Skriv inn kategorier" + +#: cps/templates/book_table.html:68 +msgid "Enter Series" +msgstr "Gå inn i serien" + +#: cps/templates/book_table.html:69 +msgid "Series Index" +msgstr "Serieindeks" + +#: cps/templates/book_table.html:70 +msgid "Enter Languages" +msgstr "Skriv inn Språk" + +#: cps/templates/book_table.html:71 +msgid "Publishing Date" +msgstr "Publiseringsdato" + +#: cps/templates/book_table.html:72 +msgid "Enter Publishers" +msgstr "Skriv inn Publishers" + +#: cps/templates/book_table.html:73 +msgid "Enter comments" +msgstr "Skriv inn kommentarer" + +#: cps/templates/book_table.html:73 +msgid "Comments" +msgstr "Kommentarer" + +#: cps/templates/book_table.html:75 +msgid "Archive Status" +msgstr "Arkivstatus" + +#: cps/templates/book_table.html:77 cps/templates/search_form.html:42 +msgid "Read Status" +msgstr "Les status" + +#: cps/templates/book_table.html:80 cps/templates/book_table.html:82 +#: cps/templates/book_table.html:84 cps/templates/book_table.html:86 +#: cps/templates/book_table.html:90 cps/templates/book_table.html:92 +#: cps/templates/book_table.html:96 +msgid "Enter " +msgstr "Tast inn " + +#: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 +msgid "Are you really sure?" +msgstr "Er du virkelig sikker?" + +#: cps/templates/book_table.html:117 +msgid "Books with Title will be merged from:" +msgstr "Bøker med tittel vil bli slått sammen fra:" + +#: cps/templates/book_table.html:121 +msgid "Into Book with Title:" +msgstr "Til bok med tittel:" + +#: cps/templates/book_table.html:126 +msgid "Merge" +msgstr "Slå sammen" + +#: cps/templates/config_db.html:12 +msgid "Location of Calibre Database" +msgstr "Plassering av Caliber-databasen" + +#: cps/templates/config_db.html:22 +msgid "Use Google Drive?" +msgstr "Bruker du Google Disk?" + +#: cps/templates/config_db.html:27 +msgid "Authenticate Google Drive" +msgstr "Autentiser Google Disk" + +#: cps/templates/config_db.html:32 +msgid "Google Drive Calibre folder" +msgstr "Google Drive Caliber-mappe" + +#: cps/templates/config_db.html:40 +msgid "Metadata Watch Channel ID" +msgstr "Metadata Se kanal-ID" + +#: cps/templates/config_db.html:43 +msgid "Revoke" +msgstr "Oppheve" + +#: cps/templates/config_db.html:68 +msgid "New db location is invalid, please enter valid path" +msgstr "Ny db-plassering er ugyldig, vennligst skriv inn gyldig bane" + +#: cps/templates/config_edit.html:18 +msgid "Server Configuration" +msgstr "Serverkonfigurasjon" + +#: cps/templates/config_edit.html:25 +msgid "Server Port" +msgstr "Serverport" + +#: cps/templates/config_edit.html:28 +msgid "SSL certfile location (leave it empty for non-SSL Servers)" +msgstr "SSL-sertfilplassering (la den stå tom for ikke-SSL-servere)" + +#: cps/templates/config_edit.html:35 +msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" +msgstr "SSL-nøkkelfilplassering (la den stå tom for ikke-SSL-servere)" + +#: cps/templates/config_edit.html:43 +msgid "Update Channel" +msgstr "Oppdater kanalen" + +#: cps/templates/config_edit.html:45 +msgid "Stable" +msgstr "Stabil" + +#: cps/templates/config_edit.html:46 +msgid "Nightly" +msgstr "Nattlig" + +#: cps/templates/config_edit.html:50 +msgid "Trusted Hosts (Comma Separated)" +msgstr "Klarerte verter (kommaseparert)" + +#: cps/templates/config_edit.html:61 +msgid "Logfile Configuration" +msgstr "Loggfilkonfigurasjon" + +#: cps/templates/config_edit.html:77 +msgid "Location and name of logfile (calibre-web.log for no entry)" +msgstr "Plassering og navn på loggfil (calibre-web.log for ingen oppføring)" + +#: cps/templates/config_edit.html:82 +msgid "Enable Access Log" +msgstr "Aktiver tilgangslogg" + +#: cps/templates/config_edit.html:85 +msgid "Location and name of access logfile (access.log for no entry)" +msgstr "Plassering og navn på tilgangsloggfil (access.log for ingen oppføring)" + +#: cps/templates/config_edit.html:96 +msgid "Feature Configuration" +msgstr "Funksjonskonfigurasjon" + +#: cps/templates/config_edit.html:104 +msgid "Convert non-English characters in title and author while saving to disk" +msgstr "Konverter ikke-engelske tegn i tittel og forfatter mens du lagrer på disk" + +#: cps/templates/config_edit.html:108 +msgid "Enable Uploads" +msgstr "Aktiver opplastinger" + +#: cps/templates/config_edit.html:108 +msgid "(Please ensure that users also have upload permissions)" +msgstr "(Vennligst sørg for at brukerne også har opplastingsrettigheter)" + +#: cps/templates/config_edit.html:112 +msgid "Allowed Upload Fileformats" +msgstr "Tillatte opplastingsfilformater" + +#: cps/templates/config_edit.html:118 +msgid "Enable Anonymous Browsing" +msgstr "Aktiver anonym surfing" + +#: cps/templates/config_edit.html:122 +msgid "Enable Public Registration" +msgstr "Aktiver offentlig registrering" + +#: cps/templates/config_edit.html:127 +#, fuzzy +msgid "Use Email as Username" +msgstr "Bruk e-post som brukernavn" + +#: cps/templates/config_edit.html:132 +msgid "Enable Magic Link Remote Login" +msgstr "Aktiver Magic Link Remote Login" + +#: cps/templates/config_edit.html:137 +msgid "Enable Kobo sync" +msgstr "Aktiver Kobo-synkronisering" + +#: cps/templates/config_edit.html:142 +msgid "Proxy unknown requests to Kobo Store" +msgstr "Ukjente proxy-forespørsler til Kobo Store" + +#: cps/templates/config_edit.html:145 +msgid "Server External Port (for port forwarded API calls)" +msgstr "Server ekstern port (for portviderekoblede API-anrop)" + +#: cps/templates/config_edit.html:153 +msgid "Use Goodreads" +msgstr "Bruk Goodreads" + +#: cps/templates/config_edit.html:154 +msgid "Create an API Key" +msgstr "Opprett en API-nøkkel" + +#: cps/templates/config_edit.html:158 +msgid "Goodreads API Key" +msgstr "Goodreads API-nøkkel" + +#: cps/templates/config_edit.html:162 +msgid "Goodreads API Secret" +msgstr "Goodreads API Secret" + +#: cps/templates/config_edit.html:169 +msgid "Allow Reverse Proxy Authentication" +msgstr "Tillat omvendt proxy-autentisering" + +#: cps/templates/config_edit.html:180 +msgid "Login type" +msgstr "Påloggingstype" + +#: cps/templates/config_edit.html:182 +msgid "Use Standard Authentication" +msgstr "Bruk standardautentisering" + +#: cps/templates/config_edit.html:184 +msgid "Use LDAP Authentication" +msgstr "Bruk LDAP-autentisering" + +#: cps/templates/config_edit.html:187 +msgid "Use OAuth" +msgstr "Bruk OAuth" + +#: cps/templates/config_edit.html:194 +msgid "LDAP Server Host Name or IP Address" +msgstr "LDAP-serverens vertsnavn eller IP-adresse" + +#: cps/templates/config_edit.html:198 +msgid "LDAP Server Port" +msgstr "LDAP-serverport" + +#: cps/templates/config_edit.html:202 +msgid "LDAP Encryption" +msgstr "LDAP-kryptering" + +#: cps/templates/config_edit.html:205 +msgid "TLS" +msgstr "TLS" + +#: cps/templates/config_edit.html:206 +msgid "SSL" +msgstr "SSL" + +#: cps/templates/config_edit.html:210 +msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" +msgstr "LDAP CACertificate Path (Kun nødvendig for klientsertifikatautentisering)" + +#: cps/templates/config_edit.html:217 +msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" +msgstr "LDAP-sertifikatbane (kun nødvendig for klientsertifikatautentisering)" + +#: cps/templates/config_edit.html:224 +msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" +msgstr "LDAP-nøkkelfilbane (kun nødvendig for klientsertifikatautentisering)" + +#: cps/templates/config_edit.html:233 +msgid "LDAP Authentication" +msgstr "LDAP-autentisering" + +#: cps/templates/config_edit.html:235 +msgid "Anonymous" +msgstr "Anonym" + +#: cps/templates/config_edit.html:236 +msgid "Unauthenticated" +msgstr "Uautentisert" + +#: cps/templates/config_edit.html:237 +msgid "Simple" +msgstr "Enkel" + +#: cps/templates/config_edit.html:242 +msgid "LDAP Administrator Username" +msgstr "LDAP-administratorbrukernavn" + +#: cps/templates/config_edit.html:248 +msgid "LDAP Administrator Password" +msgstr "LDAP-administratorpassord" + +#: cps/templates/config_edit.html:253 +msgid "LDAP Distinguished Name (DN)" +msgstr "LDAP Distinguished Name (DN)" + +#: cps/templates/config_edit.html:257 +msgid "LDAP User Object Filter" +msgstr "LDAP-brukerobjektfilter" + +#: cps/templates/config_edit.html:262 +msgid "LDAP Server is OpenLDAP?" +msgstr "LDAP Server er OpenLDAP?" + +#: cps/templates/config_edit.html:264 +msgid "Following Settings are Needed For User Import" +msgstr "Følgende innstillinger er nødvendig for brukerimport" + +#: cps/templates/config_edit.html:266 +msgid "LDAP Group Object Filter" +msgstr "LDAP gruppeobjektfilter" + +#: cps/templates/config_edit.html:270 +msgid "LDAP Group Name" +msgstr "LDAP-gruppenavn" + +#: cps/templates/config_edit.html:274 +msgid "LDAP Group Members Field" +msgstr "Felt for LDAP-gruppemedlemmer" + +#: cps/templates/config_edit.html:278 +msgid "LDAP Member User Filter Detection" +msgstr "LDAP-medlemsbrukerfilterdeteksjon" + +#: cps/templates/config_edit.html:280 +msgid "Autodetect" +msgstr "" + +#: cps/templates/config_edit.html:281 +msgid "Custom Filter" +msgstr "" + +#: cps/templates/config_edit.html:286 +msgid "LDAP Member User Filter" +msgstr "" + +#: cps/templates/config_edit.html:297 +#, python-format +msgid "Obtain %(provider)s OAuth Credential" +msgstr "" + +#: cps/templates/config_edit.html:300 +#, python-format +msgid "%(provider)s OAuth Client Id" +msgstr "" + +#: cps/templates/config_edit.html:304 +#, python-format +msgid "%(provider)s OAuth Client Secret" +msgstr "" + +#: cps/templates/config_edit.html:320 +#, fuzzy +msgid "External binaries" +msgstr "Ekstern port" + +#: cps/templates/config_edit.html:326 +msgid "Path to Calibre E-Book Converter" +msgstr "" + +#: cps/templates/config_edit.html:334 +#, fuzzy +msgid "Calibre E-Book Converter Settings" +msgstr "Caliber ebook-convert %(tool)s ble ikke funnet" + +#: cps/templates/config_edit.html:337 +msgid "Path to Kepubify E-Book Converter" +msgstr "" + +#: cps/templates/config_edit.html:345 +msgid "Location of Unrar binary" +msgstr "" + +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Vis forfattervalg" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +msgid "User Password policy" +msgstr "" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + +#: cps/templates/config_view_edit.html:17 +#, fuzzy +msgid "View Configuration" +msgstr "Konfigurasjon" + +#: cps/templates/config_view_edit.html:32 +msgid "No. of Random Books to Display" +msgstr "" + +#: cps/templates/config_view_edit.html:36 +msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" +msgstr "" + +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 +msgid "Theme" +msgstr "" + +#: cps/templates/config_view_edit.html:42 +msgid "Standard Theme" +msgstr "" + +#: cps/templates/config_view_edit.html:43 +msgid "caliBlur! Dark Theme" +msgstr "" + +#: cps/templates/config_view_edit.html:47 +msgid "Regular Expression for Ignoring Columns" +msgstr "" + +#: cps/templates/config_view_edit.html:51 +msgid "Link Read/Unread Status to Calibre Column" +msgstr "" + +#: cps/templates/config_view_edit.html:60 +msgid "View Restrictions based on Calibre column" +msgstr "" + +#: cps/templates/config_view_edit.html:69 +msgid "Regular Expression for Title Sorting" +msgstr "" + +#: cps/templates/config_view_edit.html:80 +msgid "Default Settings for New Users" +msgstr "" + +#: cps/templates/config_view_edit.html:88 cps/templates/user_edit.html:96 +#, fuzzy +msgid "Admin User" +msgstr "Legg til ny bruker" + +#: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 +#, fuzzy +msgid "Allow Downloads" +msgstr "Nedlastinger" + +#: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 +msgid "Allow eBook Viewer" +msgstr "" + +#: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 +#, fuzzy +msgid "Allow Uploads" +msgstr "Aktiver opplastinger" + +#: cps/templates/config_view_edit.html:106 cps/templates/user_edit.html:115 +msgid "Allow Edit" +msgstr "" + +#: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 +#, fuzzy +msgid "Allow Delete Books" +msgstr "Vis nyere bøker" + +#: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 +msgid "Allow Changing Password" +msgstr "" + +#: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 +msgid "Allow Editing Public Shelves" +msgstr "" + +#: cps/templates/config_view_edit.html:123 +msgid "Default Language" +msgstr "" + +#: cps/templates/config_view_edit.html:131 +msgid "Default Visible Language of Books" +msgstr "" + +#: cps/templates/config_view_edit.html:147 +msgid "Default Visibilities for New Users" +msgstr "" + +#: cps/templates/config_view_edit.html:163 cps/templates/user_edit.html:84 +#: cps/templates/user_table.html:154 +msgid "Show Random Books in Detail View" +msgstr "" + +#: cps/templates/config_view_edit.html:166 cps/templates/user_edit.html:87 +msgid "Add Allowed/Denied Tags" +msgstr "" + +#: cps/templates/config_view_edit.html:167 +msgid "Add Allowed/Denied custom column values" +msgstr "" + +#: cps/templates/detail.html:77 cps/templates/detail.html:91 +msgid "Read in Browser" +msgstr "" + +#: cps/templates/detail.html:100 cps/templates/detail.html:120 +msgid "Listen in Browser" +msgstr "" + +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 +#, fuzzy, python-format +msgid "Book %(index)s of %(range)s" +msgstr "Sletting av bok %(index)s mislyktes: %(range)s" + +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 +#, fuzzy +msgid "Published" +msgstr "Forlegger" + +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 +msgid "Mark As Unread" +msgstr "" + +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 +msgid "Mark As Read" +msgstr "" + +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 +#, fuzzy +msgid "Read" +msgstr "redusere" + +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 +msgid "Restore from archive" +msgstr "" + +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 +msgid "Add to archive" +msgstr "" + +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 +#, fuzzy +msgid "Archived" +msgstr "Arkiverte bøker" + +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 +#, fuzzy +msgid "Description:" +msgstr "Beskrivelse" + +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 +#, fuzzy +msgid "Add to shelf" +msgstr "Rediger en hylle" + +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 +#: cps/templates/search.html:22 +msgid "(Public)" +msgstr "" + +#: cps/templates/detail.html:339 +#, fuzzy +msgid "Edit Metadata" +msgstr "redigere metadata" + +#: cps/templates/email_edit.html:13 +msgid "Email Account Type" +msgstr "" + +#: cps/templates/email_edit.html:15 +msgid "Standard Email Account" +msgstr "" + +#: cps/templates/email_edit.html:16 +msgid "Gmail Account" +msgstr "" + +#: cps/templates/email_edit.html:22 +msgid "Setup Gmail Account" +msgstr "" + +#: cps/templates/email_edit.html:24 +msgid "Revoke Gmail Access" +msgstr "" + +#: cps/templates/email_edit.html:42 +#, fuzzy +msgid "STARTTLS" +msgstr "Omstart" + +#: cps/templates/email_edit.html:43 +msgid "SSL/TLS" +msgstr "" + +#: cps/templates/email_edit.html:51 +#, fuzzy +msgid "SMTP Password" +msgstr "Passord" + +#: cps/templates/email_edit.html:58 +msgid "Attachment Size Limit" +msgstr "" + +#: cps/templates/email_edit.html:66 +msgid "Save and Send Test Email" +msgstr "" + +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 +#: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 +msgid "Back" +msgstr "" + +#: cps/templates/email_edit.html:74 +msgid "Allowed Domains (Whitelist)" +msgstr "" + +#: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 +msgid "Add Domain" +msgstr "" + +#: cps/templates/email_edit.html:81 cps/templates/email_edit.html:108 +#: cps/templates/user_table.html:27 +msgid "Add" +msgstr "" + +#: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 +#, fuzzy +msgid "Enter domainname" +msgstr "Skriv inn kommentarer" + +#: cps/templates/email_edit.html:92 +msgid "Denied Domains (Blacklist)" +msgstr "" + +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 +msgid "Next" +msgstr "" + +#: cps/templates/generate_kobo_auth_url.html:6 +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "" + +#: cps/templates/generate_kobo_auth_url.html:11 +msgid "Kobo Token:" +msgstr "" + +#: cps/templates/grid.html:21 +msgid "List" +msgstr "" + +#: cps/templates/http_error.html:34 +#, fuzzy +msgid "Calibre-Web Instance is unconfigured, please contact your administrator" +msgstr "E-postserveren er ikke konfigurert, kontakt administratoren din!" + +#: cps/templates/http_error.html:44 +msgid "Create Issue" +msgstr "" + +#: cps/templates/http_error.html:51 +msgid "Return to Home" +msgstr "" + +#: cps/templates/http_error.html:53 +msgid "Logout User" +msgstr "" + +#: cps/templates/index.html:71 +msgid "Sort ascending according to download count" +msgstr "" + +#: cps/templates/index.html:72 +msgid "Sort descending according to download count" +msgstr "" + +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 +#, fuzzy +msgid "Sort authors in alphabetical order" +msgstr "Sorter tittelen i alfabetisk rekkefølge" + +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 +#, fuzzy +msgid "Sort authors in reverse alphabetical order" +msgstr "Sorter tittelen i omvendt alfabetisk rekkefølge" + +#: cps/templates/index.html:83 +msgid "Sort ascending according to series index" +msgstr "" + +#: cps/templates/index.html:84 +msgid "Sort descending according to series index" +msgstr "" + +#: cps/templates/index.xml:7 +#, fuzzy +msgid "Start" +msgstr "Omstart" + +#: cps/templates/index.xml:19 +msgid "Alphabetical Books" +msgstr "" + +#: cps/templates/index.xml:23 +msgid "Books sorted alphabetically" +msgstr "" + +#: cps/templates/index.xml:30 +msgid "Popular publications from this catalog based on Downloads." +msgstr "" + +#: cps/templates/index.xml:37 +msgid "Popular publications from this catalog based on Rating." +msgstr "" + +#: cps/templates/index.xml:40 +#, fuzzy +msgid "Recently added Books" +msgstr "Vis nyere bøker" + +#: cps/templates/index.xml:44 +#, fuzzy +msgid "The latest Books" +msgstr "Slå sammen valgte bøker" + +#: cps/templates/index.xml:47 +#, fuzzy +msgid "Random Books" +msgstr "Vis tilfeldige bøker" + +#: cps/templates/index.xml:74 +msgid "Books ordered by Author" +msgstr "" + +#: cps/templates/index.xml:81 +msgid "Books ordered by publisher" +msgstr "" + +#: cps/templates/index.xml:88 +msgid "Books ordered by category" +msgstr "" + +#: cps/templates/index.xml:95 +msgid "Books ordered by series" +msgstr "" + +#: cps/templates/index.xml:102 +msgid "Books ordered by Languages" +msgstr "" + +#: cps/templates/index.xml:109 +msgid "Books ordered by Rating" +msgstr "" + +#: cps/templates/index.xml:117 +msgid "Books ordered by file formats" +msgstr "" + +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 +msgid "Shelves" +msgstr "" + +#: cps/templates/index.xml:124 +msgid "Books organized in shelves" +msgstr "" + +#: cps/templates/layout.html:26 cps/templates/login.html:30 +msgid "Home" +msgstr "" + +#: cps/templates/layout.html:32 +#, fuzzy +msgid "Toggle Navigation" +msgstr "Loggfilkonfigurasjon" + +#: cps/templates/layout.html:47 +msgid "Search Library" +msgstr "" + +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +#, fuzzy +msgid "Uploading..." +msgstr "Laster inn..." + +#: cps/templates/layout.html:78 +#, fuzzy +msgid "Error" +msgstr "Serverport" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "" + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +#, fuzzy +msgid "Settings" +msgstr "Vurderinger" + +#: cps/templates/layout.html:135 +#, fuzzy +msgid "Please do not refresh the page" +msgstr "Oppdaterer, vennligst ikke last inn denne siden på nytt" + +#: cps/templates/layout.html:145 +msgid "Browse" +msgstr "" + +#: cps/templates/layout.html:158 cps/templates/stats.html:3 +msgid "About" +msgstr "" + +#: cps/templates/layout.html:172 +msgid "Previous" +msgstr "" + +#: cps/templates/layout.html:199 +#, fuzzy +msgid "Book Details" +msgstr "Detaljer" + +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "" + +#: cps/templates/login.html:18 +msgid "Remember Me" +msgstr "" + +#: cps/templates/login.html:23 +msgid "Forgot Password?" +msgstr "" + +#: cps/templates/login.html:34 +msgid "Log in with Magic Link" +msgstr "" + +#: cps/templates/logviewer.html:6 +msgid "Show Calibre-Web Log: " +msgstr "" + +#: cps/templates/logviewer.html:8 +msgid "Calibre-Web Log: " +msgstr "" + +#: cps/templates/logviewer.html:8 +msgid "Stream output, can't be displayed" +msgstr "" + +#: cps/templates/logviewer.html:12 +msgid "Show Access Log: " +msgstr "" + +#: cps/templates/logviewer.html:18 +msgid "Download Calibre-Web Log" +msgstr "" + +#: cps/templates/logviewer.html:21 +#, fuzzy +msgid "Download Access Log" +msgstr "Aktiver tilgangslogg" + +#: cps/templates/modal_dialogs.html:6 +msgid "Select Allowed/Denied Tags" +msgstr "" + +#: cps/templates/modal_dialogs.html:7 +msgid "Select Allowed/Denied Custom Column Values" +msgstr "" + +#: cps/templates/modal_dialogs.html:8 +msgid "Select Allowed/Denied Tags of User" +msgstr "" + +#: cps/templates/modal_dialogs.html:9 +msgid "Select Allowed/Denied Custom Column Values of User" +msgstr "" + +#: cps/templates/modal_dialogs.html:15 +#, fuzzy +msgid "Enter Tag" +msgstr "Tast inn " + +#: cps/templates/modal_dialogs.html:24 +msgid "Add View Restriction" +msgstr "" + +#: cps/templates/modal_dialogs.html:50 +msgid "This book format will be permanently erased from database" +msgstr "" + +#: cps/templates/modal_dialogs.html:51 +msgid "This book will be permanently erased from database" +msgstr "" + +#: cps/templates/modal_dialogs.html:52 +msgid "and hard disk" +msgstr "" + +#: cps/templates/modal_dialogs.html:56 +msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." +msgstr "" + +#: cps/templates/modal_dialogs.html:57 +msgid "Books must first be archived and the device synced before a book can safely be deleted." +msgstr "" + +#: cps/templates/modal_dialogs.html:76 +msgid "Choose File Location" +msgstr "" + +#: cps/templates/modal_dialogs.html:82 +msgid "type" +msgstr "" + +#: cps/templates/modal_dialogs.html:83 +#, fuzzy +msgid "name" +msgstr "Brukernavn" + +#: cps/templates/modal_dialogs.html:84 +msgid "size" +msgstr "" + +#: cps/templates/modal_dialogs.html:90 +msgid "Parent Directory" +msgstr "" + +#: cps/templates/modal_dialogs.html:98 +#, fuzzy +msgid "Select" +msgstr "Slett" + +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 +msgid "Ok" +msgstr "" + +#: cps/templates/osd.xml:5 +msgid "Calibre-Web eBook Catalog" +msgstr "" + +#: cps/templates/read.html:6 +msgid "epub Reader" +msgstr "" + +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +#, fuzzy +msgid "Light" +msgstr "Nattlig" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "" + +#: cps/templates/read.html:84 +msgid "Black" +msgstr "" + +#: cps/templates/read.html:88 +msgid "Reflow text when sidebars are open." +msgstr "" + +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 +msgid "Comic Reader" +msgstr "" + +#: cps/templates/readcbr.html:75 +msgid "Keyboard Shortcuts" +msgstr "" + +#: cps/templates/readcbr.html:78 +msgid "Previous Page" +msgstr "" + +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 +#, fuzzy +msgid "Next Page" +msgstr "Admin side" + +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 +msgid "Scale to Best" +msgstr "" + +#: cps/templates/readcbr.html:83 +msgid "Scale to Width" +msgstr "" + +#: cps/templates/readcbr.html:84 +msgid "Scale to Height" +msgstr "" + +#: cps/templates/readcbr.html:85 +msgid "Scale to Native" +msgstr "" + +#: cps/templates/readcbr.html:86 +msgid "Rotate Right" +msgstr "" + +#: cps/templates/readcbr.html:87 +msgid "Rotate Left" +msgstr "" + +#: cps/templates/readcbr.html:88 +msgid "Flip Image" +msgstr "" + +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Admin side" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 +msgid "Scale" +msgstr "" + +#: cps/templates/readcbr.html:122 +msgid "Best" +msgstr "" + +#: cps/templates/readcbr.html:123 +msgid "Width" +msgstr "" + +#: cps/templates/readcbr.html:124 +#, fuzzy +msgid "Height" +msgstr "Nattlig" + +#: cps/templates/readcbr.html:125 +#, fuzzy +msgid "Native" +msgstr "Lagre" + +#: cps/templates/readcbr.html:130 +#, fuzzy +msgid "Rotate" +msgstr "Startet" + +#: cps/templates/readcbr.html:141 +msgid "Flip" +msgstr "" + +#: cps/templates/readcbr.html:144 +msgid "Horizontal" +msgstr "" + +#: cps/templates/readcbr.html:145 +msgid "Vertical" +msgstr "" + +#: cps/templates/readcbr.html:150 +#, fuzzy +msgid "Direction" +msgstr "Administrasjon" + +#: cps/templates/readcbr.html:153 +msgid "Left to Right" +msgstr "" + +#: cps/templates/readcbr.html:154 +msgid "Right to Left" +msgstr "" + +#: cps/templates/readcbr.html:162 +msgid "Reset to Top" +msgstr "" + +#: cps/templates/readcbr.html:163 +msgid "Remember Position" +msgstr "" + +#: cps/templates/readcbr.html:168 +msgid "Scrollbar" +msgstr "" + +#: cps/templates/readcbr.html:171 +msgid "Show" +msgstr "" + +#: cps/templates/readcbr.html:172 +msgid "Hide" +msgstr "" + +#: cps/templates/readdjvu.html:5 +msgid "DJVU Reader" +msgstr "" + +#: cps/templates/readpdf.html:32 +msgid "PDF Reader" +msgstr "" + +#: cps/templates/readtxt.html:6 +msgid "txt Reader" +msgstr "" + +#: cps/templates/register.html:4 +msgid "Register New Account" +msgstr "" + +#: cps/templates/register.html:10 +#, fuzzy +msgid "Choose a username" +msgstr "Bruk e-post som brukernavn" + +#: cps/templates/register.html:15 +msgid "Your Email" +msgstr "" + +#: cps/templates/remote_login.html:5 +msgid "Magic Link - Authorise New Device" +msgstr "" + +#: cps/templates/remote_login.html:7 +msgid "On another device, login and visit:" +msgstr "" + +#: cps/templates/remote_login.html:11 +msgid "Once verified, you will automatically be logged in on this device." +msgstr "" + +#: cps/templates/remote_login.html:14 +msgid "This verification link will expire in 10 minutes." +msgstr "" + +#: cps/templates/schedule_edit.html:33 +#, fuzzy +msgid "Generate Series Cover Thumbnails" +msgstr "Generer serieomslagsminiatyrbilder" + +#: cps/templates/search.html:6 +#, fuzzy +msgid "No Results Found" +msgstr "Merket ble ikke funnet" + +#: cps/templates/search.html:7 +#, fuzzy +msgid "Search Term:" +msgstr "Søkefeil!" + +#: cps/templates/search.html:9 +msgid "Results for:" +msgstr "" + +#: cps/templates/search_form.html:21 +#, fuzzy +msgid "Published Date From" +msgstr "Publisert etter " + +#: cps/templates/search_form.html:31 +#, fuzzy +msgid "Published Date To" +msgstr "Publisert etter " + +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 +msgid "Exclude Tags" +msgstr "" + +#: cps/templates/search_form.html:78 +msgid "Exclude Series" +msgstr "" + +#: cps/templates/search_form.html:96 +msgid "Exclude Shelves" +msgstr "" + +#: cps/templates/search_form.html:116 +#, fuzzy +msgid "Exclude Languages" +msgstr "Skriv inn Språk" + +#: cps/templates/search_form.html:127 +msgid "Extensions" +msgstr "" + +#: cps/templates/search_form.html:135 +msgid "Exclude Extensions" +msgstr "" + +#: cps/templates/search_form.html:145 +#, fuzzy +msgid "Rating Above" +msgstr "Vurdering: Ingen" + +#: cps/templates/search_form.html:149 +msgid "Rating Below" +msgstr "" + +#: cps/templates/search_form.html:181 +msgid "From:" +msgstr "" + +#: cps/templates/search_form.html:191 +msgid "To:" +msgstr "" + +#: cps/templates/shelf.html:13 +msgid "Delete this Shelf" +msgstr "" + +#: cps/templates/shelf.html:14 +msgid "Edit Shelf Properties" +msgstr "" + +#: cps/templates/shelf.html:17 +msgid "Arrange books manually" +msgstr "" + +#: cps/templates/shelf.html:18 +msgid "Disable Change order" +msgstr "" + +#: cps/templates/shelf.html:18 +msgid "Enable Change order" +msgstr "" + +#: cps/templates/shelf_edit.html:14 +msgid "Share with Everyone" +msgstr "" + +#: cps/templates/shelf_edit.html:21 +msgid "Sync this shelf with Kobo device" +msgstr "" + +#: cps/templates/shelf_order.html:5 +msgid "Drag to Rearrange Order" +msgstr "" + +#: cps/templates/shelf_order.html:33 +msgid "Hidden Book" +msgstr "" + +#: cps/templates/stats.html:7 +#, fuzzy +msgid "Library Statistics" +msgstr "Statistikk" + +#: cps/templates/stats.html:12 +msgid "Books in this Library" +msgstr "" + +#: cps/templates/stats.html:16 +msgid "Authors in this Library" +msgstr "" + +#: cps/templates/stats.html:20 +msgid "Categories in this Library" +msgstr "" + +#: cps/templates/stats.html:24 +msgid "Series in this Library" +msgstr "" + +#: cps/templates/stats.html:29 +#, fuzzy +msgid "System Statistics" +msgstr "Statistikk" + +#: cps/templates/stats.html:33 +msgid "Program" +msgstr "" + +#: cps/templates/stats.html:34 +#, fuzzy +msgid "Installed Version" +msgstr "ikke installert" + +#: cps/templates/tasks.html:12 +#, fuzzy +msgid "User" +msgstr "Brukere" + +#: cps/templates/tasks.html:14 +#, fuzzy +msgid "Task" +msgstr "Oppgaver" + +#: cps/templates/tasks.html:15 +#, fuzzy +msgid "Status" +msgstr "Omstart" + +#: cps/templates/tasks.html:16 +msgid "Progress" +msgstr "" + +#: cps/templates/tasks.html:17 +msgid "Run Time" +msgstr "" + +#: cps/templates/tasks.html:20 +#, fuzzy +msgid "Actions" +msgstr "Vurderinger" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +msgstr "" + +#: cps/templates/tasks.html:41 +msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." +msgstr "" + +#: cps/templates/user_edit.html:20 +msgid "Reset user Password" +msgstr "" + +#: cps/templates/user_edit.html:43 +#, fuzzy +msgid "Language of Books" +msgstr "Språk" + +#: cps/templates/user_edit.html:54 +#, fuzzy +msgid "OAuth Settings" +msgstr "Vis forfattervalg" + +#: cps/templates/user_edit.html:56 +msgid "Link" +msgstr "" + +#: cps/templates/user_edit.html:58 +msgid "Unlink" +msgstr "" + +#: cps/templates/user_edit.html:64 +msgid "Kobo Sync Token" +msgstr "" + +#: cps/templates/user_edit.html:66 +msgid "Create/View" +msgstr "" + +#: cps/templates/user_edit.html:70 +msgid "Force full kobo sync" +msgstr "" + +#: cps/templates/user_edit.html:88 +msgid "Add allowed/Denied Custom Column Values" +msgstr "" + +#: cps/templates/user_edit.html:137 +msgid "Sync only books in selected shelves with Kobo" +msgstr "" + +#: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 +#, fuzzy +msgid "Delete User" +msgstr "Kan ikke slette gjestebruker" + +#: cps/templates/user_edit.html:159 +msgid "Generate Kobo Auth URL" +msgstr "" + +#: cps/templates/user_table.html:80 cps/templates/user_table.html:103 +msgid "Select..." +msgstr "" + +#: cps/templates/user_table.html:131 +#, fuzzy +msgid "Edit User" +msgstr "Rediger brukere" + +#: cps/templates/user_table.html:134 +#, fuzzy +msgid "Enter Username" +msgstr "Brukernavn" + +#: cps/templates/user_table.html:135 +#, fuzzy +msgid "Enter Email" +msgstr "Test e-post" + +#: cps/templates/user_table.html:136 +msgid "Enter eReader Email" +msgstr "" + +#: cps/templates/user_table.html:136 +msgid "eReader Email" +msgstr "" + +#: cps/templates/user_table.html:137 +msgid "Locale" +msgstr "" + +#: cps/templates/user_table.html:138 +msgid "Visible Book Languages" +msgstr "" + +#: cps/templates/user_table.html:139 +msgid "Edit Allowed Tags" +msgstr "" + +#: cps/templates/user_table.html:139 +msgid "Allowed Tags" +msgstr "" + +#: cps/templates/user_table.html:140 +msgid "Edit Denied Tags" +msgstr "" + +#: cps/templates/user_table.html:140 +msgid "Denied Tags" +msgstr "" + +#: cps/templates/user_table.html:141 +msgid "Edit Allowed Column Values" +msgstr "" + +#: cps/templates/user_table.html:141 +msgid "Allowed Column Values" +msgstr "" + +#: cps/templates/user_table.html:142 +msgid "Edit Denied Column Values" +msgstr "" + +#: cps/templates/user_table.html:142 +msgid "Denied Column Values" +msgstr "" + +#: cps/templates/user_table.html:144 +#, fuzzy +msgid "Change Password" +msgstr "Passord" + +#: cps/templates/user_table.html:147 +msgid "View" +msgstr "" + +#: cps/templates/user_table.html:150 +msgid "Edit Public Shelves" +msgstr "" + +#: cps/templates/user_table.html:152 +msgid "Sync selected Shelves with Kobo" +msgstr "" + +#: cps/templates/user_table.html:156 +#, fuzzy +msgid "Show Read/Unread Section" +msgstr "Vis serieutvalg" + diff --git a/cps/translations/pl/LC_MESSAGES/messages.mo b/cps/translations/pl/LC_MESSAGES/messages.mo index 81514f9d..f2bd8f97 100644 Binary files a/cps/translations/pl/LC_MESSAGES/messages.mo and b/cps/translations/pl/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/pl/LC_MESSAGES/messages.po b/cps/translations/pl/LC_MESSAGES/messages.po index 051dce4b..7f0cd6bc 100644 --- a/cps/translations/pl/LC_MESSAGES/messages.po +++ b/cps/translations/pl/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre Web - polski (POT: 2021-06-12 08:52)\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2021-06-12 15:35+0200\n" "Last-Translator: Radosław Kierznowski \n" "Language: pl\n" @@ -17,498 +17,508 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statystyki" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Serwer uruchomiony ponownie, proszę odświeżyć stronę" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Wykonano wyłączenie serwera, proszę zamknąć okno" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Ponowne połączenie zakończono sukcesem" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Nieznane polecenie" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Książka została umieszczona w kolejce do wysłania do %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Testowy e-mail czeka w kolejce do wysłania do %(email)s, sprawdź zadania, aby uzyskać wynik" # ??? -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Nieznany" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Panel administratora" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Konfiguracja podstawowa" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Konfiguracja Interfejsu" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Edytuj użytkowników" # ??? -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Wszystko" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Nie znaleziono użytkownika" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} użytkowników usuniętych pomyślnie" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Pokaż wszystkie" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Nieprawidłowo sformułowane żądanie" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Nazwa gościa nie może być zmieniona" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Gość nie może pełnić tej roli" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Nie można odebrać praw administratora. Brak na serwerze innego konta z prawami administratora" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "Wartość musi być prawdziwa lub fałszywa" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Nieprawidłowa rola" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Gość nie może tego zobaczyć" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Nieprawidłowy widok" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Lokalizacja gościa jest określana automatycznie i nie można jej ustawić" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Nie podano prawidłowej lokalizacji" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Nie podano obowiązującego języka książki" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Nie znaleziono parametru" -#: cps/admin.py:567 +#: cps/admin.py:571 #, fuzzy msgid "Invalid Read Column" msgstr "Nieprawidłowa kolumna odczytu" -#: cps/admin.py:573 +#: cps/admin.py:577 #, fuzzy msgid "Invalid Restricted Column" msgstr "Nieprawidłowa kolumna z ograniczeniami" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Konfiguracja Calibre-Web została zaktualizowana" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Czy na pewno chcesz usunąć Token Kobo?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Czy naprawdę chcesz usunąć tę domenę?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Czy naprawdę chcesz usunąć tego użytkownika?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Czy na pewno chcesz usunąć półkę?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Czy na pewno chcesz zmienić ustawienia lokalne wybranego użytkownika(ów)?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "Czy na pewno chcesz zmienić widoczne języki książek dla wybranego użytkownika (użytkowników)?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Czy na pewno chcesz zmienić wybraną rolę dla wybranego użytkownika (użytkowników)?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Czy na pewno chcesz zmienić wybrane ograniczenia dla wybranego użytkownika(ów)?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "Czy na pewno chcesz zmienić wybrane ograniczenia widoczności dla wybranego użytkownika(ów)?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Czy na pewno chcesz zmienić zachowanie synchronizacji półek dla wybranego użytkownika(ów)?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "Czy na pewno chcesz zmienić lokalizację biblioteki Calibre?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Zabroń" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Zezwalaj" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 #, fuzzy msgid "Tag not found" msgstr "Nie znaleziono znacznika" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Nieprawidłowe działanie" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json nie został skonfigurowany dla aplikacji webowej" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Lokalizacja pliku dziennika jest nieprawidłowa, wprowadź poprawną ścieżkę" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Lokalizacja pliku dziennika dostępu jest nieprawidłowa, wprowadź poprawną ścieżkę" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Wprowadź dostawcę LDAP, port, nazwę wyróżniającą i identyfikator obiektu użytkownika" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "Proszę wprowadzić konto i hasło usługi LDAP" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Proszę wprowadzić konto usługi LDAP" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "Filtr obiektów grupy LDAP musi mieć jeden identyfikator formatu \"% s\"" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Filtr obiektów grupy LDAP ma niedopasowany nawias" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "Filtr obiektów użytkownika LDAP musi mieć jeden identyfikator formatu \"% s\"" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Filtr obiektów użytkownika LDAP ma niedopasowany nawias" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "Filtr użytkownika członka LDAP musi mieć jedno \"%s\" identyfikator formatu" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "Filtr użytkownika członka LDAP ma niedopasowane nawiasy" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "Główny urząd certyfikatu LDAP, Certyfikat lub Lokalizacja Klucza nie jest prawidłowa, Proszę wprowadzić poprawną ścieżkę" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Dodaj nowego użytkownika" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Zmień ustawienia SMTP" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Weryfikacja konta Gmail przebiegła pomyślnie" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Błąd bazy danych: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, fuzzy, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "Testowy e-mail czeka w kolejce do wysłania do %(email)s, sprawdź zadania, aby uzyskać wynik" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Wystąpił błąd podczas wysyłania e-maila testowego: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Najpierw skonfiguruj swój adres e-mail..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Zaktualizowano ustawienia serwera poczty e-mail" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Wystąpił nieznany błąd. Spróbuj ponownie później." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Edytuj użytkownika %(nick)s" # ??? -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Zrestartowano hasło użytkownika %(user)s" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Proszę najpierw skonfigurować ustawienia SMTP poczty e-mail..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Przeglądanie dziennika" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Żądanie o pakiet aktualizacji" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Pobieranie pakietu aktualizacji" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Rozpakowywanie pakietu aktualizacji" # ??? -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Zastępowanie plików" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Połączenia z bazą danych zostały zakończone" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Zatrzymywanie serwera" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Aktualizacja zakończona, proszę nacisnąć OK i odświeżyć stronę" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Aktualizacja nieudana:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Błąd HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Błąd połączenia" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Przekroczono limit czasu podczas nawiązywania połączenia" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Błąd ogólny" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Plik aktualizacji nie mógł zostać zapisany w katalogu tymczasowym" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Błąd przy tworzeniu przynajmniej jednego użytkownika LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Błąd przy tworzeniu przynajmniej jednego użytkownika LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Błąd: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Błąd. LDAP nie zwrócił żadnego użytkownika" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Przynajmniej jeden użytkownik LDAP nie został znaleziony w bazie danych" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Użytkownik pomyślnie zaimportowany" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "Lokalizacja bazy danych jest nieprawidłowa, wprowadź poprawną ścieżkę" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "Baza danych nie jest zapisywalna" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "Lokalizacja pliku klucza jest nieprawidłowa, wprowadź poprawną ścieżkę" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "Lokalizacja pliku certyfikatu jest nieprawidłowa, wprowadź poprawną ścieżkę" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Zaktualizowano ustawienia serwera poczty e-mail" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "Konfiguracja bazy danych" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Proszę wypełnić wszystkie pola!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "E-mail nie pochodzi z prawidłowej domeny" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Dodaj nowego użytkownika" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Użytkownik '%(user)s' został utworzony" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "Znaleziono istniejące konto dla tego adresu e-mail lub nazwy." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Użytkownik '%(nick)s' został usunięty" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 #, fuzzy msgid "Can't delete Guest User" msgstr "Nie można usunąć użytkownika gościa" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Nie można usunąć użytkownika. Brak na serwerze innego konta z prawami administratora" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Użytkownik '%(nick)s' został zaktualizowany" @@ -521,122 +531,122 @@ msgstr "nie zainstalowane" msgid "Execution permissions missing" msgstr "Brak uprawnienia do wykonywania pliku" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Niestandardowa kolumna No.%(column)d nie istnieje w bazie calibre" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Brak" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Błąd otwierania e-booka. Plik nie istnieje lub jest niedostępny" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "W identyfikatorach nie jest rozróżniana wielkość liter, nadpisywanie starego identyfikatora" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadane zostały pomyślnie zaktualizowane" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Wysłano plik %(file)s" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Brak formatu źródłowego lub docelowego do konwersji" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Książka została pomyślnie umieszczona w zadaniach do konwersji %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Podczas konwersji książki wystąpił błąd: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Wysłana książka prawdopodobnie istnieje w bibliotece, rozważ zmianę przed przesłaniem nowej: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s nie jest prawidłowym językiem" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Rozszerzenie pliku '%(ext)s' nie jest dozwolone do wysłania na ten serwer" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Plik do wysłania musi mieć rozszerzenie" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Nie można zapisać pliku %(filename)s w katalogu tymczasowym" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Nie udało się przenieść pliku okładki %(file)s:%(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Plik książki w wybranym formacie został usunięty" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Książka została usunięta" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "edytuj metadane" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s nie jest poprawną liczbą, pomijanie" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Nie udało się utworzyć łącza %(path)s (Odmowa dostępu)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Nie można zapisać pliku %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Format pliku %(ext)s dodany do %(book)s" @@ -649,184 +659,191 @@ msgstr "Konfiguracja Google Drive nie została zakończona, spróbuj dezaktywowa msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Zwrotna domena nie jest zweryfikowana, proszę zweryfikowania domenę w konsoli deweloperskiej google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "Nie znaleziono formatu %(format)s dla id książki: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "Nie znaleziono %(format)s na Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s nie znaleziono: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Wyślij do Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Ten e-mail został wysłany za pośrednictwem Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Testowy e-mail Calibre-Web" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Testowy e-mail" # ??? -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Zacznij korzystać z Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Rejestracja e-mail dla użytkownika: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Konwertuj %(orig)s do %(format)s i wyślij do Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Wyślij %(format)s do Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Wyślij do Kindle" # ??? -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Żądany plik nie mógł zostać odczytany. Może brakuje uprawnień?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Usuwanie folderu książki dla książki %(id)s nie powiodło się, ścieżka ma podfoldery: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Usuwanie książki %(id)s zakończyło się błędem: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, fuzzy, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Usuwanie książki %(id)s, ścieżka książki jest niepoprawna: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Zmiana nazwy tytułu z: „%(src)s” na „%(dest)s” zakończyła się błędem: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Nie znaleziono pliku %(file)s na Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Zmiana nazwy tytułu z: „%(src)s” na „%(dest)s” zakończyła się błędem: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Nie znaleziono ścieżki do książki %(path)s na Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "Znaleziono istniejące konto dla tego adresu e-mail" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Nazwa użytkownika jest już zajęta" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Nieprawidłowy format adresu e-mail" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Błąd przy pobieraniu okładki" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Błędny format okładki" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Nie udało się utworzyć ścieżki dla okładki" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Plik okładki nie jest poprawnym plikiem obrazu lub nie mógł zostać zapisany" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Jako plik okładki obsługiwane są tylko pliki jpg/jpeg/png/webp/bmp" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Jako plik okładki dopuszczalne są jedynie pliki jpg/jpeg" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Plik wykonywalny programu unrar nie znaleziony" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Błąd przy wykonywaniu unrar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Odkrywaj" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Aby uzyskać prawidłowy api_endpoint dla urządzenia Kobo, należy skorzystać z dostępu do calibre-web spoza localhost" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Konfiguracja Kobo" @@ -836,9 +853,9 @@ msgstr "Konfiguracja Kobo" msgid "Register with %(provider)s" msgstr "Zarejestruj się %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "zalogowałeś się jako: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -897,12 +914,13 @@ msgstr "Błąd Google Oauth, proszę spróbować później." msgid "Google Oauth error: {}" msgstr "Błąd Google Oauth: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Gwiazdek" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Zaloguj się" @@ -918,149 +936,158 @@ msgstr "Token wygasł" msgid "Success! Please return to your device" msgstr "Powodzenie! Wróć do swojego urządzenia" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Książki" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Pokaż menu ostatnio dodanych książek" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Najpopularniejsze" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Pokaż menu najpopularniejszych książek" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Pobrane książki" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Pokaż pobrane książki" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Najwyżej ocenione" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Pokaż menu najwyżej ocenionych książek" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Przeczytane" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Pokaż menu przeczytane i nieprzeczytane" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Nieprzeczytane" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Pokaż nieprzeczytane" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Odkrywaj" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Pokazuj losowe książki" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Kategorie" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Pokaż menu wyboru kategorii" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Cykle" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Pokaż menu wyboru cyklu" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Autorzy" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Pokaż menu wyboru autora" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Wydawcy" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Pokaż menu wyboru wydawcy" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Języki" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Pokaż menu wyboru języka" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Oceny" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Pokaż menu listy ocen" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Formaty plików" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Pokaż menu formatu plików" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Zarchiwizowane książki" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Pokaż zarchiwizowane książki" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Lista książek" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Pokaż listę książek" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Szukaj" @@ -1083,16 +1110,16 @@ msgid "Rating >= %(rating)s" msgstr "Ocena >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Status przeczytania = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 #, fuzzy msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Błąd podczas wyszukiwania kolumn niestandardowych, proszę zrestartować Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Wyszukiwanie" @@ -1143,7 +1170,7 @@ msgstr "Książka została usunięta z półki: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Utwórz półkę" @@ -1170,73 +1197,73 @@ msgstr "Książka została usunięta" msgid "Change order of Shelf: '%(name)s'" msgstr "Zmieniono kolejność półki: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Półka %(title)s została utworzona" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Półka %(title)s została zmieniona" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Wystąpił błąd" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Publiczna półka o nazwie '%(title)s' już istnieje." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Prywatna półka o nazwie '%(title)s' już istnieje." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Półka: „%(name)s”" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Błąd otwierania półki. Półka nie istnieje lub jest niedostępna" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Zadania" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Oczekiwanie" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Nieudane" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Rozpoczynanie" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Zakończone" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Ststus nieznany" @@ -1269,146 +1296,185 @@ msgstr "Dostępna jest nowa aktualizacja. Kliknij przycisk poniżej, aby zaktual msgid "No release information available" msgstr "Brak dostępnych informacji o wersji" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Odkrywaj (losowe książki)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Najpopularniejsze książki (najczęściej pobierane)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Książki pobrane przez %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autor: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Wydawca: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Cykl: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Ocena: %(rating)s gwiazdek" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Format pliku: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategoria: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Język: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "DLS" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Lista z ocenami" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Lista formatów" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Książka została umieszczona w kolejce do wysłania do %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Proszę najpierw skonfigurować ustawienia SMTP poczty e-mail..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Książka została umieszczona w kolejce do wysłania do %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Wystąpił błąd podczas wysyłania tej książki: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Najpierw skonfiguruj adres e-mail Kindle..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "Serwer e-mail nie jest skonfigurowany, skontaktuj się z administratorem!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Zarejestruj się" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Serwer e-mail nie jest skonfigurowany, skontaktuj się z administratorem!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Twój e-mail nie może się zarejestrować" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Wiadomość e-mail z potwierdzeniem została wysłana na Twoje konto e-mail." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Nie można aktywować uwierzytelniania LDAP" -#: cps/web.py:1297 -#, python-format -msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" -msgstr "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "zalogowałeś się jako: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format +msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" +msgstr "Fallback Login as: %(nickname)s, LDAP Server not reachable, or user not known" + +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Nie można zalogować: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Błędna nazwa użytkownika lub hasło" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Nowe hasło zostało wysłane na Twój adres e-mail" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Wystąpił nieznany błąd. Spróbuj ponownie później." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Wprowadź prawidłową nazwę użytkownika, aby zresetować hasło" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Jesteś teraz zalogowany jako: '%(nickname)s'" +msgstr "zalogowałeś się jako: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Profil użytkownika %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Zaktualizowano profil" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Znaleziono istniejące konto dla tego adresu e-mail" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Nie znaleziono poprawnego pliku gmail.json z informacjami OAuth" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Wyślij do Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1451,35 +1517,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "edytuj metadane" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Wysyłanie" @@ -1495,16 +1561,16 @@ msgstr "Nazwa użytkownika" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "E-mail" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Adres e-mail dla wysyłania do Kindle" # ??? -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Panel administratora" @@ -1515,8 +1581,8 @@ msgid "Password" msgstr "Hasło" # ??? -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Pobieranie" @@ -1542,16 +1608,12 @@ msgstr "Usuń" msgid "Public Shelf" msgstr "Półka publiczna" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Dodaj nowego użytkownika" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importuj użytkowników LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Ustawienia serwera e-mail SMTP" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1572,11 +1634,12 @@ msgstr "Nazwa użytkownika SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Wyślij z adresu e-mail" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "Usługa e-mail" #: cps/templates/admin.html:91 @@ -1648,102 +1711,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Zarządzanie" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Pobierz pakiet Debug" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Podgląd dziennika" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Połącz ponownie z bazą danych Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Uruchom ponownie Calibre Web" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Zatrzymaj Calibre Web" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Wersja" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Szczegóły" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Bieżąca wersja" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Sprawdź aktualizacje" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Wykonaj aktualizację" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Na pewno chcesz uruchomić ponownie Calibre Web?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "OK" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Anuluj" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Na pewno chcesz zatrzymać Calibre Web?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Aktualizowanie, proszę nie odświeżać strony" @@ -1834,7 +1899,7 @@ msgid "Author" msgstr "Autor" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Opis" @@ -1859,7 +1924,7 @@ msgstr "Usuń" msgid "Add Identifier" msgstr "Dodaj identyfikator" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Etykiety" @@ -1884,23 +1949,23 @@ msgid "Published Date" msgstr "Data publikacji" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Wydawca" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Język" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Tak" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Nie" @@ -1917,8 +1982,8 @@ msgid "Fetch Metadata" msgstr "Uzyskaj metadane" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1941,8 +2006,8 @@ msgstr "Kliknij okładkę, aby załadować metadane do formularza" msgid "Loading..." msgstr "Ładowanie..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Zamknij" @@ -2175,7 +2240,7 @@ msgid "Enable Uploads" msgstr "Włącz wysyłanie" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2191,7 +2256,7 @@ msgid "Enable Public Registration" msgstr "Włącz publiczną rejestrację" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Użyj e-maila jako nazwy użytkownika" #: cps/templates/config_edit.html:132 @@ -2381,6 +2446,52 @@ msgstr "Ścieżka do konwertera Kepubify" msgid "Location of Unrar binary" msgstr "Lokalizacja pliku binarnego Unrar" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Ustawienia OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Zresetuj hasło użytkownika" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Konfiguracja widoku" @@ -2393,7 +2504,7 @@ msgstr "Liczba losowych książek do pokazania" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Liczba autorów do pokazania przed ukryciem (0=wyłącza ukrywanie)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Motyw" @@ -2484,80 +2595,84 @@ msgstr "Dodaj dozwolone/zabronione etykiety" msgid "Add Allowed/Denied custom column values" msgstr "Dodaj dozwolone/zabronione wartości własnych kolumn" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Czytaj w przeglądarce" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Słuchaj w przeglądarce" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, fuzzy, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Data publikacji" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Oznacz jako nieprzeczytane" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Oznacz jako przeczytane" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Przeczytana" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Przywróć z archiwum" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Dodaj do archiwum" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Zarchiwizowane" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Opis:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Dodaj do półki" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(publiczna)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Edytuj metadane" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Wybierz typ serwera" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Użyj standardowego konta e-mail" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Konto Gmail z weryfikacją OAuth2" +#, fuzzy +msgid "Gmail Account" +msgstr "Wybierz typ serwera" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Skonfiguruj konto Gmail jako serwer poczty e-mail" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2580,10 +2695,11 @@ msgid "Attachment Size Limit" msgstr "Limit rozmiaru załącznika" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Zapisz ustawienia i wyślij testową wiadomość e-mail" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Wróć" @@ -2609,13 +2725,13 @@ msgstr "Podaj nazwę domeny" msgid "Denied Domains (Blacklist)" msgstr "Domeny zabronione (czarna lista)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Następne" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Otwórz plik .kobo/Kobo eReader.conf w edytorze tekstu i dodaj (lub edytuj):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Otwórz plik .kobo/Kobo/Kobo eReader.conf w edytorze tekstu i dodaj (lub edytuj):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2626,21 +2742,21 @@ msgstr "Token Kobo Sync" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Instancja Calibre-Web jest nieskonfigurowana, proszę skontaktować się z administratorem" # | msgid "Create a Shelf" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Zgłoś błąd" # ??? -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Powrót do głównego menu" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 #, fuzzy msgid "Logout User" msgstr "Wyloguj użytkownika" @@ -2671,80 +2787,80 @@ msgstr "Sortuj rosnąco według indeksu serii" msgid "Sort descending according to series index" msgstr "Sortuj malejąco według indeksu serii" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Rozpocznij" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Książki alfabetyczne" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Książki uporządkowane alfabetycznie" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Popularne publikacje z tego katalogu bazujące na pobranych." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Popularne publikacje z tego katalogu bazujące na ocenach." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Ostatnio dodane książki" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Ostatnie książki" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Losowe książki" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Książki sortowane według autorów" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Książki sortowane według wydawców" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Książki sortowane według kategorii" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Książki sortowane według cyklu" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Ksiązki sortowane według języka" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Książki sortowane według oceny" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Ksiązki sortowane według formatu" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Półki" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Książki ułożone na półkach" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Główne menu" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Przełącz nawigację" @@ -2752,50 +2868,50 @@ msgstr "Przełącz nawigację" msgid "Search Library" msgstr "Przeszukaj bibliotekę" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Konto" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Wyloguj się" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 msgid "Uploading..." msgstr "Wysyłanie…" # ??? -#: cps/templates/layout.html:64 +#: cps/templates/layout.html:78 msgid "Error" msgstr "Błąd" -#: cps/templates/layout.html:64 +#: cps/templates/layout.html:78 msgid "Upload done, processing, please wait..." msgstr "Wysyłanie zakończone, przetwarzanie, proszę czekać…" -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 msgid "Settings" msgstr "Ustawienia" -#: cps/templates/layout.html:79 -msgid "Account" -msgstr "Konto" - -#: cps/templates/layout.html:81 -msgid "Logout" -msgstr "Wyloguj się" - -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Proszę nie odświeżać strony" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Przeglądaj" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Informacje" # ??? -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Poprzedni" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Szczegóły książki" @@ -2811,7 +2927,7 @@ msgstr "Zapamiętaj mnie" msgid "Forgot Password?" msgstr "Zapomniałeś hasło?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Zaloguj się za pomocą „magic link”" @@ -2921,137 +3037,162 @@ msgstr "Katalog e-booków Calibre-Web" msgid "epub Reader" msgstr "Czytnik PDF" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Jasny" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Ciemny" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Wróć" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Przepływ tekstu, gdy paski boczne są otwarte." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "Czytnik PDF" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Skróty klawiaturowe" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Poprzednia strona" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Następna strona" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Skaluj do najlepszego" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Skaluj do szerokości" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Skaluj do wysokości" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Skaluj do wielkości oryginalnej" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Obróć w prawo" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Obróć w lewo" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Odwórć obraz" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Panel administratora" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Skaluj" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Najlepszy" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Szerokość" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Wysokość" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Natywnie" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Obrót" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Odwróć" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Poziomo" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Pionowo" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Kierunek" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Od lewej do prawej" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Od prawej do lewej" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Resetuj do góry" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Zapamiętaj pozycję" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Pasek przewijania" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Pokaż" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Ukryj" @@ -3060,7 +3201,7 @@ msgstr "Ukryj" msgid "DJVU Reader" msgstr "Czytnik PDF" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "Czytnik PDF" @@ -3079,7 +3220,7 @@ msgid "Choose a username" msgstr "Wybierz nazwę użytkownika" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Twój adres e-mail" #: cps/templates/remote_login.html:5 @@ -3098,10 +3239,6 @@ msgstr "Gdy to zrobisz, automatycznie zalogujesz się na tym urządzeniu." msgid "This verification link will expire in 10 minutes." msgstr "Link wygaśnie po 10 minutach." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3126,43 +3263,51 @@ msgstr "Data publikacji od" msgid "Published Date To" msgstr "Data publikacji do" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Wyklucz etykiety" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Wyklucz cykle" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "Z wyłączeniem półek" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Wyklucz języki" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Rozszerzenia" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Wyklucz rozszerzenia" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Ocena większa niż" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Ocena mniejsza niż" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "Od:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Do:" @@ -3255,10 +3400,6 @@ msgstr "Postęp" msgid "Run Time" msgstr "Czas wykonania" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Start" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3332,17 +3473,18 @@ msgid "Enter Username" msgstr "Wprowadź nazwę użytkownika" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "Wpisz adres e-mail" +#, fuzzy +msgid "Enter Email" +msgstr "Testowy e-mail" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "Wprowadź adres e-mail Kindle" +msgid "Enter eReader Email" +msgstr "Adres e-mail dla wysyłania do Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Testowy e-mail" #: cps/templates/user_table.html:137 @@ -3405,10 +3547,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "Zsynchronizuj wybrane półki z Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "Pokaż wybór przeczytane/nieprzeczytane" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Pokaż menu losowych książek" - diff --git a/cps/translations/pt/LC_MESSAGES/messages.mo b/cps/translations/pt/LC_MESSAGES/messages.mo new file mode 100644 index 00000000..3e500110 Binary files /dev/null and b/cps/translations/pt/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/pt/LC_MESSAGES/messages.po b/cps/translations/pt/LC_MESSAGES/messages.po new file mode 100644 index 00000000..741bc429 --- /dev/null +++ b/cps/translations/pt/LC_MESSAGES/messages.po @@ -0,0 +1,3496 @@ +# Translation to portuguese (Portugal) for Calibre-Web. +# This file is distributed under the same license as the Calibre-Web +msgid "" +msgstr "" +"Project-Id-Version: Calibre-Web\n" +"Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" +"PO-Revision-Date: 2023-07-25 11:30+0100\n" +"Last-Translator: horus68 \n" +"Language: pt\n" +"Language-Team: pt-PT <>\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.13.1\n" + +#: cps/about.py:84 +msgid "Statistics" +msgstr "Estatísticas" + +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." +msgstr "Servidor reiniciado, por favor, refresque a página" + +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." +msgstr "A encerrar o servidor, por favor, feche a janela" + +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "Sucesso! Base de dados religada" + +#: cps/admin.py:162 +msgid "Unknown command" +msgstr "Comando desconhecido" + +#: cps/admin.py:173 +#, fuzzy +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Sucesso! Livros enviados para lista de espera para cópia de segurança de metadados. Por favor, verifique o resultado em Tarefas" + +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 +msgid "Unknown" +msgstr "Desconhecido" + +#: cps/admin.py:231 +msgid "Admin page" +msgstr "Página de administração" + +#: cps/admin.py:251 +msgid "Basic Configuration" +msgstr "Configuração básica" + +#: cps/admin.py:289 +msgid "UI Configuration" +msgstr "Configuração de IU" + +#: cps/admin.py:323 cps/templates/admin.html:51 +msgid "Edit Users" +msgstr "Editar utilizadores" + +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 +#: cps/templates/list.html:13 +msgid "All" +msgstr "Tudo" + +#: cps/admin.py:394 cps/admin.py:1405 +msgid "User not found" +msgstr "Utilizador não encontrado" + +#: cps/admin.py:408 +msgid "{} users deleted successfully" +msgstr "{} utilizadores eliminados com sucesso" + +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 +#: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 +msgid "Show All" +msgstr "Mostrar tudo" + +#: cps/admin.py:452 cps/admin.py:458 +msgid "Malformed request" +msgstr "Pedido mal construído" + +#: cps/admin.py:470 cps/admin.py:2023 +msgid "Guest Name can't be changed" +msgstr "Nome do convidado não pode ser alterado" + +#: cps/admin.py:482 +msgid "Guest can't have this role" +msgstr "Convidado não pode ter esta função" + +#: cps/admin.py:494 cps/admin.py:1977 +msgid "No admin user remaining, can't remove admin role" +msgstr "Nenhum utilizador administrador restante, impossível remover a função de administrador" + +#: cps/admin.py:498 cps/admin.py:512 +msgid "Value has to be true or false" +msgstr "Valor tem de ser verdadeiro ou falso" + +#: cps/admin.py:500 +msgid "Invalid role" +msgstr "Função inválida" + +#: cps/admin.py:504 +msgid "Guest can't have this view" +msgstr "O convidado não podr ter esta vista" + +#: cps/admin.py:514 +msgid "Invalid view" +msgstr "Vista inválida" + +#: cps/admin.py:517 +msgid "Guest's Locale is determined automatically and can't be set" +msgstr "O idioma do convidado é detetado automaticamente e não pode ser alterado" + +#: cps/admin.py:521 +msgid "No Valid Locale Given" +msgstr "Nenhum idioma válido fornecido" + +#: cps/admin.py:532 +msgid "No Valid Book Language Given" +msgstr "Não foi indicado um idioma de livro válido" + +#: cps/admin.py:534 cps/editbooks.py:453 +msgid "Parameter not found" +msgstr "Parâmetro não encontrado" + +#: cps/admin.py:571 +msgid "Invalid Read Column" +msgstr "Coluna Lido é inválida" + +#: cps/admin.py:577 +msgid "Invalid Restricted Column" +msgstr "Coluna Restrito é inválida" + +#: cps/admin.py:597 cps/admin.py:1848 +msgid "Calibre-Web configuration updated" +msgstr "Configuração do Calibre-Web atualizada" + +#: cps/admin.py:609 +msgid "Do you really want to delete the Kobo Token?" +msgstr "Quer realmente apagar a Kobo Token?" + +#: cps/admin.py:611 +msgid "Do you really want to delete this domain?" +msgstr "Quer realmente eliminar este domínio?" + +#: cps/admin.py:613 +msgid "Do you really want to delete this user?" +msgstr "Quer realmente apagar este utilizador?" + +#: cps/admin.py:615 +msgid "Are you sure you want to delete this shelf?" +msgstr "Tem a certeza de que quer apagar essa estante?" + +#: cps/admin.py:617 +msgid "Are you sure you want to change locales of selected user(s)?" +msgstr "Tem a certeza de que quer alterar o idioma dos utilizadores selecionados?" + +#: cps/admin.py:619 +msgid "Are you sure you want to change visible book languages for selected user(s)?" +msgstr "Tem a certeza de que quer alterar os idiomas de livros visíveis para os utilizadores selecionados?" + +#: cps/admin.py:621 +msgid "Are you sure you want to change the selected role for the selected user(s)?" +msgstr "Tem a certeza de que quer alterar a função selecionada para os utilizadores selecionados?" + +#: cps/admin.py:623 +msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" +msgstr "Tem a certeza de que quer alterar as restrições selecionadas para os utilizadores selecionados?" + +#: cps/admin.py:625 +msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" +msgstr "Tem a certeza de de que quer alterar as restrições de visibilidade selecionadas para os utilizadores selecionados?" + +#: cps/admin.py:628 +msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" +msgstr "Tem a certeza de que quer alterar o comportamento de sincronização da estante para os utilizadores selecionados?" + +#: cps/admin.py:630 +msgid "Are you sure you want to change Calibre library location?" +msgstr "Tem a certeza de que quer alterar a localização da biblioteca Calibre?" + +#: cps/admin.py:632 +msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" +msgstr "O Calibre-Web irá procurar por capas atualizadas e atualizará as miniaturas das capas. Isto poderá demorar um pouco" + +#: cps/admin.py:635 +msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +msgstr "Tem a certeza de que deseja apagar a base de dados de sincronização do Calibre-Web para forçar uma sincronização completa com seu Kobo Reader?" + +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 +#: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 +#: cps/templates/user_table.html:58 +msgid "Deny" +msgstr "Negar" + +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 +#: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 +#: cps/templates/user_table.html:61 +msgid "Allow" +msgstr "Permitir" + +#: cps/admin.py:921 +msgid "{} sync entries deleted" +msgstr "{} entradas de sincronização eliminadas" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Etiqueta não encontrada" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Ação inválida" + +#: cps/admin.py:1111 +msgid "client_secrets.json Is Not Configured For Web Application" +msgstr "client_secrets.json não está configurado para aplicação Web" + +#: cps/admin.py:1156 +msgid "Logfile Location is not Valid, Please Enter Correct Path" +msgstr "A localização do ficheiro de historial não é válida. Por favor, digite um caminho correto" + +#: cps/admin.py:1162 +msgid "Access Logfile Location is not Valid, Please Enter Correct Path" +msgstr "A localização do ficheiro de historial não é válida. Por favor, digite um caminho correto" + +#: cps/admin.py:1196 +msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" +msgstr "Digite um fornecedor LDAP, porta, DN e identificador de objeto do utilizador" + +#: cps/admin.py:1202 +msgid "Please Enter a LDAP Service Account and Password" +msgstr "Por favor, digite uma conta de serviço LDAP e senha" + +#: cps/admin.py:1205 +msgid "Please Enter a LDAP Service Account" +msgstr "Por favor, digite uma conta de serviço LDAP" + +#: cps/admin.py:1210 +#, python-format +msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" +msgstr "O filtro de objeto de grupo LDAP precisa de ter um identificador de formato \"%s\"" + +#: cps/admin.py:1212 +msgid "LDAP Group Object Filter Has Unmatched Parenthesis" +msgstr "Filtro de objeto de grupo LDAP tem parênteses não coincidentes" + +#: cps/admin.py:1216 +#, python-format +msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" +msgstr "O filtro de objeto de utilizador LDAP precisa de ter um identificador de formato \"%s\"" + +#: cps/admin.py:1218 +msgid "LDAP User Object Filter Has Unmatched Parenthesis" +msgstr "Filtro de objeto de utilizador LDAP tem parênteses não coincidentes" + +#: cps/admin.py:1225 +#, python-format +msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" +msgstr "O filtro de utilizador membro do LDAP precisa ter um identificador de formato \"%s\"" + +#: cps/admin.py:1227 +msgid "LDAP Member User Filter Has Unmatched Parenthesis" +msgstr "Filtro de utilizador de membro LDAP tem parênteses incomparáveis" + +#: cps/admin.py:1234 +msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" +msgstr "LDAP Certificado CA: Localização inválida de certificado ou chave. Por favor, digite um caminho correto" + +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Adicionar utilizador" + +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Editar configurações do servidor de email" + +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Sucesso! Conta Gmail verificada" + +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 +#, python-format +msgid "Oops! Database Error: %(error)s." +msgstr "Erro de base de dados: %(error)s." + +#: cps/admin.py:1323 +#, python-format +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +msgstr "Email de teste enviado para lista de espera para envio para %(email)s. Por favor, verifique o resultado em Tarefas" + +#: cps/admin.py:1326 +#, python-format +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "Ocorreu um erro ao enviar o email de teste: %(res)s" + +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "Por favor, primeiro configure seu endereço de email..." + +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Atualização das configurações do servidor de email" + +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "Editar configurações de tarefas agendadas" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "Hora de início inválida para a tarefa especificada" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "Duração inválida para a tarefa especificada" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Foram atualizadas as configurações de tarefas agendadas" + +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." +msgstr "Ocorreu um erro desconhecido. Por favor, tente novamente mais tarde." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "Configuaração da DB não é gravável" + +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "Editar utilizador %(nick)s" + +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" +msgstr "Sucesso! Senha do utilizador %(user)s redefinida" + +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." +msgstr "Por favor, configure primeiro as configurações de correio SMTP..." + +#: cps/admin.py:1453 +msgid "Logfile viewer" +msgstr "Visualizador do historial" + +#: cps/admin.py:1519 +msgid "Requesting update package" +msgstr "A solicitar pacote de atualização" + +#: cps/admin.py:1520 +msgid "Downloading update package" +msgstr "A descarregar pacote de atualização" + +#: cps/admin.py:1521 +msgid "Unzipping update package" +msgstr "A descomprimir pacote de atualização" + +#: cps/admin.py:1522 +msgid "Replacing files" +msgstr "A substituir ficheiros" + +#: cps/admin.py:1523 +msgid "Database connections are closed" +msgstr "As ligações à base de dados estão fechadas" + +#: cps/admin.py:1524 +msgid "Stopping server" +msgstr "A parar o servidor" + +#: cps/admin.py:1525 +msgid "Update finished, please press okay and reload page" +msgstr "Atualização concluída, pressione OK e refresque a página" + +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 +msgid "Update failed:" +msgstr "Atualização falhou:" + +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +msgid "HTTP Error" +msgstr "Erro HTTP" + +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 +msgid "Connection error" +msgstr "Erro de ligação" + +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 +msgid "Timeout while establishing connection" +msgstr "Tempo limite ao estabelecer a ligação" + +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 +msgid "General error" +msgstr "Erro geral" + +#: cps/admin.py:1530 +msgid "Update file could not be saved in temp dir" +msgstr "Ficheiro de atualização não pode ser guardado na pasta temporária" + +#: cps/admin.py:1531 +msgid "Files could not be replaced during update" +msgstr "Não foi possível substituir ficheiros durante a atualização" + +#: cps/admin.py:1555 +msgid "Failed to extract at least One LDAP User" +msgstr "Falha ao extrair pelo menos um utilizador LDAP" + +#: cps/admin.py:1600 +msgid "Failed to Create at Least One LDAP User" +msgstr "Falha ao criar pelo menos um utilizador LDAP" + +#: cps/admin.py:1613 +#, python-format +msgid "Error: %(ldaperror)s" +msgstr "Erro: %(ldaperror)s" + +#: cps/admin.py:1617 +msgid "Error: No user returned in response of LDAP server" +msgstr "Erro: Nenhum utilizador devolvido na resposta do servidor LDAP" + +#: cps/admin.py:1650 +msgid "At Least One LDAP User Not Found in Database" +msgstr "No mínimo um utilizador LDAP não encontrado no base de dados" + +#: cps/admin.py:1652 +msgid "{} User Successfully Imported" +msgstr "{} utilizador importado com sucesso" + +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "A localização da base de dados não é válida. Por favor, digite o caminho correto" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "DB não é gravável" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "Localização do ficheiro de chaves não é válida. Por favor, digite o caminho correto" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "Localização do ficheiro de certificados não é válida. Por favor, digite o caminho correto" + +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "A dimensão da senha deve estar entre 1 e 40" + +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "Configurações da base de dados atualizadas" + +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Configuração da base de dados" + +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Por favor, preencha todos os campos!" + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "O email não é de um domínio válido" + +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Adicionar novo utilizador" + +#: cps/admin.py:1920 +#, python-format +msgid "User '%(user)s' created" +msgstr "Criado utilizador '%(user)s'" + +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "Já existe uma conta para este endereço de email ou nome." + +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Utilizador '%(nick)s' eliminado" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Impossível eliminar convidado" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "Nenhum utilizador administrador restante, não é possível eliminar o utilizador" + +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "O email não pode estar vazio e tem de ser válido" + +#: cps/admin.py:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Utilizador '%(nick)s' atualizado" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "não instalado" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Falta de permissões de execução" + +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 +#, python-format +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "A coluna personalizada No.%(column)d não existe na base de dados do Calibre" + +#: cps/db.py:993 cps/templates/config_edit.html:204 +#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 +msgid "None" +msgstr "Nenhum" + +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" +msgstr "Oops! O Livro selecionado não está disponível. O ficheiro não existe ou não está acessível" + +#: cps/editbooks.py:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" +msgstr "Utilizador não tem permissão para carregar capas" + +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +msgstr "Os identificadores não diferenciam maiúsculas de minúsculas, substituindo o identificador antigo" + +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Metadados atualizados com sucesso" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" +msgstr "Erro ao editar o livro: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Ficheiro %(file)s enviado" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Formato de origem ou destino para conversão está em falta" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "Livro enviado com sucesso para lista de espera de conversão para %(book_format)s" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "Ocorreu um erro ao converter este livro: %(res)s" + +#: cps/editbooks.py:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " +msgstr "O livro carregado provavelmente existe na biblioteca, considere alterar antes de carregar novo: " + +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "%(langname)s não é um idioma válido" + +#: cps/editbooks.py:741 cps/editbooks.py:1179 +#, python-format +msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" +msgstr "A extensão de ficheiro '%(ext)s' não pode ser enviada para este servidor" + +#: cps/editbooks.py:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "O ficheiro a ser carregado deve ter uma extensão" + +#: cps/editbooks.py:753 +#, python-format +msgid "File %(filename)s could not saved to temp dir" +msgstr "O ficheiro %(filename)s não foi possível ser guardado na pasta temporária" + +#: cps/editbooks.py:773 +#, python-format +msgid "Failed to Move Cover File %(file)s: %(error)s" +msgstr "Falha ao mover ficheiro de capa %(file)s: %(error)s" + +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Formato de livro eliminado com sucesso" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Livro eliminado com sucesso" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "Não tem permissões para apagar livros" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "editar metadados" + +#: cps/editbooks.py:992 +#, python-format +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s não é um número válido, ignorando" + +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "Utilizador não tem direitos para carregar formatos de ficheiro adicionais" + +#: cps/editbooks.py:1195 +#, python-format +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Falha ao criar o caminho %(path)s (Permissão negada)." + +#: cps/editbooks.py:1200 +#, python-format +msgid "Failed to store file %(file)s." +msgstr "Falha ao armazenar o ficheiro %(file)s." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Formato de ficheiro %(ext)s adicionado a %(book)s" + +#: cps/gdrive.py:58 +msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" +msgstr "Configuração do Google Drive não concluída, tente desativar e ativar o Google Drive novamente" + +#: cps/gdrive.py:95 +msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" +msgstr "O domínio Callback não foi verificado. Por favor, siga os passos para verificar o domínio na consola de programadores do Google" + +#: cps/helper.py:81 +#, python-format +msgid "%(format)s format not found for book id: %(book)d" +msgstr "Formato %(format)s não encontrado para o ID do livro: %(book)d" + +#: cps/helper.py:88 cps/tasks/convert.py:75 +#, python-format +msgid "%(format)s not found on Google Drive: %(fn)s" +msgstr "%(format)s não encontrado no Google Drive: %(fn)s" + +#: cps/helper.py:93 +#, python-format +msgid "%(format)s not found: %(fn)s" +msgstr "%(format)s não encontrado: %(fn)s" + +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" +msgstr "Enviar para dispositivo de leitura" + +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." +msgstr "Este email foi enviado via Calibre-Web." + +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" +msgstr "Email de teste do Calibre-Web" + +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" +msgstr "Email de teste" + +#: cps/helper.py:133 +msgid "Get Started with Calibre-Web" +msgstr "Comece a usar o Calibre-Web" + +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" +msgstr "Email de registo do utilizador: %(name)s" + +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +msgid "Convert %(orig)s to %(format)s and send to eReader" +msgstr "Converter %(orig)s em %(format)s e enviar para dispositivo de leitura" + +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" +msgstr "Enviar %(format)s para o dispositivo de leitura" + +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" +msgstr "%(book)s enviado para o dispositivo de leitura" + +#: cps/helper.py:227 +msgid "The requested file could not be read. Maybe wrong permissions?" +msgstr "Não foi possível ler o ficheiro solicitado. Talvez permissões erradas?" + +#: cps/helper.py:342 +msgid "Read status could not set: {}" +msgstr "Estatuto de Lido não pode ser alterado: {}" + +#: cps/helper.py:365 +#, python-format +msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" +msgstr "A eliminação da pasta de livros do livro %(id)s falhou, o caminho tem subpastas: %(path)s" + +#: cps/helper.py:371 +#, python-format +msgid "Deleting book %(id)s failed: %(message)s" +msgstr "Falha ao eliminar livro %(id)s: %(message)s" + +#: cps/helper.py:382 +#, python-format +msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" +msgstr "Eliminar livro %(id)s apenas da base de dados, caminho do livro inválido: %(path)s" + +#: cps/helper.py:447 +#, python-format +msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Renomear autor de: '%(src)s' para '%(dest)s' falhou com o erro: %(error)s" + +#: cps/helper.py:519 cps/helper.py:528 +#, python-format +msgid "File %(file)s not found on Google Drive" +msgstr "Ficheiro %(file)s não encontrado no Google Drive" + +#: cps/helper.py:562 +#, python-format +msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Renomear título de: '%(src)s' para '%(dest)s' falhou com o erro: %(error)s" + +#: cps/helper.py:582 +msgid "Error in rename file in path: {}" +msgstr "Erro ao renomear ficheiro no caminho: {}" + +#: cps/helper.py:600 +#, python-format +msgid "Book path %(path)s not found on Google Drive" +msgstr "Caminho do livro %(path)s não encontrado no Google Drive" + +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "Encontrada uma conta existente para este endereço de email" + +#: cps/helper.py:673 +msgid "This username is already taken" +msgstr "Este nome de utilizador já está registado" + +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" +msgstr "Formato de endereço de email inválido" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "O módulo Python 'advocate' não está instalado, mas é necessário para carregar capas" + +#: cps/helper.py:862 +msgid "Error Downloading Cover" +msgstr "Erro ao descarregar a capa" + +#: cps/helper.py:865 +msgid "Cover Format Error" +msgstr "Erro de formato da capa" + +#: cps/helper.py:868 +msgid "You are not allowed to access localhost or the local network for cover uploads" +msgstr "Não possui permissões para aceder a localhost ou à rede local para carregar capas" + +#: cps/helper.py:878 +msgid "Failed to create path for cover" +msgstr "Falha em criar um caminho para a capa" + +#: cps/helper.py:894 +msgid "Cover-file is not a valid image file, or could not be stored" +msgstr "O ficheiro de capa não é um ficheiro de imagem válido, ou não foi possível ser armazenado" + +#: cps/helper.py:905 +msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" +msgstr "Apenas ficheiros jpg/jpeg/png/webp/bmp são suportados como ficheiros de capa" + +#: cps/helper.py:917 +msgid "Invalid cover file content" +msgstr "Conteúdo do ficheiro de capa inválido" + +#: cps/helper.py:921 +msgid "Only jpg/jpeg files are supported as coverfile" +msgstr "Apenas ficheiros jpg/jpeg são suportados como ficheiros de capa" + +#: cps/helper.py:973 +msgid "Unrar binary file not found" +msgstr "Binário Unrar não encontrado" + +#: cps/helper.py:984 +#, fuzzy +msgid "Error executing UnRar" +msgstr "Erro a executar UnRar" + +#: cps/helper.py:1077 +#, fuzzy +msgid "Cover" +msgstr "Capa" + +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "Enviar todos os livros para lista de espera para cópia de segurança de metadados" + +#: cps/kobo_auth.py:90 +msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" +msgstr "Por favor, aceda ao Calibre-web a partir de um servidor não local para obter uma api_endpoint válida para o dispositivo Kobo" + +#: cps/kobo_auth.py:116 +msgid "Kobo Setup" +msgstr "Configuração Kobo" + +#: cps/oauth_bb.py:77 +#, python-format +msgid "Register with %(provider)s" +msgstr "Autentique-se com %(provider)s" + +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 +#, python-format +msgid "Success! You are now logged in as: %(nickname)s" +msgstr "Sucesso! Agora está autenticado como: '%(nickname)s'" + +#: cps/oauth_bb.py:148 +#, python-format +msgid "Link to %(oauth)s Succeeded" +msgstr "Hiperligação para %(oauth)s bem-sucedida" + +#: cps/oauth_bb.py:155 +msgid "Login failed, No User Linked With OAuth Account" +msgstr "Falha na autenticação, nenhum utilizador ligado a uma conta OAuth" + +#: cps/oauth_bb.py:197 +#, python-format +msgid "Unlink to %(oauth)s Succeeded" +msgstr "Desvincular a %(oauth)s bem-sucedido" + +#: cps/oauth_bb.py:202 +#, python-format +msgid "Unlink to %(oauth)s Failed" +msgstr "Falha ao desvincular de %(oauth)s" + +#: cps/oauth_bb.py:205 +#, python-format +msgid "Not Linked to %(oauth)s" +msgstr "Não vinculado a %(oauth)s" + +#: cps/oauth_bb.py:261 +msgid "Failed to log in with GitHub." +msgstr "Falha na autenticação com GitHub." + +#: cps/oauth_bb.py:267 +msgid "Failed to fetch user info from GitHub." +msgstr "Falha na pesquisa de informações do utilizador no GitHub." + +#: cps/oauth_bb.py:279 +msgid "Failed to log in with Google." +msgstr "Falha na autenticação com Google." + +#: cps/oauth_bb.py:285 +msgid "Failed to fetch user info from Google." +msgstr "Falha na pesquisa de informações de utilizador no Google." + +#: cps/oauth_bb.py:332 +msgid "GitHub Oauth error, please retry later." +msgstr "Erro no Oauth do GitHub. Por favor, tente novamente mais tarde." + +#: cps/oauth_bb.py:335 +msgid "GitHub Oauth error: {}" +msgstr "Erro no Oauth do GitHub: {}" + +#: cps/oauth_bb.py:356 +msgid "Google Oauth error, please retry later." +msgstr "Erro no Google Oauth, tente novamente mais tarde." + +#: cps/oauth_bb.py:359 +msgid "Google Oauth error: {}" +msgstr "Erro no Oauth do Google: {}" + +#: cps/opds.py:274 +msgid "{} Stars" +msgstr "{} Estrelas" + +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 +msgid "Login" +msgstr "Autenticar" + +#: cps/remotelogin.py:74 cps/remotelogin.py:108 +msgid "Token not found" +msgstr "Token não encontrado" + +#: cps/remotelogin.py:83 cps/remotelogin.py:116 +msgid "Token has expired" +msgstr "O Token expirou" + +#: cps/remotelogin.py:92 +msgid "Success! Please return to your device" +msgstr "Sucesso! Por favor, volte ao seu dispositivo" + +#: cps/render_template.py:42 cps/web.py:414 +msgid "Books" +msgstr "Livros" + +#: cps/render_template.py:44 +msgid "Show recent books" +msgstr "Mostrar livros recentes" + +#: cps/render_template.py:45 cps/templates/index.xml:26 +msgid "Hot Books" +msgstr "Livros quentes" + +#: cps/render_template.py:47 +msgid "Show Hot Books" +msgstr "Mostrar livros mais descarregados" + +#: cps/render_template.py:49 cps/render_template.py:54 +msgid "Downloaded Books" +msgstr "Livros descarregados" + +#: cps/render_template.py:51 cps/render_template.py:56 +#: cps/templates/user_table.html:167 +msgid "Show Downloaded Books" +msgstr "Mostrar livros descarregados" + +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 +msgid "Top Rated Books" +msgstr "Top de pontuação de livros" + +#: cps/render_template.py:61 cps/templates/user_table.html:161 +msgid "Show Top Rated Books" +msgstr "Mostrar livros mais bem pontuados" + +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 +msgid "Read Books" +msgstr "Livros lidos" + +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" +msgstr "Mostrar lido e não lido" + +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 +msgid "Unread Books" +msgstr "Livros não lidos" + +#: cps/render_template.py:68 +msgid "Show unread" +msgstr "Mostrar Não Lidos" + +#: cps/render_template.py:69 +msgid "Discover" +msgstr "Descobrir" + +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 +msgid "Show Random Books" +msgstr "Mostrar livros aleatoriamente" + +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 +msgid "Categories" +msgstr "Categorias" + +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" +msgstr "Mostrar secção da categoria" + +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 +msgid "Series" +msgstr "Séries" + +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" +msgstr "Mostrar secção de séries" + +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 +msgid "Authors" +msgstr "Autores" + +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" +msgstr "Mostrar secção de autor" + +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 +msgid "Publishers" +msgstr "Editoras" + +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" +msgstr "Mostrar seleção de editoras" + +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 +msgid "Languages" +msgstr "Idiomas" + +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" +msgstr "Mostrar secção de idioma" + +#: cps/render_template.py:89 cps/templates/index.xml:105 +msgid "Ratings" +msgstr "Pontuações" + +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" +msgstr "Mostrar secção de pontuações" + +#: cps/render_template.py:92 cps/templates/index.xml:113 +msgid "File formats" +msgstr "Formatos de ficheiro" + +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" +msgstr "Mostrar secção de formatos de ficheiro" + +#: cps/render_template.py:96 cps/web.py:776 +msgid "Archived Books" +msgstr "Livros arquivados" + +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Mostrar livros arquivados" + +#: cps/render_template.py:101 cps/web.py:807 +msgid "Books List" +msgstr "Lista de livros" + +#: cps/render_template.py:103 cps/templates/user_table.html:168 +msgid "Show Books List" +msgstr "Mostrar lista de livros" + +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 +#: cps/templates/layout.html:46 cps/templates/layout.html:49 +#: cps/templates/search_form.html:227 +msgid "Search" +msgstr "Pesquisar" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Publicado depois de " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Publicado antes de " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Pontuação <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Pontuação >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Estado de leitura = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "Erro na pesquisa de colunas personalizadas. Por favor, reinicie o Calibre-Web" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Pesquisa avançada" + +#: cps/shelf.py:49 cps/shelf.py:103 +msgid "Invalid shelf specified" +msgstr "Estante inválida especificada" + +#: cps/shelf.py:55 +msgid "Sorry you are not allowed to add a book to that shelf" +msgstr "Desculpe, não possui permissões para adicionar um livro a esta estante" + +#: cps/shelf.py:64 +#, python-format +msgid "Book is already part of the shelf: %(shelfname)s" +msgstr "O livro já faz parte da estante: %(shelfname)s" + +#: cps/shelf.py:89 +#, python-format +msgid "Book has been added to shelf: %(sname)s" +msgstr "O livro foi adicionado à estante: %(sname)s" + +#: cps/shelf.py:108 +msgid "You are not allowed to add a book to the shelf" +msgstr "Não possui permissões para adicionar um livro à estante" + +#: cps/shelf.py:126 +#, python-format +msgid "Books are already part of the shelf: %(name)s" +msgstr "Os livros já fazem parte da estante: %(name)s" + +#: cps/shelf.py:138 +#, python-format +msgid "Books have been added to shelf: %(sname)s" +msgstr "Livros adicionados à estante: %(sname)s" + +#: cps/shelf.py:145 +#, python-format +msgid "Could not add books to shelf: %(sname)s" +msgstr "Não foi possível adicionar livros à estante: %(sname)s" + +#: cps/shelf.py:191 +#, python-format +msgid "Book has been removed from shelf: %(sname)s" +msgstr "O livro foi removido da estante: %(sname)s" + +#: cps/shelf.py:200 +msgid "Sorry you are not allowed to remove a book from this shelf" +msgstr "Desculpe, não possui permissões para remover um livro desta estante" + +#: cps/shelf.py:210 cps/templates/layout.html:157 +msgid "Create a Shelf" +msgstr "Criar estante" + +#: cps/shelf.py:218 +msgid "Sorry you are not allowed to edit this shelf" +msgstr "Desculpe, não possui permissões para editar esta estante" + +#: cps/shelf.py:220 +msgid "Edit a shelf" +msgstr "Editar uma estante" + +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Erro a eliminar a estante" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Estante eliminada com sucesso" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Alterar ordem da Estante: '%(name)s'" + +#: cps/shelf.py:316 +msgid "Sorry you are not allowed to create a public shelf" +msgstr "Desculpe, não possui permissões para criar uma estante pública" + +#: cps/shelf.py:333 +#, python-format +msgid "Shelf %(title)s created" +msgstr "Estante %(title)s criada" + +#: cps/shelf.py:336 +#, python-format +msgid "Shelf %(title)s changed" +msgstr "Estante %(title)s alterada" + +#: cps/shelf.py:350 +msgid "There was an error" +msgstr "Ocorreu um erro" + +#: cps/shelf.py:372 +#, python-format +msgid "A public shelf with the name '%(title)s' already exists." +msgstr "Já existe uma estante pública com o nome '%(title)s' ." + +#: cps/shelf.py:383 +#, python-format +msgid "A private shelf with the name '%(title)s' already exists." +msgstr "Já existe uma estante privada com o nome'%(title)s' ." + +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "Estante: '%(name)s'" + +#: cps/shelf.py:469 +msgid "Error opening shelf. Shelf does not exist or is not accessible" +msgstr "Erro ao abrir estante. A estante não existe ou não está acessível" + +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Tarefas" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Aguardando" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Falhado" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Iniciado" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Concluído" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Terminado" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Cancelado" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Estado desconhecido" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 +msgid "Unexpected data while reading update information" +msgstr "Dados inesperados ao ler informações de atualização" + +#: cps/updater.py:438 cps/updater.py:550 +msgid "No update available. You already have the latest version installed" +msgstr "Não existem atualizações disponíveis. Você já tem instalada a última versão" + +#: cps/updater.py:456 +msgid "A new update is available. Click on the button below to update to the latest version." +msgstr "Uma nova atualização está disponível. Clique no botão abaixo para atualizar para a versão mais recente." + +#: cps/updater.py:474 +msgid "Could not fetch update information" +msgstr "Não foi possível obter informações sobre atualizações" + +#: cps/updater.py:484 +msgid "Click on the button below to update to the latest stable version." +msgstr "Clique no botão abaixo para atualizar para a última versão estável." + +#: cps/updater.py:493 cps/updater.py:507 cps/updater.py:518 +#, python-format +msgid "A new update is available. Click on the button below to update to version: %(version)s" +msgstr "Uma nova atualização está disponível. Clique no botão abaixo para atualizar para a versão: %(version)s" + +#: cps/updater.py:536 +msgid "No release information available" +msgstr "Não existem informações disponíveis sobre o lançamento" + +#: cps/templates/index.html:6 cps/web.py:441 +msgid "Discover (Random Books)" +msgstr "Descobrir (Livros aleatórios)" + +#: cps/web.py:477 +msgid "Hot Books (Most Downloaded)" +msgstr "Livros quentes (Mais descarregados)" + +#: cps/web.py:508 +#, python-format +msgid "Downloaded books by %(user)s" +msgstr "Livros descarregados por %(user)s" + +#: cps/web.py:541 +#, python-format +msgid "Author: %(name)s" +msgstr "Autor: %(name)s" + +#: cps/web.py:577 +#, python-format +msgid "Publisher: %(name)s" +msgstr "Editora: %(name)s" + +#: cps/web.py:605 +#, python-format +msgid "Series: %(serie)s" +msgstr "Séries: %(serie)s" + +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Pontuação: Nenhuma" + +#: cps/web.py:629 +#, python-format +msgid "Rating: %(rating)s stars" +msgstr "Pontuação: %(rating)s estrelas" + +#: cps/web.py:645 +#, python-format +msgid "File format: %(format)s" +msgstr "Formato do ficheiro: %(format)s" + +#: cps/web.py:682 +#, python-format +msgid "Category: %(name)s" +msgstr "Categoria: %(name)s" + +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Idioma: %(name)s" + +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "Descarregamentos" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "Lista de pontuações" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Lista de formatos de ficheiro" + +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Por favor, configure primeiro as configurações de correio SMTP..." + +#: cps/web.py:1240 +#, python-format +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Sucesso! Livro enviado para lista de espera para envio a %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" +msgstr "Ops! Ocorreu um erro ao enviar este livro: %(res)s" + +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "Ops! Por favor, atualize o seu perfil com um endereço de email válido para envio ao Kindle." + +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "Por favor, aguarde um minuto para registar o próximo utilizador" + +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 +msgid "Register" +msgstr "Registar" + +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Ops! O servidor de email não está configurado. Por favor, contacte o seu administrador!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." +msgstr "Ops! O seu email não é permitido para registo" + +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "Sucesso! O email de confirmação foi enviado para a sua conta de email." + +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy +msgid "Cannot activate LDAP authentication" +msgstr "Não é possível ativar a autenticação LDAP" + +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "Por favor, aguarde um minuto antes de nova autenticação" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "agora você está autenticado como: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format +msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" +msgstr "Autenticação recurso como:'%(nickname)s', servidor LDAP não acessível ou utilizador desconhecido" + +#: cps/web.py:1388 +#, fuzzy, python-format +msgid "Could not login: %(message)s" +msgstr "Não foi possível autenticar-se: %(message)s" + +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy +msgid "Wrong Username or Password" +msgstr "Nome de utilizador ou senha incorretos" + +#: cps/web.py:1399 +#, fuzzy +msgid "New Password was send to your email address" +msgstr "Nova senha foi enviada para seu endereço de email" + +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Ocorreu um erro desconhecido. Por favor, tente novamente mais tarde." + +#: cps/web.py:1405 +#, fuzzy +msgid "Please enter valid username to reset password" +msgstr "Por favor, digite um nome de utilizador válido para poder redefinir a senha" + +#: cps/web.py:1413 +#, fuzzy, python-format +msgid "You are now logged in as: '%(nickname)s'" +msgstr "Agora você está autenticado como: '%(nickname)s'" + +#: cps/web.py:1471 cps/web.py:1521 +#, python-format +msgid "%(name)s's Profile" +msgstr "Perfil de %(name)s" + +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" +msgstr "Perfil atualizado" + +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Foi encontrada uma conta já existente com este endereço de email." + +#: cps/services/gmail.py:58 +msgid "Found no valid gmail.json file with OAuth information" +msgstr "Não foi encontrado nenhum ficheiro gmail.json válido com informações do OAuth" + +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s enviado para dispositivo de leitura" + +#: cps/tasks/convert.py:153 +#, python-format +msgid "Calibre ebook-convert %(tool)s not found" +msgstr "Calibre ebook-convert %(tool)s não encontrado" + +#: cps/tasks/convert.py:186 +#, python-format +msgid "%(format)s format not found on disk" +msgstr "Formato %(format)s não encontrado no disco" + +#: cps/tasks/convert.py:190 +msgid "Ebook converter failed with unknown error" +msgstr "O conversor de ebook falhou com erro desconhecido" + +#: cps/tasks/convert.py:202 +#, python-format +msgid "Kepubify-converter failed: %(error)s" +msgstr "Conversor Kepubify falhou: %(error)s" + +#: cps/tasks/convert.py:224 +#, python-format +msgid "Converted file not found or more than one file in folder %(folder)s" +msgstr "Ficheiro convertido não encontrado ou mais de um ficheiro na pasta %(folder)s" + +#: cps/tasks/convert.py:247 +#, python-format +msgid "Ebook-converter failed: %(error)s" +msgstr "Conversor de ebook falhou: %(error)s" + +#: cps/tasks/convert.py:270 +#, python-format +msgid "Calibre failed with error: %(error)s" +msgstr "Calibre falhou com erro: %(error)s" + +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Converter" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "A religar base de dados Calibre" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "Email" + +#: cps/tasks/metadata_backup.py:46 +#, fuzzy +msgid "Backing up Metadata" +msgstr "Cópia de segurança de metadados" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "Geradas %(count)s miniaturas para capa" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "Miniaturas de capa" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "Geradas {0} miniaturas de série" + +#: cps/tasks/thumbnail.py:454 +msgid "Clearing cover thumbnail cache" +msgstr "A esvaziar a cache de miniaturas da capa" + +#: cps/tasks/upload.py:38 cps/templates/admin.html:20 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Carregar" + +#: cps/templates/admin.html:9 +msgid "Users" +msgstr "Utilizadores" + +#: cps/templates/admin.html:13 cps/templates/login.html:9 +#: cps/templates/login.html:10 cps/templates/register.html:9 +#: cps/templates/user_edit.html:10 cps/templates/user_table.html:134 +msgid "Username" +msgstr "Nome de utilizador" + +#: cps/templates/admin.html:14 cps/templates/register.html:14 +#: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 +msgid "Email" +msgstr "Endereço de email" + +#: cps/templates/admin.html:15 cps/templates/user_edit.html:28 +msgid "Send to eReader Email" +msgstr "Enviar para o endereço de email do dispositivod e leitura" + +#: cps/templates/admin.html:17 cps/templates/layout.html:91 +#: cps/templates/user_table.html:143 +msgid "Admin" +msgstr "Admin" + +#: cps/templates/admin.html:18 cps/templates/login.html:13 +#: cps/templates/login.html:14 cps/templates/user_edit.html:23 +msgid "Password" +msgstr "Senha" + +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 +#: cps/templates/user_table.html:146 +msgid "Download" +msgstr "Descarregar" + +#: cps/templates/admin.html:23 +msgid "View Books" +msgstr "Ver Livros" + +#: cps/templates/admin.html:24 cps/templates/user_table.html:131 +#: cps/templates/user_table.html:148 +msgid "Edit" +msgstr "Editar" + +#: cps/templates/admin.html:25 cps/templates/book_edit.html:17 +#: cps/templates/book_table.html:100 cps/templates/modal_dialogs.html:63 +#: cps/templates/modal_dialogs.html:116 cps/templates/user_edit.html:67 +#: cps/templates/user_table.html:149 +msgid "Delete" +msgstr "Apagar" + +#: cps/templates/admin.html:26 +msgid "Public Shelf" +msgstr "Estante pública" + +#: cps/templates/admin.html:55 +msgid "Import LDAP Users" +msgstr "Importar utilizadores LDAP" + +#: cps/templates/admin.html:62 +msgid "Email Server Settings" +msgstr "Configurações do servidor de email" + +#: cps/templates/admin.html:67 cps/templates/email_edit.html:31 +msgid "SMTP Hostname" +msgstr "Nome de servidor SMTP" + +#: cps/templates/admin.html:71 cps/templates/email_edit.html:35 +msgid "SMTP Port" +msgstr "Porta SMTP" + +#: cps/templates/admin.html:75 cps/templates/email_edit.html:39 +msgid "Encryption" +msgstr "Encriptação" + +#: cps/templates/admin.html:79 cps/templates/email_edit.html:47 +msgid "SMTP Login" +msgstr "Autenticação SMTP" + +#: cps/templates/admin.html:83 cps/templates/admin.html:94 +#: cps/templates/email_edit.html:55 +msgid "From Email" +msgstr "Do email" + +#: cps/templates/admin.html:90 +#, fuzzy +msgid "Email Service" +msgstr "Serviço de eMail" + +#: cps/templates/admin.html:91 +msgid "Gmail via Oauth2" +msgstr "Gmail via Oauth2" + +#: cps/templates/admin.html:106 +msgid "Configuration" +msgstr "Configuração" + +#: cps/templates/admin.html:109 +msgid "Calibre Database Directory" +msgstr "Pasta da base de dados Calibre" + +#: cps/templates/admin.html:113 cps/templates/config_edit.html:68 +msgid "Log Level" +msgstr "Nível de registos" + +#: cps/templates/admin.html:117 +msgid "Port" +msgstr "Porta" + +#: cps/templates/admin.html:122 +msgid "External Port" +msgstr "Porta externa" + +#: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 +msgid "Books per Page" +msgstr "Livros por página" + +#: cps/templates/admin.html:133 +msgid "Uploads" +msgstr "Carregamentos" + +#: cps/templates/admin.html:137 +msgid "Anonymous Browsing" +msgstr "Navegação anónima" + +#: cps/templates/admin.html:141 +msgid "Public Registration" +msgstr "Inscrição pública" + +#: cps/templates/admin.html:145 +msgid "Magic Link Remote Login" +msgstr "Autenticação remota Magic Link" + +#: cps/templates/admin.html:149 +msgid "Reverse Proxy Login" +msgstr "Autenticação de Proxy reverso" + +#: cps/templates/admin.html:154 cps/templates/config_edit.html:173 +msgid "Reverse Proxy Header Name" +msgstr "Nome do cabeçalho do Proxy reverso" + +#: cps/templates/admin.html:159 +msgid "Edit Calibre Database Configuration" +msgstr "Editar configuração da base de dados do Calibre" + +#: cps/templates/admin.html:160 +msgid "Edit Basic Configuration" +msgstr "Editar configurações básicas" + +#: cps/templates/admin.html:161 +msgid "Edit UI Configuration" +msgstr "Editar configuração de IU" + +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Tarefas agendadas" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "Hora de início" + +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +msgid "Maximum Duration" +msgstr "Duração máxima" + +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" +msgstr "Gerar miniaturas" + +#: cps/templates/admin.html:182 +msgid "Generate series cover thumbnails" +msgstr "Gerar miniaturas para capa de séries" + +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Religar à biblioteca do Calibre" + +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "Criar cópia de segurança dos metadados" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "Atualizar Cache de miniaturas" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Administração" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Descarregar pacote de depuração" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Ver historial" + +#: cps/templates/admin.html:211 +msgid "Restart" +msgstr "Reiniciar" + +#: cps/templates/admin.html:212 +msgid "Shutdown" +msgstr "Desligar" + +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Dados da versão" + +#: cps/templates/admin.html:225 +msgid "Version" +msgstr "Versão" + +#: cps/templates/admin.html:226 +msgid "Details" +msgstr "Detalhes" + +#: cps/templates/admin.html:232 +msgid "Current Version" +msgstr "Versão atual" + +#: cps/templates/admin.html:239 +msgid "Check for Update" +msgstr "Verificar atualizações" + +#: cps/templates/admin.html:240 +msgid "Perform Update" +msgstr "Aplicar atualizações" + +#: cps/templates/admin.html:253 +msgid "Are you sure you want to restart?" +msgstr "Tem a certeza de que quer reiniciar?" + +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 +msgid "OK" +msgstr "Ok" + +#: cps/templates/admin.html:259 cps/templates/admin.html:273 +#: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 +#: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 +#: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 +#: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 +#: cps/templates/user_edit.html:144 +msgid "Cancel" +msgstr "Cancelar" + +#: cps/templates/admin.html:271 +msgid "Are you sure you want to shutdown?" +msgstr "Tem certeza de que quer encerrar?" + +#: cps/templates/admin.html:283 +msgid "Updating, please do not reload this page" +msgstr "A atualizar, por favor, não refresque esta página" + +#: cps/templates/author.html:15 +msgid "via" +msgstr "via" + +#: cps/templates/author.html:23 +msgid "In Library" +msgstr "Na Biblioteca" + +#: cps/templates/author.html:26 cps/templates/index.html:74 +#: cps/templates/search.html:31 cps/templates/shelf.html:20 +msgid "Sort according to book date, newest first" +msgstr "Ordenar de acordo com a data do livro, o mais recente primeiro" + +#: cps/templates/author.html:27 cps/templates/index.html:75 +#: cps/templates/search.html:32 cps/templates/shelf.html:21 +msgid "Sort according to book date, oldest first" +msgstr "Ordenar de acordo com a data do livro, o mais antigo primeiro" + +#: cps/templates/author.html:28 cps/templates/index.html:76 +#: cps/templates/search.html:33 cps/templates/shelf.html:22 +msgid "Sort title in alphabetical order" +msgstr "Ordenar título em ordem alfabética" + +#: cps/templates/author.html:29 cps/templates/index.html:77 +#: cps/templates/search.html:34 cps/templates/shelf.html:23 +msgid "Sort title in reverse alphabetical order" +msgstr "Ordenar título em ordem alfabética inversa" + +#: cps/templates/author.html:30 cps/templates/index.html:80 +#: cps/templates/search.html:37 cps/templates/shelf.html:26 +msgid "Sort according to publishing date, newest first" +msgstr "Ordenar de acordo com a data de publicação, o mais novo primeiro" + +#: cps/templates/author.html:31 cps/templates/index.html:81 +#: cps/templates/search.html:38 cps/templates/shelf.html:27 +msgid "Sort according to publishing date, oldest first" +msgstr "Ordenar de acordo com a data de publicação, o mais antigo primeiro" + +#: cps/templates/author.html:56 cps/templates/author.html:115 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 +msgid "reduce" +msgstr "reduzir" + +#: cps/templates/author.html:99 +msgid "More by" +msgstr "Outros por" + +#: cps/templates/book_edit.html:11 +msgid "Delete Book" +msgstr "Apagar livro" + +#: cps/templates/book_edit.html:14 +msgid "Delete formats:" +msgstr "Apagar formatos:" + +#: cps/templates/book_edit.html:25 +msgid "Convert book format:" +msgstr "Converter formato do livro:" + +#: cps/templates/book_edit.html:30 +msgid "Convert from:" +msgstr "Converter de:" + +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 +msgid "select an option" +msgstr "selecionar uma opção" + +#: cps/templates/book_edit.html:37 +msgid "Convert to:" +msgstr "Converter para:" + +#: cps/templates/book_edit.html:46 +msgid "Convert book" +msgstr "Converter livro" + +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 +msgid "Book Title" +msgstr "Título do livro" + +#: cps/templates/book_edit.html:63 cps/templates/book_edit.html:271 +#: cps/templates/book_edit.html:289 cps/templates/search_form.html:12 +msgid "Author" +msgstr "Autor" + +#: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 +msgid "Description" +msgstr "Descrição" + +#: cps/templates/book_edit.html:73 +msgid "Identifiers" +msgstr "Identificadores" + +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +msgid "Identifier Type" +msgstr "Tipo de identificador" + +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +msgid "Identifier Value" +msgstr "Valor do identificador" + +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 +#: cps/templates/user_table.html:24 +msgid "Remove" +msgstr "Remover" + +#: cps/templates/book_edit.html:83 +msgid "Add Identifier" +msgstr "Adicionar identificador" + +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 +msgid "Tags" +msgstr "Etiquetas" + +#: cps/templates/book_edit.html:95 +msgid "Series ID" +msgstr "Identificador da série" + +#: cps/templates/book_edit.html:99 +msgid "Rating" +msgstr "Pontuação" + +#: cps/templates/book_edit.html:104 +msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" +msgstr "Obter capa a partir de URL (JPEG - Imagem será descarregada e armazenada na base de dados)" + +#: cps/templates/book_edit.html:108 +msgid "Upload Cover from Local Disk" +msgstr "Carregar capa a partir de disco local" + +#: cps/templates/book_edit.html:113 +msgid "Published Date" +msgstr "Data de publicação" + +#: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 +msgid "Publisher" +msgstr "Editora" + +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 +msgid "Language" +msgstr "Idioma" + +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 +msgid "Yes" +msgstr "Sim" + +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 +msgid "No" +msgstr "Não" + +#: cps/templates/book_edit.html:201 +msgid "Upload Format" +msgstr "Formato de carregamento" + +#: cps/templates/book_edit.html:209 +msgid "View Book on Save" +msgstr "Ver livro ao guardar" + +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 +msgid "Fetch Metadata" +msgstr "Obter metadados" + +#: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 +#: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 +#: cps/templates/user_edit.html:142 +msgid "Save" +msgstr "Guardar" + +#: cps/templates/book_edit.html:233 +msgid "Keyword" +msgstr "Termo-chave" + +#: cps/templates/book_edit.html:234 +msgid "Search keyword" +msgstr "Pesquisar termo-chave" + +#: cps/templates/book_edit.html:240 +msgid "Click the cover to load metadata to the form" +msgstr "Clique na capa para carregar os metadados para o formulário" + +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 +msgid "Loading..." +msgstr "A carregar..." + +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 +#: cps/templates/user_edit.html:163 +msgid "Close" +msgstr "Fechar" + +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 +msgid "Source" +msgstr "Fonte" + +#: cps/templates/book_edit.html:287 +msgid "Search error!" +msgstr "Erro de pesquisa!" + +#: cps/templates/book_edit.html:288 +msgid "No Result(s) found! Please try another keyword." +msgstr "Nenhum resultado encontrado! Por favor, tente pesquisar por outro termo-chave." + +#: cps/templates/book_table.html:12 cps/templates/book_table.html:69 +#: cps/templates/user_table.html:14 cps/templates/user_table.html:77 +#: cps/templates/user_table.html:100 +msgid "This Field is Required" +msgstr "Este campo é obrigatório" + +#: cps/templates/book_table.html:37 +msgid "Merge selected books" +msgstr "Fundir livros selecionados" + +#: cps/templates/book_table.html:38 cps/templates/user_table.html:124 +msgid "Remove Selections" +msgstr "Remover seleções" + +#: cps/templates/book_table.html:41 +msgid "Exchange author and title" +msgstr "Trocar autor por título" + +#: cps/templates/book_table.html:47 +msgid "Update Title Sort automatically" +msgstr "Atualizar ordenação de título automaticamente" + +#: cps/templates/book_table.html:51 +msgid "Update Author Sort automatically" +msgstr "Atualizar ordenação de autor automaticamente" + +#: cps/templates/book_table.html:63 cps/templates/book_table.html:69 +msgid "Enter Title" +msgstr "Preencher título" + +#: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 +#: cps/templates/shelf_edit.html:8 +msgid "Title" +msgstr "Título" + +#: cps/templates/book_table.html:64 +msgid "Enter Title Sort" +msgstr "Preencher ordenação do título" + +#: cps/templates/book_table.html:64 +msgid "Title Sort" +msgstr "Ordenação de título" + +#: cps/templates/book_table.html:65 +msgid "Enter Author Sort" +msgstr "Preencher ordenação de autor" + +#: cps/templates/book_table.html:65 +msgid "Author Sort" +msgstr "Ordenação de autor" + +#: cps/templates/book_table.html:66 +msgid "Enter Authors" +msgstr "Preencher autores" + +#: cps/templates/book_table.html:67 +msgid "Enter Categories" +msgstr "Preencher categorias" + +#: cps/templates/book_table.html:68 +msgid "Enter Series" +msgstr "Preencher série" + +#: cps/templates/book_table.html:69 +msgid "Series Index" +msgstr "Índice da série" + +#: cps/templates/book_table.html:70 +msgid "Enter Languages" +msgstr "Preencher idiomas" + +#: cps/templates/book_table.html:71 +msgid "Publishing Date" +msgstr "Data de publicação" + +#: cps/templates/book_table.html:72 +msgid "Enter Publishers" +msgstr "Preencher editoras" + +#: cps/templates/book_table.html:73 +msgid "Enter comments" +msgstr "Preencher comentários" + +#: cps/templates/book_table.html:73 +msgid "Comments" +msgstr "Comentários" + +#: cps/templates/book_table.html:75 +msgid "Archive Status" +msgstr "Estado de arquivamento" + +#: cps/templates/book_table.html:77 cps/templates/search_form.html:42 +msgid "Read Status" +msgstr "Estado de leitura" + +#: cps/templates/book_table.html:80 cps/templates/book_table.html:82 +#: cps/templates/book_table.html:84 cps/templates/book_table.html:86 +#: cps/templates/book_table.html:90 cps/templates/book_table.html:92 +#: cps/templates/book_table.html:96 +msgid "Enter " +msgstr "Preencher " + +#: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 +msgid "Are you really sure?" +msgstr "Tem realmente a certeza?" + +#: cps/templates/book_table.html:117 +msgid "Books with Title will be merged from:" +msgstr "Livros com título serão fundidos de:" + +#: cps/templates/book_table.html:121 +msgid "Into Book with Title:" +msgstr "Em livro com o título:" + +#: cps/templates/book_table.html:126 +msgid "Merge" +msgstr "Fundir" + +#: cps/templates/config_db.html:12 +msgid "Location of Calibre Database" +msgstr "Localização da base de dados Calibre" + +#: cps/templates/config_db.html:22 +msgid "Use Google Drive?" +msgstr "Usar Google Drive?" + +#: cps/templates/config_db.html:27 +msgid "Authenticate Google Drive" +msgstr "Autenticar com Google Drive" + +#: cps/templates/config_db.html:32 +msgid "Google Drive Calibre folder" +msgstr "Pasta Calibre no Google Drive" + +#: cps/templates/config_db.html:40 +msgid "Metadata Watch Channel ID" +msgstr "ID de canal de metadados" + +#: cps/templates/config_db.html:43 +msgid "Revoke" +msgstr "Revogar" + +#: cps/templates/config_db.html:68 +msgid "New db location is invalid, please enter valid path" +msgstr "Novo local da base de dados é inválido. Por favor, insira um caminho válido" + +#: cps/templates/config_edit.html:18 +msgid "Server Configuration" +msgstr "Configuração do servidor" + +#: cps/templates/config_edit.html:25 +msgid "Server Port" +msgstr "Porta do servidor" + +#: cps/templates/config_edit.html:28 +msgid "SSL certfile location (leave it empty for non-SSL Servers)" +msgstr "Localização do ficheiro de certificado SSL (deixar vazio para servidores não-SSL)" + +#: cps/templates/config_edit.html:35 +msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" +msgstr "Localização do ficheiro de chave SSL (deixar vazio para servidores não-SSL)" + +#: cps/templates/config_edit.html:43 +msgid "Update Channel" +msgstr "Canal de atualização" + +#: cps/templates/config_edit.html:45 +msgid "Stable" +msgstr "Estável" + +#: cps/templates/config_edit.html:46 +msgid "Nightly" +msgstr "Desenvolvimento" + +#: cps/templates/config_edit.html:50 +msgid "Trusted Hosts (Comma Separated)" +msgstr "Alojamentos confiáveis (Separado por vírgulas)" + +#: cps/templates/config_edit.html:61 +msgid "Logfile Configuration" +msgstr "Configuração do ficheiro de historial" + +#: cps/templates/config_edit.html:77 +msgid "Location and name of logfile (calibre-web.log for no entry)" +msgstr "Localização e nome do ficheiro de historial (calibre-web.log se nenhuma indicação)" + +#: cps/templates/config_edit.html:82 +msgid "Enable Access Log" +msgstr "Ativar historial de acesso" + +#: cps/templates/config_edit.html:85 +msgid "Location and name of access logfile (access.log for no entry)" +msgstr "Localização e nome do ficheiro de historial de acesso (access.log se nenhuma indicação)" + +#: cps/templates/config_edit.html:96 +msgid "Feature Configuration" +msgstr "Configuração do Recursos" + +#: cps/templates/config_edit.html:104 +msgid "Convert non-English characters in title and author while saving to disk" +msgstr "Converter caracteres não latinos nos títulos e autores enquanto guarda em disco" + +#: cps/templates/config_edit.html:108 +msgid "Enable Uploads" +msgstr "Ativar carregamentos" + +#: cps/templates/config_edit.html:108 +msgid "(Please ensure that users also have upload permissions)" +msgstr "(Por favor, certifique-se de que os utilizadores também tenham direitos de carregamento)" + +#: cps/templates/config_edit.html:112 +msgid "Allowed Upload Fileformats" +msgstr "Formatos de ficheiros de carregamento permitidos" + +#: cps/templates/config_edit.html:118 +msgid "Enable Anonymous Browsing" +msgstr "Ativar navegação anónima" + +#: cps/templates/config_edit.html:122 +msgid "Enable Public Registration" +msgstr "Ativar inscrição pública" + +#: cps/templates/config_edit.html:127 +msgid "Use Email as Username" +msgstr "Usar email como nome de utilizador" + +#: cps/templates/config_edit.html:132 +msgid "Enable Magic Link Remote Login" +msgstr "Ativar autenticação remota do Magic Link" + +#: cps/templates/config_edit.html:137 +msgid "Enable Kobo sync" +msgstr "Ativar Kobo sync" + +#: cps/templates/config_edit.html:142 +msgid "Proxy unknown requests to Kobo Store" +msgstr "Solicitações desconhecidas de Proxy para a Kobo Store" + +#: cps/templates/config_edit.html:145 +msgid "Server External Port (for port forwarded API calls)" +msgstr "Porta externa do servidor (para chamadas API encaminhadas)" + +#: cps/templates/config_edit.html:153 +msgid "Use Goodreads" +msgstr "Usar Goodreads" + +#: cps/templates/config_edit.html:154 +msgid "Create an API Key" +msgstr "Criar uma chave API" + +#: cps/templates/config_edit.html:158 +msgid "Goodreads API Key" +msgstr "Chave API Goodreads" + +#: cps/templates/config_edit.html:162 +msgid "Goodreads API Secret" +msgstr "Senha API Goodreads" + +#: cps/templates/config_edit.html:169 +msgid "Allow Reverse Proxy Authentication" +msgstr "Permitir autenticação por Proxy reverso" + +#: cps/templates/config_edit.html:180 +msgid "Login type" +msgstr "Tipo de autenticação" + +#: cps/templates/config_edit.html:182 +msgid "Use Standard Authentication" +msgstr "Usar autenticação padrão" + +#: cps/templates/config_edit.html:184 +msgid "Use LDAP Authentication" +msgstr "Usar autenticação LDAP" + +#: cps/templates/config_edit.html:187 +msgid "Use OAuth" +msgstr "Usar OAuth" + +#: cps/templates/config_edit.html:194 +msgid "LDAP Server Host Name or IP Address" +msgstr "Nome ou endereço IP do servidor LDAP" + +#: cps/templates/config_edit.html:198 +msgid "LDAP Server Port" +msgstr "Porta do servidor LDAP" + +#: cps/templates/config_edit.html:202 +msgid "LDAP Encryption" +msgstr "Criptografia LDAP" + +#: cps/templates/config_edit.html:205 +msgid "TLS" +msgstr "TLS" + +#: cps/templates/config_edit.html:206 +msgid "SSL" +msgstr "SSL" + +#: cps/templates/config_edit.html:210 +msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" +msgstr "Caminho do certificado CA do LDAP (Necessário apenas para autenticação por certificado de cliente)" + +#: cps/templates/config_edit.html:217 +msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" +msgstr "Caminho do certificado LDAP (Necessário apenas para autenticação por certificado de cliente)" + +#: cps/templates/config_edit.html:224 +msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" +msgstr "Caminho do ficheiro de chave LDAP (Necessário apenas para autenticação por certificado de cliente)" + +#: cps/templates/config_edit.html:233 +msgid "LDAP Authentication" +msgstr "Autenticação LDAP" + +#: cps/templates/config_edit.html:235 +msgid "Anonymous" +msgstr "Anónimo" + +#: cps/templates/config_edit.html:236 +msgid "Unauthenticated" +msgstr "Não autenticado" + +#: cps/templates/config_edit.html:237 +msgid "Simple" +msgstr "Simples" + +#: cps/templates/config_edit.html:242 +msgid "LDAP Administrator Username" +msgstr "Nome de utilizador do administrador LDAP" + +#: cps/templates/config_edit.html:248 +msgid "LDAP Administrator Password" +msgstr "Senha de administrador LDAP" + +#: cps/templates/config_edit.html:253 +msgid "LDAP Distinguished Name (DN)" +msgstr "Nome distinto LDAP (DN)" + +#: cps/templates/config_edit.html:257 +msgid "LDAP User Object Filter" +msgstr "Filtro de Objeto do utilizador LDAP" + +#: cps/templates/config_edit.html:262 +msgid "LDAP Server is OpenLDAP?" +msgstr "O Servidor LDAP é OpenLDAP?" + +#: cps/templates/config_edit.html:264 +msgid "Following Settings are Needed For User Import" +msgstr "As seguintes configurações são necessárias para a importação de utilizadores" + +#: cps/templates/config_edit.html:266 +msgid "LDAP Group Object Filter" +msgstr "Filtro de objetos do grupo LDAP" + +#: cps/templates/config_edit.html:270 +msgid "LDAP Group Name" +msgstr "Nome do grupo LDAP" + +#: cps/templates/config_edit.html:274 +msgid "LDAP Group Members Field" +msgstr "Campo de membros do grupo LDAP" + +#: cps/templates/config_edit.html:278 +msgid "LDAP Member User Filter Detection" +msgstr "LDAP deteção de filtro de utilizador membro LDAP" + +#: cps/templates/config_edit.html:280 +msgid "Autodetect" +msgstr "Autodetetar" + +#: cps/templates/config_edit.html:281 +msgid "Custom Filter" +msgstr "Filtro personalizado" + +#: cps/templates/config_edit.html:286 +msgid "LDAP Member User Filter" +msgstr "Filtro de utilizador Membro LDAP" + +#: cps/templates/config_edit.html:297 +#, python-format +msgid "Obtain %(provider)s OAuth Credential" +msgstr "Obter credenciais OAuth de %(provider)s" + +#: cps/templates/config_edit.html:300 +#, python-format +msgid "%(provider)s OAuth Client Id" +msgstr "ID do cliente OAuth de %(provider)s" + +#: cps/templates/config_edit.html:304 +#, python-format +msgid "%(provider)s OAuth Client Secret" +msgstr "Senha do cliente Oauth de %(provider)s" + +#: cps/templates/config_edit.html:320 +msgid "External binaries" +msgstr "Binários externos" + +#: cps/templates/config_edit.html:326 +msgid "Path to Calibre E-Book Converter" +msgstr "Caminho para o conversor de ebooks do Calibre" + +#: cps/templates/config_edit.html:334 +msgid "Calibre E-Book Converter Settings" +msgstr "Configurações do conversor de ebooks do Calibre" + +#: cps/templates/config_edit.html:337 +msgid "Path to Kepubify E-Book Converter" +msgstr "Caminho para o conversor de ebooks do Kepubify" + +#: cps/templates/config_edit.html:345 +msgid "Location of Unrar binary" +msgstr "Caminho para o binário Unrar" + +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Configurações do OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "Limitar tentativas de autenticação falhada" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "Proteção de sessão" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "Básica" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "Forte" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Política de senha do utilizador" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "Tamanho mínimo da senha" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "Exigir números" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "Exigir letras minúsculas" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "Exigir letras maiúsculas" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "Exigir caracteres especiais" + +#: cps/templates/config_view_edit.html:17 +msgid "View Configuration" +msgstr "Configuração de visualização" + +#: cps/templates/config_view_edit.html:32 +msgid "No. of Random Books to Display" +msgstr "Nº aleatório de livros exibir" + +#: cps/templates/config_view_edit.html:36 +msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" +msgstr "Nº de autores a exibir antes de esconder (0=Desativar Esconder)" + +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 +msgid "Theme" +msgstr "Tema" + +#: cps/templates/config_view_edit.html:42 +msgid "Standard Theme" +msgstr "Tema padrão" + +#: cps/templates/config_view_edit.html:43 +msgid "caliBlur! Dark Theme" +msgstr "Tema caliBlur! Escuro" + +#: cps/templates/config_view_edit.html:47 +msgid "Regular Expression for Ignoring Columns" +msgstr "Expressão regular para ignorar colunas" + +#: cps/templates/config_view_edit.html:51 +msgid "Link Read/Unread Status to Calibre Column" +msgstr "Ligar Lido/Não Lido à coluna Calibre" + +#: cps/templates/config_view_edit.html:60 +msgid "View Restrictions based on Calibre column" +msgstr "Exibir restrições com base na coluna Calibre" + +#: cps/templates/config_view_edit.html:69 +msgid "Regular Expression for Title Sorting" +msgstr "Expressão regular para ordenação de títulos" + +#: cps/templates/config_view_edit.html:80 +msgid "Default Settings for New Users" +msgstr "Configuração predefinida para novos utilizadores" + +#: cps/templates/config_view_edit.html:88 cps/templates/user_edit.html:96 +msgid "Admin User" +msgstr "Utilizador Admin" + +#: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 +msgid "Allow Downloads" +msgstr "Permitir descarregamentos" + +#: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 +msgid "Allow eBook Viewer" +msgstr "Permitir visualizador de eBook" + +#: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 +msgid "Allow Uploads" +msgstr "Permitir carregamentos" + +#: cps/templates/config_view_edit.html:106 cps/templates/user_edit.html:115 +msgid "Allow Edit" +msgstr "Permitir editar" + +#: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 +msgid "Allow Delete Books" +msgstr "Permitir apagar livros" + +#: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 +msgid "Allow Changing Password" +msgstr "Permitir alterar senha" + +#: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 +msgid "Allow Editing Public Shelves" +msgstr "Permitir editar estantes públicas" + +#: cps/templates/config_view_edit.html:123 +msgid "Default Language" +msgstr "Idioma predefinido" + +#: cps/templates/config_view_edit.html:131 +msgid "Default Visible Language of Books" +msgstr "Idioma predefinido para os livros visíveis" + +#: cps/templates/config_view_edit.html:147 +msgid "Default Visibilities for New Users" +msgstr "Visibilidade predefinida para novos utilizadores" + +#: cps/templates/config_view_edit.html:163 cps/templates/user_edit.html:84 +#: cps/templates/user_table.html:154 +msgid "Show Random Books in Detail View" +msgstr "Mostrar livros aleatoriamente em visualização de detalhes" + +#: cps/templates/config_view_edit.html:166 cps/templates/user_edit.html:87 +msgid "Add Allowed/Denied Tags" +msgstr "Adicionar etiquetas Permitidas/Negadas" + +#: cps/templates/config_view_edit.html:167 +msgid "Add Allowed/Denied custom column values" +msgstr "Adicionar valores permitidos/negados de coluna personalizada" + +#: cps/templates/detail.html:77 cps/templates/detail.html:91 +msgid "Read in Browser" +msgstr "Ler no Navegador" + +#: cps/templates/detail.html:100 cps/templates/detail.html:120 +msgid "Listen in Browser" +msgstr "Ouvir no Navegador" + +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 +#, python-format +msgid "Book %(index)s of %(range)s" +msgstr "Livro %(index)s de %(range)s" + +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 +msgid "Published" +msgstr "Publicado em" + +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 +msgid "Mark As Unread" +msgstr "Marcar como não Lido" + +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 +msgid "Mark As Read" +msgstr "Marcar como lido" + +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 +msgid "Read" +msgstr "Lido" + +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 +msgid "Restore from archive" +msgstr "Restaurar do ficheiro" + +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 +msgid "Add to archive" +msgstr "Adicionar ao ficheiro" + +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 +msgid "Archived" +msgstr "Arquivado" + +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 +msgid "Description:" +msgstr "Descrição:" + +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 +msgid "Add to shelf" +msgstr "Adicionar à estante" + +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 +#: cps/templates/search.html:22 +msgid "(Public)" +msgstr "(Público)" + +#: cps/templates/detail.html:339 +msgid "Edit Metadata" +msgstr "Editar metadados" + +#: cps/templates/email_edit.html:13 +msgid "Email Account Type" +msgstr "Escolha o tipo do servidor" + +#: cps/templates/email_edit.html:15 +#, fuzzy +msgid "Standard Email Account" +msgstr "Usar conta de email padrão" + +#: cps/templates/email_edit.html:16 +#, fuzzy +msgid "Gmail Account" +msgstr "Conta Gmail" + +#: cps/templates/email_edit.html:22 +msgid "Setup Gmail Account" +msgstr "Configurar conta Gmail" + +#: cps/templates/email_edit.html:24 +msgid "Revoke Gmail Access" +msgstr "Revogar acesso ao Gmail" + +#: cps/templates/email_edit.html:42 +msgid "STARTTLS" +msgstr "STARTTLS" + +#: cps/templates/email_edit.html:43 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: cps/templates/email_edit.html:51 +msgid "SMTP Password" +msgstr "Senha SMTP" + +#: cps/templates/email_edit.html:58 +msgid "Attachment Size Limit" +msgstr "Limite de tamanho do anexo" + +#: cps/templates/email_edit.html:66 +#, fuzzy +msgid "Save and Send Test Email" +msgstr "Guardar e enviar email de teste" + +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 +#: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 +msgid "Back" +msgstr "Voltar" + +#: cps/templates/email_edit.html:74 +msgid "Allowed Domains (Whitelist)" +msgstr "Domínios permitidos (Lista Branca)" + +#: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 +msgid "Add Domain" +msgstr "Adicionar domínio" + +#: cps/templates/email_edit.html:81 cps/templates/email_edit.html:108 +#: cps/templates/user_table.html:27 +msgid "Add" +msgstr "Adicionar" + +#: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 +msgid "Enter domainname" +msgstr "Digite o nome do domínio" + +#: cps/templates/email_edit.html:92 +msgid "Denied Domains (Blacklist)" +msgstr "Domínios ngados (Lista Negra)" + +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 +msgid "Next" +msgstr "Seguinte" + +#: cps/templates/generate_kobo_auth_url.html:6 +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Abra o ficheiro .kobo/Kobo/Kobo eReader.conf em um editor de texto e adicione (ou edite):" + +#: cps/templates/generate_kobo_auth_url.html:11 +msgid "Kobo Token:" +msgstr "Token Kobo:" + +#: cps/templates/grid.html:21 +msgid "List" +msgstr "Lista" + +#: cps/templates/http_error.html:34 +msgid "Calibre-Web Instance is unconfigured, please contact your administrator" +msgstr "Instancia do Calibre-Web não configurada. Por favor, contacte o seu administrador" + +#: cps/templates/http_error.html:44 +msgid "Create Issue" +msgstr "Criar ocorrência" + +#: cps/templates/http_error.html:51 +msgid "Return to Home" +msgstr "Voltar para entrada" + +#: cps/templates/http_error.html:53 +msgid "Logout User" +msgstr "Terminar sessão" + +#: cps/templates/index.html:71 +msgid "Sort ascending according to download count" +msgstr "Ordenar por ordem crescente de acordo com a quantidade de descarregamentos" + +#: cps/templates/index.html:72 +msgid "Sort descending according to download count" +msgstr "Ordenar por ordem decrescente de acordo com a quantidade de descarregamentos" + +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 +msgid "Sort authors in alphabetical order" +msgstr "Ordenar autores por ordem alfabética" + +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 +msgid "Sort authors in reverse alphabetical order" +msgstr "Ordenar autores por ordem alfabética inversa" + +#: cps/templates/index.html:83 +msgid "Sort ascending according to series index" +msgstr "Ordenar em ordem ascendente de acordo com o índice da série" + +#: cps/templates/index.html:84 +msgid "Sort descending according to series index" +msgstr "Ordenação em ordem descendente de acordo com o índice de série" + +#: cps/templates/index.xml:7 +msgid "Start" +msgstr "Início" + +#: cps/templates/index.xml:19 +msgid "Alphabetical Books" +msgstr "Livros alfabeticamente" + +#: cps/templates/index.xml:23 +msgid "Books sorted alphabetically" +msgstr "Livros ordenados alfabeticamente" + +#: cps/templates/index.xml:30 +msgid "Popular publications from this catalog based on Downloads." +msgstr "Publicações populares deste catálogo com base no número de descarregamentos." + +#: cps/templates/index.xml:37 +msgid "Popular publications from this catalog based on Rating." +msgstr "Publicações populares deste catálogo com base nas pontuações." + +#: cps/templates/index.xml:40 +msgid "Recently added Books" +msgstr "Livros recentemente adicionados" + +#: cps/templates/index.xml:44 +msgid "The latest Books" +msgstr "Os livros mais recentes" + +#: cps/templates/index.xml:47 +msgid "Random Books" +msgstr "Livros aleatórios" + +#: cps/templates/index.xml:74 +msgid "Books ordered by Author" +msgstr "Livros ordenados por autor" + +#: cps/templates/index.xml:81 +msgid "Books ordered by publisher" +msgstr "Livros ordenados por editora" + +#: cps/templates/index.xml:88 +msgid "Books ordered by category" +msgstr "Livros ordenados por categoria" + +#: cps/templates/index.xml:95 +msgid "Books ordered by series" +msgstr "Livros ordenados por série" + +#: cps/templates/index.xml:102 +msgid "Books ordered by Languages" +msgstr "Livros ordenados por idiomas" + +#: cps/templates/index.xml:109 +msgid "Books ordered by Rating" +msgstr "Livros ordenados por pontuação" + +#: cps/templates/index.xml:117 +msgid "Books ordered by file formats" +msgstr "Livros ordenados por formatos de ficheiro" + +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 +msgid "Shelves" +msgstr "Estantes" + +#: cps/templates/index.xml:124 +msgid "Books organized in shelves" +msgstr "Livros organizados em estantes" + +#: cps/templates/layout.html:26 cps/templates/login.html:30 +msgid "Home" +msgstr "Entrada" + +#: cps/templates/layout.html:32 +msgid "Toggle Navigation" +msgstr "Alternar navegação" + +#: cps/templates/layout.html:47 +msgid "Search Library" +msgstr "Pesquisar na biblioteca" + +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Conta" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Sair" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "A carregar..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Erro" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Carregamento concluído, a processar. Por favor, aguarde ..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Configurações" + +#: cps/templates/layout.html:135 +msgid "Please do not refresh the page" +msgstr "Por favor, não refresque a página" + +#: cps/templates/layout.html:145 +msgid "Browse" +msgstr "Navegar" + +#: cps/templates/layout.html:158 cps/templates/stats.html:3 +msgid "About" +msgstr "Sobre" + +#: cps/templates/layout.html:172 +msgid "Previous" +msgstr "Anterior" + +#: cps/templates/layout.html:199 +msgid "Book Details" +msgstr "Detalhes do livro" + +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Grelha" + +#: cps/templates/login.html:18 +msgid "Remember Me" +msgstr "Memorizar-me" + +#: cps/templates/login.html:23 +msgid "Forgot Password?" +msgstr "Esqueceu-se da senha?" + +#: cps/templates/login.html:34 +msgid "Log in with Magic Link" +msgstr "Autentique-se com o Magic Link" + +#: cps/templates/logviewer.html:6 +msgid "Show Calibre-Web Log: " +msgstr "Mostrar historial Calibre-Web: " + +#: cps/templates/logviewer.html:8 +msgid "Calibre-Web Log: " +msgstr "Historial Calibre-Web: " + +#: cps/templates/logviewer.html:8 +msgid "Stream output, can't be displayed" +msgstr "Saída do fluxo, não pode ser exibida" + +#: cps/templates/logviewer.html:12 +msgid "Show Access Log: " +msgstr "Mostrar historial de acesso: " + +#: cps/templates/logviewer.html:18 +msgid "Download Calibre-Web Log" +msgstr "Descarregar historial Calibre-Web" + +#: cps/templates/logviewer.html:21 +msgid "Download Access Log" +msgstr "Descarregar historial de acessos" + +#: cps/templates/modal_dialogs.html:6 +msgid "Select Allowed/Denied Tags" +msgstr "Selecionar etiquetas permitidas/negadas" + +#: cps/templates/modal_dialogs.html:7 +msgid "Select Allowed/Denied Custom Column Values" +msgstr "Selecionar valores permitidos/negados para coluna personalizada" + +#: cps/templates/modal_dialogs.html:8 +msgid "Select Allowed/Denied Tags of User" +msgstr "Selecionar etiquetas de utilizador permitidas/negadas" + +#: cps/templates/modal_dialogs.html:9 +msgid "Select Allowed/Denied Custom Column Values of User" +msgstr "Selecionar valores de utilizador permitidos/negados para coluna personalizada" + +#: cps/templates/modal_dialogs.html:15 +msgid "Enter Tag" +msgstr "Digite a etiqueta" + +#: cps/templates/modal_dialogs.html:24 +msgid "Add View Restriction" +msgstr "Adicionar restrição de visualização" + +#: cps/templates/modal_dialogs.html:50 +msgid "This book format will be permanently erased from database" +msgstr "Este formato de livro será apagado permanentemente da base de dados" + +#: cps/templates/modal_dialogs.html:51 +msgid "This book will be permanently erased from database" +msgstr "Este livro será apagado permanentemente da base de dados" + +#: cps/templates/modal_dialogs.html:52 +msgid "and hard disk" +msgstr "e disco rígido" + +#: cps/templates/modal_dialogs.html:56 +msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." +msgstr "Nota importante Kobo: os livros apagados continuarão existindo em qualquer dispositivo Kobo que esteja emparelhado." + +#: cps/templates/modal_dialogs.html:57 +msgid "Books must first be archived and the device synced before a book can safely be deleted." +msgstr "Os livros devem primeiro ser arquivados e o dispositivo deve ser sincronizado antes que um livro possa ser apagado com segurança." + +#: cps/templates/modal_dialogs.html:76 +msgid "Choose File Location" +msgstr "Escolher a localização do ficheiro" + +#: cps/templates/modal_dialogs.html:82 +msgid "type" +msgstr "tipo" + +#: cps/templates/modal_dialogs.html:83 +msgid "name" +msgstr "nome" + +#: cps/templates/modal_dialogs.html:84 +msgid "size" +msgstr "tamanho" + +#: cps/templates/modal_dialogs.html:90 +msgid "Parent Directory" +msgstr "Pasta superior" + +#: cps/templates/modal_dialogs.html:98 +msgid "Select" +msgstr "Selecionar" + +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 +msgid "Ok" +msgstr "Ok" + +#: cps/templates/osd.xml:5 +msgid "Calibre-Web eBook Catalog" +msgstr "Catálogo de ebooks Calibre-Web" + +#: cps/templates/read.html:6 +msgid "epub Reader" +msgstr "leitor de epub" + +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Claro" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Escuro" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "Sépia" + +#: cps/templates/read.html:84 +msgid "Black" +msgstr "Preto" + +#: cps/templates/read.html:88 +msgid "Reflow text when sidebars are open." +msgstr "Refluir o texto quando as barras laterais estiverem abertas." + +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "Tamanhos de letra" + +#: cps/templates/readcbr.html:8 +msgid "Comic Reader" +msgstr "Leitor de banda desenhada" + +#: cps/templates/readcbr.html:75 +msgid "Keyboard Shortcuts" +msgstr "Atalhos de teclado" + +#: cps/templates/readcbr.html:78 +msgid "Previous Page" +msgstr "Página anterior" + +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 +msgid "Next Page" +msgstr "Página seguinte" + +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "Exibição de página única" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "Exibição de tira única" + +#: cps/templates/readcbr.html:82 +msgid "Scale to Best" +msgstr "Dimensionar para melhor" + +#: cps/templates/readcbr.html:83 +msgid "Scale to Width" +msgstr "Dimensionar para largura" + +#: cps/templates/readcbr.html:84 +msgid "Scale to Height" +msgstr "Dimensionar para altura" + +#: cps/templates/readcbr.html:85 +msgid "Scale to Native" +msgstr "Dimensionar para nativo" + +#: cps/templates/readcbr.html:86 +msgid "Rotate Right" +msgstr "Girar para direita" + +#: cps/templates/readcbr.html:87 +msgid "Rotate Left" +msgstr "Girar para esquerda" + +#: cps/templates/readcbr.html:88 +msgid "Flip Image" +msgstr "Inverter imagem" + +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Exibir" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Página única" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "Tira longa" + +#: cps/templates/readcbr.html:119 +msgid "Scale" +msgstr "Dimensionar" + +#: cps/templates/readcbr.html:122 +msgid "Best" +msgstr "Melhor" + +#: cps/templates/readcbr.html:123 +msgid "Width" +msgstr "Largura" + +#: cps/templates/readcbr.html:124 +msgid "Height" +msgstr "Altura" + +#: cps/templates/readcbr.html:125 +msgid "Native" +msgstr "Nativo" + +#: cps/templates/readcbr.html:130 +msgid "Rotate" +msgstr "Rodar" + +#: cps/templates/readcbr.html:141 +msgid "Flip" +msgstr "Inverter" + +#: cps/templates/readcbr.html:144 +msgid "Horizontal" +msgstr "Horizontal" + +#: cps/templates/readcbr.html:145 +msgid "Vertical" +msgstr "Vertical" + +#: cps/templates/readcbr.html:150 +msgid "Direction" +msgstr "Direção" + +#: cps/templates/readcbr.html:153 +msgid "Left to Right" +msgstr "Esquerda para a direita" + +#: cps/templates/readcbr.html:154 +msgid "Right to Left" +msgstr "Direita para a esquerda" + +#: cps/templates/readcbr.html:162 +msgid "Reset to Top" +msgstr "" + +#: cps/templates/readcbr.html:163 +msgid "Remember Position" +msgstr "" + +#: cps/templates/readcbr.html:168 +msgid "Scrollbar" +msgstr "Barra de rolagem" + +#: cps/templates/readcbr.html:171 +msgid "Show" +msgstr "Mostrar" + +#: cps/templates/readcbr.html:172 +msgid "Hide" +msgstr "Esconder" + +#: cps/templates/readdjvu.html:5 +msgid "DJVU Reader" +msgstr "Leitor de DJVU" + +#: cps/templates/readpdf.html:32 +msgid "PDF Reader" +msgstr "Leitor de PDF" + +#: cps/templates/readtxt.html:6 +msgid "txt Reader" +msgstr "Leitor de TXT" + +#: cps/templates/register.html:4 +msgid "Register New Account" +msgstr "Criar nova conta" + +#: cps/templates/register.html:10 +msgid "Choose a username" +msgstr "Escolher um nome de utilizador" + +#: cps/templates/register.html:15 +msgid "Your Email" +msgstr "O seu endereço de email" + +#: cps/templates/remote_login.html:5 +msgid "Magic Link - Authorise New Device" +msgstr "Magic Link - Autorizar novo dispositivo" + +#: cps/templates/remote_login.html:7 +msgid "On another device, login and visit:" +msgstr "Noutro dispositivo, autentique-se e visite:" + +#: cps/templates/remote_login.html:11 +msgid "Once verified, you will automatically be logged in on this device." +msgstr "Uma vez verificado, você será automaticamente ligado a este dispositivo." + +#: cps/templates/remote_login.html:14 +msgid "This verification link will expire in 10 minutes." +msgstr "Esta ligação de verificação irá expirar em 10 minutos." + +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Gerar miniaturas para capa de série" + +#: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "Nenhum resultado encontrado" + +#: cps/templates/search.html:7 +msgid "Search Term:" +msgstr "Termo de pesquisa:" + +#: cps/templates/search.html:9 +msgid "Results for:" +msgstr "Resultados sobre:" + +#: cps/templates/search_form.html:21 +msgid "Published Date From" +msgstr "Data de publicação de" + +#: cps/templates/search_form.html:31 +msgid "Published Date To" +msgstr "Data de publicação até" + +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 +msgid "Exclude Tags" +msgstr "Excluir etiquetas" + +#: cps/templates/search_form.html:78 +msgid "Exclude Series" +msgstr "Excluir série" + +#: cps/templates/search_form.html:96 +msgid "Exclude Shelves" +msgstr "Excluir estante" + +#: cps/templates/search_form.html:116 +msgid "Exclude Languages" +msgstr "Excluir idiomas" + +#: cps/templates/search_form.html:127 +msgid "Extensions" +msgstr "Extensões" + +#: cps/templates/search_form.html:135 +msgid "Exclude Extensions" +msgstr "Excluir extensões" + +#: cps/templates/search_form.html:145 +msgid "Rating Above" +msgstr "Pontuação acima" + +#: cps/templates/search_form.html:149 +msgid "Rating Below" +msgstr "Pontuação abaixo" + +#: cps/templates/search_form.html:181 +msgid "From:" +msgstr "De:" + +#: cps/templates/search_form.html:191 +msgid "To:" +msgstr "Para:" + +#: cps/templates/shelf.html:13 +msgid "Delete this Shelf" +msgstr "Apagar esta estante" + +#: cps/templates/shelf.html:14 +msgid "Edit Shelf Properties" +msgstr "Editar propriedades da estante" + +#: cps/templates/shelf.html:17 +msgid "Arrange books manually" +msgstr "Organizar livros manualmente" + +#: cps/templates/shelf.html:18 +msgid "Disable Change order" +msgstr "Desativar alterar ordenação" + +#: cps/templates/shelf.html:18 +msgid "Enable Change order" +msgstr "Ativar alterar ordenação" + +#: cps/templates/shelf_edit.html:14 +msgid "Share with Everyone" +msgstr "Partilhar com todos" + +#: cps/templates/shelf_edit.html:21 +msgid "Sync this shelf with Kobo device" +msgstr "sincronizar esta Estante com o Dispositivo Kobo" + +#: cps/templates/shelf_order.html:5 +msgid "Drag to Rearrange Order" +msgstr "Arrastar para reordenar" + +#: cps/templates/shelf_order.html:33 +msgid "Hidden Book" +msgstr "Livro oculto" + +#: cps/templates/stats.html:7 +msgid "Library Statistics" +msgstr "Estatísticas da biblioteca" + +#: cps/templates/stats.html:12 +msgid "Books in this Library" +msgstr "Livros nesta biblioteca" + +#: cps/templates/stats.html:16 +msgid "Authors in this Library" +msgstr "Autores nesta biblioteca" + +#: cps/templates/stats.html:20 +msgid "Categories in this Library" +msgstr "Categorias nesta biblioteca" + +#: cps/templates/stats.html:24 +msgid "Series in this Library" +msgstr "Séries nesta biblioteca" + +#: cps/templates/stats.html:29 +msgid "System Statistics" +msgstr "Estatísticas do sistema" + +#: cps/templates/stats.html:33 +msgid "Program" +msgstr "Programa" + +#: cps/templates/stats.html:34 +msgid "Installed Version" +msgstr "Versão instalada" + +#: cps/templates/tasks.html:12 +msgid "User" +msgstr "Utilizador" + +#: cps/templates/tasks.html:14 +msgid "Task" +msgstr "Tarefa" + +#: cps/templates/tasks.html:15 +msgid "Status" +msgstr "Estado" + +#: cps/templates/tasks.html:16 +msgid "Progress" +msgstr "Progresso" + +#: cps/templates/tasks.html:17 +msgid "Run Time" +msgstr "Tempo de execução" + +#: cps/templates/tasks.html:20 +msgid "Actions" +msgstr "Ações" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +msgstr "Esta tarefa será cancelada. Qualquer progresso feito por esta tarefa será guardado." + +#: cps/templates/tasks.html:41 +msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." +msgstr "Se esta for uma tarefa agendada, ela será executada novamente durante o próximo horário agendado." + +#: cps/templates/user_edit.html:20 +msgid "Reset user Password" +msgstr "Redefinir senha do utilizador" + +#: cps/templates/user_edit.html:43 +msgid "Language of Books" +msgstr "Idioma dos livros" + +#: cps/templates/user_edit.html:54 +msgid "OAuth Settings" +msgstr "Configurações do OAuth" + +#: cps/templates/user_edit.html:56 +msgid "Link" +msgstr "Ligação" + +#: cps/templates/user_edit.html:58 +msgid "Unlink" +msgstr "Desvincular" + +#: cps/templates/user_edit.html:64 +msgid "Kobo Sync Token" +msgstr "Token de sincronização Kobo" + +#: cps/templates/user_edit.html:66 +msgid "Create/View" +msgstr "Criar/Ver" + +#: cps/templates/user_edit.html:70 +msgid "Force full kobo sync" +msgstr "Forçar sincronização completa Kobo" + +#: cps/templates/user_edit.html:88 +msgid "Add allowed/Denied Custom Column Values" +msgstr "Adicionar valores permitidos/negados da coluna personalizada" + +#: cps/templates/user_edit.html:137 +msgid "Sync only books in selected shelves with Kobo" +msgstr "Sincronizar com Kobo apenas livros em estantes selecionadas" + +#: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 +msgid "Delete User" +msgstr "Apagar utilizador" + +#: cps/templates/user_edit.html:159 +msgid "Generate Kobo Auth URL" +msgstr "Gerar URL de autenticação Kobo" + +#: cps/templates/user_table.html:80 cps/templates/user_table.html:103 +msgid "Select..." +msgstr "Selecionar..." + +#: cps/templates/user_table.html:131 +msgid "Edit User" +msgstr "Editar utilizador" + +#: cps/templates/user_table.html:134 +msgid "Enter Username" +msgstr "Escolha um nome de utilizador" + +#: cps/templates/user_table.html:135 +#, fuzzy +msgid "Enter Email" +msgstr "Email de teste" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "Enter eReader Email" +msgstr "Enviar para o endereço de email do dispositivo de leitura" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "eReader Email" +msgstr "Email do dispositivo de leitura" + +#: cps/templates/user_table.html:137 +msgid "Locale" +msgstr "Idioma" + +#: cps/templates/user_table.html:138 +msgid "Visible Book Languages" +msgstr "Idiomas de livros visíveis" + +#: cps/templates/user_table.html:139 +msgid "Edit Allowed Tags" +msgstr "Editar etiquetas permitidas" + +#: cps/templates/user_table.html:139 +msgid "Allowed Tags" +msgstr "Etiquetas permitidas" + +#: cps/templates/user_table.html:140 +msgid "Edit Denied Tags" +msgstr "Editar etiquetas não permitidas" + +#: cps/templates/user_table.html:140 +msgid "Denied Tags" +msgstr "Etiquetas não permitidas" + +#: cps/templates/user_table.html:141 +msgid "Edit Allowed Column Values" +msgstr "Editar valores de coluna permitidos" + +#: cps/templates/user_table.html:141 +msgid "Allowed Column Values" +msgstr "Valores de coluna permitidos" + +#: cps/templates/user_table.html:142 +msgid "Edit Denied Column Values" +msgstr "Editar valores de coluna não permitidos" + +#: cps/templates/user_table.html:142 +msgid "Denied Column Values" +msgstr "Valores de coluna não permitidos" + +#: cps/templates/user_table.html:144 +msgid "Change Password" +msgstr "Alterar senha" + +#: cps/templates/user_table.html:147 +msgid "View" +msgstr "Ver" + +#: cps/templates/user_table.html:150 +msgid "Edit Public Shelves" +msgstr "Editar estantes públicas" + +#: cps/templates/user_table.html:152 +msgid "Sync selected Shelves with Kobo" +msgstr "Sincronizar com Kobo as estantes selecionadas" + +#: cps/templates/user_table.html:156 +#, fuzzy +msgid "Show Read/Unread Section" +msgstr "Mostrar secção de lidos/não lidos" + diff --git a/cps/translations/pt_BR/LC_MESSAGES/messages.mo b/cps/translations/pt_BR/LC_MESSAGES/messages.mo index 173d51b4..281a704f 100644 Binary files a/cps/translations/pt_BR/LC_MESSAGES/messages.mo and b/cps/translations/pt_BR/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/pt_BR/LC_MESSAGES/messages.po b/cps/translations/pt_BR/LC_MESSAGES/messages.po index 10ddb0a8..84a0a7f3 100644 --- a/cps/translations/pt_BR/LC_MESSAGES/messages.po +++ b/cps/translations/pt_BR/LC_MESSAGES/messages.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: br\n" @@ -13,487 +13,497 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Estatísticas" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Servidor reiniciado, por favor recarregue a página" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Executando o desligamento do servidor, por favor feche a janela" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Reconexão bem-sucedida" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Comando desconhecido" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Livro enfileirado com sucesso para envio para %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "E-mail de teste enfileirado para envio para %(email)s, verifique o resultado em Tarefas" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Desconhecido" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Página de Administração" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Configuração Básica" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Configuração de UI" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Editar Usuários" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Todos" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Usuário não encontrado" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} usuário(s) deletedos com sucesso" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Mostrar Tudo" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Requisição Malformada" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Nome do Convidado não pode ser alterado" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Convidado não pode ter esta função" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Nenhum usuário administrador restante, impossível remover a função de administrador" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" -msgstr "Valor não pode ser Verdadeiro ou Falso" +msgstr "Valor tem de ser Verdadeiro ou Falso" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Função Inválida" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Convidado não pode ter esta visão" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Visão Inválida" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "O idioma do Convidado é detectado automaticamente e não pode ser alterado" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Nenhum Idioma Válido Fornecido" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Nenhum Idioma do Livro Válido Fornecido" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parametro não encontrado" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Coluna Lido Inválida" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Coluna Restrito Inválida" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Configuração do Calibre-Web atualizada" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Você realmente quer apagar a Kobo Token?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Você realmente quer apagar este domínio?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Você realmente quer apagar este usuário?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Tem certeza que quer apagar essa estante?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Tem certeza que quer alterar o idioma do(s) usuário(s) selecionados?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "Tem certeza que quer alterar os idiomas de livros visíveis par o usuário(s) selecionado(s)?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Tem certeza que quer alterar a função selecionada para o(s) usuário(s) selecionado(s)?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Tem certeza que quer alterar as restriçõeo selecionada para o(s) usuário(s) selecionado(s)?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "Tem certeza de que quer alterar as restrições de visibilidade selecionadas para os usuários selecionados?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Tem certeza de que quer alterar o comportamento de sincronização da estante para o usuário selecionado?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "Tem certeza que queres alterar a localização da biblioteca Calibre?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "O Calibre-Web buscará por Capas atualizadas e atualizará as Miniaturas de Capas, isso pode demorar um pouco" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "Tem certeza de que deseja apagar o banco de dados de sincronização do Calibre-Web para forçar uma sincronização completa com seu Kobo Reader?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Negar" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Permitir" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} entradas de sincronização deletadas" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Tag não encontrada" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Ação Inválida" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json Não Está Configurado para Aplicação Web" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "A localização do arquivo de log não é válida, digite o caminho correto" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "A localização do arquivo de log de acesso não é válida, digite o caminho correto" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Digite um provedor LDAP, porta, DN e identificador de objeto do usuário" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "Por favor, digite uma Conta de Serviço LDAP e Senha" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "Por favor, digite uma Conta de Serviço LDAP" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "O filtro de objeto de grupo LDAP precisa ter um identificador de formato \"%s\"" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Filtro de objeto de grupo LDAP tem parênteses incomparáveis" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "O filtro de objeto de usuário LDAP precisa ter um identificador de formato \"%s\"" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Filtro de objeto de usuário LDAP tem parênteses incomparáveis" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "O filtro de usuário membro do LDAP precisa ter um identificador de formato \"%s\"" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "Filtro de usuário de membro LDAP tem parênteses incomparáveis" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "Localização de LDAP CACertificate, Certificados ou Key Inválida, Insira o Caminho Correto" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Adicionar novo usuário" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Adicionar Novo Usuário" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Editar configurações do servidor de e-mail" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "Verificação da Conta Gmail com Sucesso" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Erro de banco de dados: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "E-mail de teste enfileirado para envio para %(email)s, verifique o resultado em Tarefas" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Ocorreu um erro ao enviar o e-mail de teste: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Por favor, configure seu endereço de e-mail primeiro..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Atualização das configurações do servidor de e-mail" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "Editar configurações de tarefas agendadas" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "Hora de início inválida para a tarefa especificada" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "Duração inválida para a tarefa especificada" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "Configurações de tarefas agendadas atualizadas" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Ocorreu um erro desconhecido. Por favor, tente novamente mais tarde." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "Settings DB não é gravável" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Editar Usuário %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Senha do usuário %(user)s redefinida" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Por favor, configure primeiro as configurações de correio SMTP..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visualizador do Log" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Solicitação de pacote de atualização" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Baixando pacote de atualização" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Descompactando pacote de atualização" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Substituindo arquivos" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "As conexões à base de dados estão fechadas" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Parando servidor" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Atualização concluída, pressione okay e recarregue a página" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Atualização falhou:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Erro HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Erro de conexão" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Tempo limite durante o estabelecimento da conexão" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Erro geral" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "Arquivo de atualização não pôde ser salvo no diretório temporário" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "Arquivos não puderam ser substituídos durante a atualização" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "Falha ao extrair pelo menos um usuário LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Falha ao criar pelo menos um usuário LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Erro: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Erro: Nenhum usuário retornado na resposta do servidor LDAP" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "No mínimo um usuário LDAP não encontrado no banco de dados" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} Usuário Importado com Sucesso" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "A localização do banco de dados não é válida, digite o caminho correto" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "DB não é gravável" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "Localização do Keyfile Inválida, Insira o Caminho Correto" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "Localização do Certfile Inválida, Insira o Caminho Correto" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "Configurações do Banco de Dados Atualizada" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "Configuração do Banco de Dados" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Por favor, preencha todos os campos!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "O e-mail não é de um domínio válido" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Adicionar novo usuário" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Usuário '%(user)s' criado" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "Encontrada uma conta existente para este endereço de e-mail ou apelido." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Usuário '%(nick)s' excluído" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Impossível excluir Convidado" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Nenhum usuário administrador restante, não é possível apagar o usuário" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Usuário '%(nick)s' atualizado" @@ -506,122 +516,122 @@ msgstr "não instalado" msgid "Execution permissions missing" msgstr "Faltam as permissões de execução" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "A Coluna Personalizada No.%(column)d não existe no banco de dados do calibre" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Nenhum" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Oops! O Livro selecionado não está disponível. O arquivo não existe ou não é acessível" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "Usuário não tem permissão para fazer upload da capa" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Os identificadores não diferenciam maiúsculas de minúsculas, substituindo o identificador antigo" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadados atualizados com sucesso" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "Erro ao editar o livro: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Arquivo %(file)s enviado" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Formato de origem ou destino para conversão ausente" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Livro enfileirado com sucesso para conversão em %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Ocorreu um erro ao converter este livro: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "O livro carregado provavelmente existe na biblioteca, considere alterar antes de carregar novo: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s não é um idioma válido" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "A extensão de arquivo '%(ext)s' não pode ser enviada para este servidor" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "O arquivo a ser carregado deve ter uma extensão" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "O arquivo %(filename)s não pôde ser salvo no diretório temporário" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Falha ao mover arquivo de capa %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Formato do Livro Apagado com Sucesso" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Livro Apagado com Sucesso" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "Você não tem permissão para apagar livros" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "editar metadados" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s não é um número válido, ignorando" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "Usuário não tem direitos para fazer upload de formatos de arquivo adicionais" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Falha ao criar o caminho %(path)s (Permission denied)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Falha ao armazenar o arquivo %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Formato de arquivo %(ext)s adicionado a %(book)s" @@ -634,180 +644,187 @@ msgstr "Configuração do Google Drive não concluída, tente desativar e ativar msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "O domínio Callback não foi verificado, por favor siga os passos para verificar o domínio no console do desenvolvedor do google" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "Formato %(format)s não encontrado para o id do livro: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s não encontrado no Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s não encontrado: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 -msgid "Send to E-Reader" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" msgstr "Enviar para E-Reader" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Este e-mail foi enviado via Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "E-mail de teste do Calibre-Web" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "E-mail de teste" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Comece a usar o calibre-web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "E-mail de registro do usuário: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 -#, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +#: cps/helper.py:149 cps/helper.py:155 +#, fuzzy, python-format +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Converter %(orig)s em %(format)s e enviar para E-Reader" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 -#, python-format -msgid "Send %(format)s to E-Reader" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Enviar %(format)s para o E-Reader" -#: cps/helper.py:225 cps/tasks/convert.py:92 -#, python-format -msgid "%(book)s send to E-Reader" +#: cps/helper.py:222 +#, fuzzy, python-format +msgid "%(book)s send to eReader" msgstr "%(book)s enviado para E-Reader" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "O arquivo solicitado não pôde ser lido. Talvez permissões erradas?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "Status Lido não pode ser alterado: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "A exclusão da pasta de livros do livro %(id)s falhou, o caminho tem subpastas: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Falha ao excluir livro %(id)s: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Excluindo livro %(id)s somente do banco de dados, caminho do livro inválido: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Renomear autor de: '%(src)s' para '%(dest)s' falhou com o erro: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Arquivo %(file)s não encontrado no Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Renomear título de: '%(src)s' para '%(dest)s' falhou com o erro: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "Erro ao renomear arquivo no caminho: {}" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Caminho do livro %(path)s não encontrado no Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "Encontrada uma conta existente para este endereço de e-mail." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Este nome de usuário já está registrado" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Formato de endereço de e-mail inválido" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "O módulo Python 'advocate' não está instalado, mas é necessário para uploads de capa" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Erro ao Baixar a capa" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Erro de Formato da Capa" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "Você não tem permissão para acessar localhost ou a rede local para uploads de capa" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Falha em criar caminho para a capa" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "O arquivo de capa não é um arquivo de imagem válido, ou não pôde ser armazenado" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Apenas arquivos jpg/jpeg/png/webp/bmp são suportados como arquivos de capa" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "Conteúdo do arquivo de capa inválido" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Apenas arquivos jpg/jpeg são suportados como arquivos de capa" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Binário Unrar não encontrado" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Erro excecutando UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" -msgstr "Descubra" +msgstr "Capa" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Por favor, acesse o calibre-web de um host não local para obter um api_endpoint válido para o dispositivo kobo" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Configuração Kobo" @@ -816,9 +833,9 @@ msgstr "Configuração Kobo" msgid "Register with %(provider)s" msgstr "Registre-se com %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "agora você está logado como: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -877,12 +894,13 @@ msgstr "Erro no Google Oauth, tente novamente mais tarde." msgid "Google Oauth error: {}" msgstr "Erro no Oauth do Google: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} Estrelas" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Login" @@ -898,149 +916,158 @@ msgstr "O Token expirou" msgid "Success! Please return to your device" msgstr "Sucesso! Por favor, volte ao seu aparelho" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Livros" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Mostrar livros recentes" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Livros Quentes" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Mostrar Livros Quentes" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Livros Baixados" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Mostrar Livros Baixados" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Livros Mais Bem Avaliados" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Mostrar Livros Mais Bem Avaliados" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Livros Lidos" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Mostrar lido e não lido" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Livros Não Lidos" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Mostrar Não Lidos" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Descubra" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Mostrar Livros Aleatórios" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Categorias" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" -msgstr "Mostrar seleção de categoria" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" +msgstr "Mostrar seção de categoria" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Série" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" -msgstr "Mostrar seleção de séries" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" +msgstr "Mostrar seção de séries" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Autores" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" -msgstr "Mostrar seleção de autor" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" +msgstr "Mostrar seção de autor" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Editoras" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" -msgstr "Mostrar seleção de editoras" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" +msgstr "Mostrar seção de editoras" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Idiomas" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" -msgstr "Mostrar seleção de idioma" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" +msgstr "Mostrar seção de idioma" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Avaliações" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" -msgstr "Mostrar seleção de avaliações" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" +msgstr "Mostrar seção de avaliações" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Formatos de arquivo" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" -msgstr "Mostrar seleção de formatos de arquivo" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" +msgstr "Mostrar seção de formatos de arquivo" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Livros Arquivados" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Mostrar livros arquivados" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Lista de Livros" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Mostrar Lista de Livros" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Pesquisar" @@ -1063,15 +1090,15 @@ msgid "Rating >= %(rating)s" msgstr "Avaliação >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Status de leitura = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "Erro na pesquisa de colunas personalizadas, reinicie o Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Pesquisa Avançada" @@ -1121,7 +1148,7 @@ msgstr "O livro foi removido da estante: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "Desculpe, você não tem permissão para remover um livro desta estante" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Crie uma Estante" @@ -1146,73 +1173,73 @@ msgstr "Estante Apagada com Sucesso" msgid "Change order of Shelf: '%(name)s'" msgstr "Alterar ordem da Estante: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "Desculpe, você não tem permissão para criar uma estante pública" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Estante %(title)s criada" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Estante %(title)s alterada" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Houve um erro" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Já existe uma estante pública com o nome '%(title)s' ." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Já existe uma estante privada com o nome'%(title)s' ." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Estante: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Erro ao abrir estante. A estante não existe ou não está acessível" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Tarefas" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Aguardando" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Falha" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Iniciado" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Concluído" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "Terminado" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "Cancelado" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Status Desconhecido" @@ -1245,146 +1272,185 @@ msgstr "Uma nova atualização está disponível. Clique no botão abaixo para a msgid "No release information available" msgstr "Não há informações de lançamento disponíveis" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Descobrir (Livros Aleatórios)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Livros Quentess (Mais Baixados)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Livros baixados por %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Autor: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Editora: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Série: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "Avaliação: Nenhuma" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Avaliação: %(rating)s estrelas" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Formato do arquivo: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Categoria: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Idioma: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Downloads" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Lista de Avaliações" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Lista de formatos de arquivo" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Livro enfileirado com sucesso para envio para %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Por favor, configure primeiro as configurações de correio SMTP..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Livro enfileirado com sucesso para envio para %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Ops! Ocorreu um erro ao enviar este livro: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Por favor, atualize seu perfil com um endereço de e-mail Envie Para o Kindle válido." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "O servidor de E-Mail não está configurado, por favor contacte o seu administrador!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Registe-se" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "O servidor de E-Mail não está configurado, por favor contacte o seu administrador!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Seu e-mail não tem permissão para registrar" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "O e-mail de confirmação foi enviado para a sua conta de e-mail." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Não é possível ativar a autenticação LDAP" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "agora você está logado como: '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Login de reserva como:'%(nickname)s', servidor LDAP não acessível ou usuário desconhecido" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Não foi possível fazer o login: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Nome de Usuário ou Senha incorretos" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Nova Senha foi enviada para seu endereço de e-mail" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Ocorreu um erro desconhecido. Por favor, tente novamente mais tarde." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Por favor, digite um nome de usuário válido para redefinir a senha" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Você agora está logado como: '%(nickname)s'" +msgstr "agora você está logado como: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Perfil de %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Perfil atualizado" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Encontrada uma conta existente para este endereço de e-mail." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Não foi encontrado nenhum arquivo gmail.json válido com informações do OAuth" +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s enviado para E-Reader" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1427,35 +1493,35 @@ msgstr "Converter" msgid "Reconnecting Calibre database" msgstr "Reconectando banco de dados Calibre" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "E-mail" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" -msgstr "editar metadados" +msgstr "Cópia de segurança de metadados" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "Gerado %(count)s miniaturas de capa" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "Miniatura da Capa" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "Gerado {0} miniaturas de série" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "Limpando o cache de miniaturas da capa" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Upload" @@ -1471,14 +1537,14 @@ msgstr "Nome de usuário" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Endereço de e-mail" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Enviar para o endereço de e-mail do E-Reader" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Admin" @@ -1488,8 +1554,8 @@ msgstr "Admin" msgid "Password" msgstr "Senha" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Baixar" @@ -1514,16 +1580,12 @@ msgstr "Apagar" msgid "Public Shelf" msgstr "Estante Pública" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Adicionar Novo Usuário" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importar usuários LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Configurações do servidor de e-mail" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1544,11 +1606,12 @@ msgstr "Login SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Do E-mail" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "Serviço de E-Mail" #: cps/templates/admin.html:91 @@ -1620,102 +1683,104 @@ msgid "Scheduled Tasks" msgstr "Tarefas Agendadas" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "Hora em que as tarefas começam a ser executadas" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "Duração máxima das tarefas" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "Gerar miniaturas de capa de livro" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "Gerar miniaturas de capa de séries" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "Reconectar à Biblioteca do Calibre" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" msgstr "Atualizar Cache de Capas de Miniaturas" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Administração" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Baixar Pacote de Depuração" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Ver Logs" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Reconectar Banco de dados Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Reiniciar" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Desligar" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "Informação da Versão" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Versão" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detalhes" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Versão atual" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Verificar Atualizações" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Realizar Atualizações" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Tem a certeza que quer reiniciar?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Ok" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Cancelar" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Tem certeza que quer encerrar?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Atualizando, por favor não recarregue esta página" @@ -1805,7 +1870,7 @@ msgid "Author" msgstr "Autor" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Descrição" @@ -1830,7 +1895,7 @@ msgstr "Remover" msgid "Add Identifier" msgstr "Adicionar Identificador" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Tags" @@ -1855,23 +1920,23 @@ msgid "Published Date" msgstr "Data de Publicação" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Editora" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Idioma" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Sim" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Não" @@ -1888,8 +1953,8 @@ msgid "Fetch Metadata" msgstr "Buscar Metadados" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1911,8 +1976,8 @@ msgstr "Clique na capa para carregar os metadados para o formulário" msgid "Loading..." msgstr "Carregando..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Fechar" @@ -2137,7 +2202,7 @@ msgid "Enable Uploads" msgstr "Habilitar Uploads" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "(Por favor, certifique-se de que os usuários também tenham direitos de upload)" #: cps/templates/config_edit.html:112 @@ -2153,7 +2218,7 @@ msgid "Enable Public Registration" msgstr "Habilitar Registro Público" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Use e-mail como nome de usuário" #: cps/templates/config_edit.html:132 @@ -2343,6 +2408,52 @@ msgstr "Caminho para Kepubify E-Book Converter" msgid "Location of Unrar binary" msgstr "Caminho para o binário Unrar" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Configurações do OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Política de senha do usuário" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Configuração de Visualização" @@ -2355,7 +2466,7 @@ msgstr "Nº de Livros Aleatórios a Exibir" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Nº de Autores a Exibir Antes de Esconder (0=Desativar Esconder)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Tema" @@ -2444,80 +2555,84 @@ msgstr "Adicionar Tags Permitidas/Negadas" msgid "Add Allowed/Denied custom column values" msgstr "Adicionar Valores Permitidos/Negados de Coluna Personalizada" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Ler no Browser" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Ouvir no Browser" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "Livro %(index)s de %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publicado em" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Marcar como Não Lido" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Marcar como Lido" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Lido" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Restaurar do arquivo" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Adicionar ao arquivo" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Arquivado" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Descrição:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Adicionar à estante" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Público)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Editar Metadados" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Escolha o Tipo do Servidor" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Use Conta de E-Mail Padrão" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Conta Gmail com Verificação OAuth2" +#, fuzzy +msgid "Gmail Account" +msgstr "Conta Gmail" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Configurar conta do Gmail como servidor de e-mail" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2540,10 +2655,11 @@ msgid "Attachment Size Limit" msgstr "Limite do Tamanho do Anexo" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Salvar e enviar e-mail de teste" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Voltar" @@ -2569,13 +2685,13 @@ msgstr "Digite o nome do domínio" msgid "Denied Domains (Blacklist)" msgstr "Domínios Negados (Lista Negra)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Próximo" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Abra o arquivo .kobo/Kobo eReader.conf em um editor de texto e adicione (ou edite):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Abra o arquivo .kobo/Kobo/Kobo eReader.conf em um editor de texto e adicione (ou edite):" #: cps/templates/generate_kobo_auth_url.html:11 msgid "Kobo Token:" @@ -2585,19 +2701,19 @@ msgstr "Token Kobo:" msgid "List" msgstr "Lista" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Instancia do Calibre-Web não configurado, por favor contacte o seu administrador" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Criar Issue" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Voltar para Início" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "Deslogar" @@ -2627,80 +2743,80 @@ msgstr "Ordenar em ordem crescente de acordo com o índice de série" msgid "Sort descending according to series index" msgstr "Ordenação em ordem decrescente de acordo com o índice de série" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Início" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Livros Alfabéticos" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Livros ordenados alfabeticamente" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Publicações populares deste catálogo baseadas em Downloads." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Publicações populares deste catálogo baseadas em Avaliação." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Livros recentemente adicionados" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Os últimos Livros" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Livros Aleatórios" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Livros ordenados por Autor" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Livros ordenados por editora" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Livros ordenados por categoria" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Livros ordenados por série" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Livros ordenados por Idiomas" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Livros ordenados por Avaliação" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Livros ordenados por formatos de arquivo" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Estantes" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Livros organizados em Estantes" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Início" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Alternar Navegação" @@ -2708,48 +2824,48 @@ msgstr "Alternar Navegação" msgid "Search Library" msgstr "Pesquisar na Biblioteca" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Enviando..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Erro" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Upload concluído, processando, por favor aguarde ..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Configurações" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Conta" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Sair" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Enviando..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Erro" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Upload concluído, processando, por favor aguarde ..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Configurações" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Por favor, não atualize a página" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Navegue em" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Sobre" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Anterior" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Detalhes do Livro" @@ -2765,7 +2881,7 @@ msgstr "Lembre-se de mim" msgid "Forgot Password?" msgstr "Esqueceu a senha?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Entre com o Magic Link" @@ -2873,135 +2989,160 @@ msgstr "Catálogo de e-books Calibre-Web" msgid "epub Reader" msgstr "leitor de epub" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Claro" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Escuro" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "Sépia" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 msgid "Black" msgstr "Preto" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Refluir o texto quando as barras laterais estiverem abertas." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "Leitor de Quadrinhos" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Atalhos de Teclado" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Página Anterior" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Página seguinte" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Dimensionar para Melhor" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Dimensionar para Largura" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Dimensionar para Altura" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Dimensionar para a Nativo" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Girar para direita" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Girar para esqueda" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Inverter Imagem" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Página única" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Dimensionar" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Melhor" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Largura" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Altura" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Nativo" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Rodar" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Inverter" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Horizontal" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Vertical" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Direção" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Esquerda para a direita" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Direita para a esquerda" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Redefinir para o topo" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Lembrar Posição" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Barra de Rolagem" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Mostrar" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Esconder" @@ -3009,7 +3150,7 @@ msgstr "Esconder" msgid "DJVU Reader" msgstr "leitor de DJVU" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "Leitor de PDF" @@ -3026,7 +3167,7 @@ msgid "Choose a username" msgstr "Escolha um nome de usuário" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Seu endereço de e-mail" #: cps/templates/remote_login.html:5 @@ -3045,10 +3186,6 @@ msgstr "Uma vez verificado, você será automaticamente conectado a este disposi msgid "This verification link will expire in 10 minutes." msgstr "Este link de verificação irá expirar em 10 minutos." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "Gerar miniaturas de capa de Livro" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "Gerar miniaturas de capa de Série" @@ -3073,43 +3210,51 @@ msgstr "Data de Publicação de" msgid "Published Date To" msgstr "Data de Publicação Até" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Excluir Tags" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Excluir Série" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "Excluir Estante" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Excluir idiomas" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Extensões" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Excluir extensões" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Avaliação Acima" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Avaliação Abaixo" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "De:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Para:" @@ -3201,10 +3346,6 @@ msgstr "Progresso" msgid "Run Time" msgstr "Tempo de execução" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Hora de início" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "Ações" @@ -3278,15 +3419,18 @@ msgid "Enter Username" msgstr "Escolha um nome de usuário" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "Seu endereço de e-mail" +#, fuzzy +msgid "Enter Email" +msgstr "E-mail de teste" #: cps/templates/user_table.html:136 -msgid "Enter E-Reader E-mail Address" -msgstr "Digite o endereço de e-mail do E-Reader" +#, fuzzy +msgid "Enter eReader Email" +msgstr "Enviar para o endereço de e-mail do E-Reader" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" +#, fuzzy +msgid "eReader Email" msgstr "E-mail do E-Reader" #: cps/templates/user_table.html:137 @@ -3346,10 +3490,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "Sincronizar Estantes Selecionadas com Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" -msgstr "Mostrar seleção de lidos/não lidos" - -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Mostrar livros aleatórios" +#, fuzzy +msgid "Show Read/Unread Section" +msgstr "Mostrar seção de lidos/não lidos" diff --git a/cps/translations/ru/LC_MESSAGES/messages.mo b/cps/translations/ru/LC_MESSAGES/messages.mo index a5fd7591..87a4c5ef 100644 Binary files a/cps/translations/ru/LC_MESSAGES/messages.mo and b/cps/translations/ru/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/ru/LC_MESSAGES/messages.po b/cps/translations/ru/LC_MESSAGES/messages.po index cbf38da6..5e1bcf29 100644 --- a/cps/translations/ru/LC_MESSAGES/messages.po +++ b/cps/translations/ru/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-04-29 01:20+0400\n" "Last-Translator: ZIZA\n" "Language: ru\n" @@ -17,498 +17,508 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Статистика" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Сервер перезагружен, пожалуйста, обновите страницу" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Производится остановка сервера, пожалуйста, закройте окно" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Успешно переподключено" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Неизвестная команда" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Книга успешно поставлена в очередь для отправки на %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Книга успешно поставлена в очередь для отправки на %(eReadermail)s" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Неизвестно" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Администрирование" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Настройки сервера" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Настройка интерфейса" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Управление сервером" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Все" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Показать все" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Конфигурация Calibre-Web обновлена" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Вы действительно хотите удалить Kobo Token ?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Вы действительно хотите удалить эту книжную полку?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Вы действительно хотите удалить эту книжную полку?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Вы действительно хотите удалить эту книжную полку?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Вы действительно хотите удалить эту книжную полку?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Вы действительно хотите остановить Calibre-Web?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Запретить" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Разрешить" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json не настроен для веб-приложения" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Неправильное расположение файла журнала, пожалуйста, введите правильный путь." -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Недопустимое расположение файла журнала доступа, пожалуйста, введите правильный путь" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Пожалуйста, введите провайдера LDAP, порт, DN и идентификатор объекта пользователя" -#: cps/admin.py:1179 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Пожалуйста, введите действительное имя пользователя для сброса пароля" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "Фильтр объектов группы LDAP должен иметь один идентификатор формата \"%s\"" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "Фильтр объектов группы LDAP имеет незавершённые круглые скобки" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "Фильтр объектов пользователя LDAP должен иметь один идентификатор формата \"%s\"" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "Фильтр объектов пользователя LDAP имеет незавершенную круглую скобку" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Добавить пользователя" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Добавить нового пользователя" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Изменить настройки SMTP" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Произошла ошибка при отправке тестового письма на: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Пожалуйста, сначала настройте свой адрес электронной почты ..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "Настройки E-mail сервера обновлены" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Неизвестная ошибка. Попробуйте позже." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Изменить пользователя %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Пароль для пользователя %(user)s сброшен" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Пожалуйста, сперва настройте параметры SMTP....." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Просмотр лога" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Проверка обновлений" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Загрузка обновлений" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Распаковка обновлений" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Замена файлов" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Соединения с базой данных закрыты" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Остановка сервера" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Обновления установлены, нажмите ок и перезагрузите страницу" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Ошибка обновления:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Ошибка HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Ошибка соединения" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Тайм-аут при установлении соединения" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Общая ошибка" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Не удалось сохранить файл обновления во временной папке." -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Не удалось создать хотя бы одного пользователя LDAP" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Не удалось создать хотя бы одного пользователя LDAP" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Ошибка: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Ошибка: ни одного пользователя не найдено в ответ на запрос сервер LDAP" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "По крайней мере, один пользователь LDAP не найден в базе данных" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "Расположение Базы Данных неверно, пожалуйста, введите правильный путь." -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "Расположение ключевого файла неверно, пожалуйста, введите правильный путь" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "Расположение Certfile не является действительным, пожалуйста, введите правильный путь" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "Настройки E-mail сервера обновлены" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Дополнительный Настройки" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Пожалуйста, заполните все поля!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "E-mail не из существующей доменной зоны" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Добавить пользователя" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Пользователь '%(user)s' добавлен" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Для этого адреса электронной почты или логина уже есть учётная запись." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Пользователь '%(nick)s' удалён" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Это последний администратор, невозможно удалить пользователя" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Пользователь '%(nick)s' обновлён" @@ -521,122 +531,122 @@ msgstr "не установлено" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Нет" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Невозможно открыть книгу. Файл не существует или недоступен" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Метаданные обновлены" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Файл %(file)s загружен" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Исходный или целевой формат для конвертирования отсутствует" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Книга успешно поставлена в очередь для конвертирования в %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Произошла ошибка при конвертирования этой книги: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Загруженная книга, вероятно, существует в библиотеке, перед тем как загрузить новую, рассмотрите возможность изменения: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s не допустимый язык" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Запрещена загрузка файлов с расширением '%(ext)s'" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Загружаемый файл должен иметь расширение" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Файл %(filename)s не удалось сохранить во временную папку" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "изменить метаданные" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Ошибка при создании пути %(path)s (Доступ запрещён)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Не удалось сохранить файл %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Формат файла %(ext)s добавлен в %(book)s" @@ -649,182 +659,187 @@ msgstr "Настройка Google Drive не завершена, попробу msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Не удалось проверить домен обратного вызова, пожалуйста, выполните шаги для проверки домена в консоли разработчика Google." -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s форма не найден для книги с id: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s не найден на Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s не найден: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Отправить на Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Это электронное письмо было отправлено через Caliber-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Тестовый e-mail для Calibre-Web" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Тестовый e-mail" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Начать работу с Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Регистрационный e-mail для пользователя: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Преобразовать %(orig)s в %(format)s и отправить в Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Отправить %(format)s в Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Отправить на Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Запрашиваемый файл не может быть прочитан. Возможно у вас нет разрешения?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Переименовывание заголовка с: '%(src)s' на '%(dest)s' не удалось из-за ошибки: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Файл %(file)s не найден на Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Переименовывание заголовка с: '%(src)s' на '%(dest)s' не удалось из-за ошибки: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Путь книги %(path)s не найден на Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Этот адрес электронной почты уже зарегистрирован." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Это имя пользователя уже занято" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Не удалось создать путь для обложки." -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Только файлы в формате jpg / jpeg поддерживаются как файл обложки" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Обзор" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Пожалуйста, подключитесь к Calibre-Web не с локального хоста, чтобы получить действительный api_endpoint для устройства Kobo" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Настройка Kobo" @@ -833,9 +848,9 @@ msgstr "Настройка Kobo" msgid "Register with %(provider)s" msgstr "Зарегистрируйтесь с %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "вы вошли как пользователь '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -894,12 +909,13 @@ msgstr "Ошибка Google Oauth, пожалуйста попробуйте п msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Логин" @@ -915,149 +931,158 @@ msgstr "Ключ просрочен" msgid "Success! Please return to your device" msgstr "Успешно! Пожалуйста, проверьте свое устройство" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Книги" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Показывать недавние книги" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Популярные Книги" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Показывать популярные книги" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Книги с наилучшим рейтингом" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Показывать книги с наивысшим рейтингом" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Прочитанные Книги" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Показывать прочитанные и непрочитанные" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Непрочитанные Книги" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Показать непрочитанное" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Обзор" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Показывать Случайные Книги" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Категории" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Показывать выбор категории" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Серии" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Показывать выбор серии" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Авторы" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Показывать выбор автора" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Издатели" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Показать выбор издателя" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Языки" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Показывать выбор языка" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Рейтинги" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Показать выбор рейтинга" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Форматы файлов" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Показать выбор форматов файлов" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" -msgstr "" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Показывать недавние книги" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Поиск" @@ -1081,14 +1106,14 @@ msgstr "Рейтинг >= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Расширенный поиск" @@ -1139,7 +1164,7 @@ msgstr "Книга удалена с полки: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Создать полку" @@ -1166,73 +1191,73 @@ msgstr "Метаданные обновлены" msgid "Change order of Shelf: '%(name)s'" msgstr "Изменить расположение полки '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Создана полка %(title)s" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Колка %(title)s изменена" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Произошла ошибка" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "Публичная полка с названием '%(title)s' уже существует." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "Приватная полка с названием '%(title)s' уже существует." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Полка: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Ошибка открытия Полки. Полка не существует или недоступна" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Задания" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Ожидание" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Неудачно" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Начало" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Завершено" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Неизвестный статус" @@ -1265,146 +1290,186 @@ msgstr "Новое обновление доступно. Нажмите на к msgid "No release information available" msgstr "Информация о выпуске недоступна" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Обзор (Случайные Книги)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Популярные книги (часто загружаемые)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Автор: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Издатель: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Серии: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Оценка: %(rating)s звезды(а)" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Формат файла: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Категория: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Язык: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Скачать" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Список рейтингов" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Список форматов файлов" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Книга успешно поставлена в очередь для отправки на %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Пожалуйста, сперва настройте параметры SMTP....." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Книга успешно поставлена в очередь для отправки на %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "При отправке этой книги произошла ошибка: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Пожалуйста, сначала настройте e-mail на вашем kindle..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "Сервер электронной почты не настроен, обратитесь к администратору !" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Зарегистрироваться" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Сервер электронной почты не настроен, обратитесь к администратору !" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Ваш e-mail не подходит для регистрации" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Письмо с подтверждением отправлено вам на e-mail." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Не удается активировать LDAP аутентификацию" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "вы вошли как пользователь '%(nickname)s'" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "Резервный вход в систему как: '%(nickname)s', LDAP-сервер недоступен или пользователь не известен" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Не удалось войти: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Ошибка в имени пользователя или пароле" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Новый пароль был отправлен на ваш адрес электронной почты" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Неизвестная ошибка. Попробуйте позже." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Пожалуйста, введите действительное имя пользователя для сброса пароля" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Вы вошли как: '%(nickname)s'" +msgstr "вы вошли как пользователь '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Профиль %(name)s's" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Профиль обновлён" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Этот адрес электронной почты уже зарегистрирован." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Отправить на Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1447,35 +1512,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "изменить метаданные" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Загрузить" @@ -1491,15 +1556,15 @@ msgstr "Имя пользователя" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Адрес электронной почты" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Отправить на Kindle Адрес электронной почты" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Управление" @@ -1509,8 +1574,8 @@ msgstr "Управление" msgid "Password" msgstr "Пароль" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Скачать" @@ -1535,16 +1600,12 @@ msgstr "Удалить" msgid "Public Shelf" msgstr "" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Добавить нового пользователя" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Импорт пользователей LDAP" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Настройки SMTP-сервера" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1565,11 +1626,11 @@ msgstr "SMTP-логин" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Отправитель" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1642,102 +1703,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Управление" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Просмотреть лог файл" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Пере подключиться к базе жанных Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Перезагрузить Calibre-Web" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Остановить Calibre-Web" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Версия" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Подробности" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Текущая версия" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Проверка обновлений" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Установить обновления" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Вы действительно хотите перезагрузить Calibre-Web?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Ok" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Отмена" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Вы действительно хотите остановить Calibre-Web?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Установка обновлений, пожалуйста, не обновляйте страницу" @@ -1827,7 +1890,7 @@ msgid "Author" msgstr "Автор" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Описание" @@ -1852,7 +1915,7 @@ msgstr "" msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Теги" @@ -1877,23 +1940,23 @@ msgid "Published Date" msgstr "Опубликовано" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Издатель" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Язык" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Да" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Нет" @@ -1910,8 +1973,8 @@ msgid "Fetch Metadata" msgstr "Получить метаданные" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1934,8 +1997,8 @@ msgstr "Нажмите на обложку, чтобы получить мета msgid "Loading..." msgstr "Загрузка..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Закрыть" @@ -2163,7 +2226,7 @@ msgid "Enable Uploads" msgstr "Разрешить загрузку на сервер" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2179,7 +2242,7 @@ msgid "Enable Public Registration" msgstr "Разрешить публичную регистрацию" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2369,6 +2432,52 @@ msgstr "" msgid "Location of Unrar binary" msgstr "Расположение бинарного файла Unrar" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Настройки OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Сбросить пароль пользователя" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Просмотреть Конфигурацию" @@ -2381,7 +2490,7 @@ msgstr "Количество отображаемых случайных кни msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Количество авторов для отображения перед скрытием (0 = отключить скрытие)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Тема" @@ -2472,79 +2581,82 @@ msgstr "Добавить разрешенные / запрещенные тег msgid "Add Allowed/Denied custom column values" msgstr "Добавить разрешенные / запрещенные значения индивидуальных столбцов" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Читать" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Прослушать в браузере" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Опубликованный" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Отметить как непрочитанное" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Отметить как прочитанное" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Прочесть" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Описание:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Добавить на книжную полку" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Публичная)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Редактировать метаданные" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "" +#, fuzzy +msgid "Gmail Account" +msgstr "Учетная запись" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2568,10 +2680,11 @@ msgid "Attachment Size Limit" msgstr "" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Сохранить настройки и отправить тестовое письмо" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Назад" @@ -2597,12 +2710,12 @@ msgstr "Введите доменное имя" msgid "Denied Domains (Blacklist)" msgstr "Запрещенные домены (черный список)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Далее" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "Откройте файл .kobo / Kobo eReader.conf в текстовом редакторе и добавьте (или отредактируйте):" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2614,20 +2727,20 @@ msgstr "Kobo Sync Token" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Сервер электронной почты не настроен, обратитесь к администратору !" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Создать запись" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Вернуться на главную" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2657,80 +2770,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Старт" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Популярные книги в этом каталоге, на основе количества Скачиваний." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Популярные книги из этого каталога на основании Рейтинга." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Недавно добавленные книги" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Последние Книги" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Случайный выбор" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Книги, отсортированные по Автору" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Книги, отсортированные по издателю" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Книги, отсортированные по категории" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Книги, отсортированные по серии" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Книги отсортированы по языкам" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Книги, упорядоченные по рейтингу" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Книги отсортированы по формату файла" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Полки" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Книги организованы на полках" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Главная" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Включить навигацию" @@ -2738,48 +2851,48 @@ msgstr "Включить навигацию" msgid "Search Library" msgstr "Поиск в библиотеке" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Загружается..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Ошибка" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Загрузка завершена, обработка, пожалуйста, подождите..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Настройки" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Учетная запись" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Выход" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Загружается..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Ошибка" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Загрузка завершена, обработка, пожалуйста, подождите..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Настройки" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Пожалуйста не обновляйте страницу" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Просмотр" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "О программе" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Предыдущий" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Подробнее о книге" @@ -2795,7 +2908,7 @@ msgstr "Запомнить меня" msgid "Forgot Password?" msgstr "Забыли пароль ?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Войти через магическую ссылку" @@ -2905,137 +3018,162 @@ msgstr "Каталог электронных книг Caliber-Web" msgid "epub Reader" msgstr "PDF reader" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Светлая" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Темная" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Назад" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Обновить размещение текста при открытии боковой панели." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "PDF reader" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Горячие клавиши" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Предыдущая страница" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Следующая страница" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Масштабировать до лучшего" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Масштабироваать по ширине" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Масштабировать по высоте" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Масштабировать до оригинала" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Повернуть Вправо" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Повернуть Влево" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Перевернуть изображение" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Администрирование" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Масштаб" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Лучшее" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Ширина" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Длина" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Оригинальный" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Повернуть" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Перевернуть" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Горизонтально" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Вертикально" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Направление" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Слева направо" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Справа налево" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3044,7 +3182,7 @@ msgstr "" msgid "DJVU Reader" msgstr "PDF reader" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "PDF reader" @@ -3063,7 +3201,7 @@ msgid "Choose a username" msgstr "Выберите имя пользователя" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Ваш email-адрес" #: cps/templates/remote_login.html:5 @@ -3082,10 +3220,6 @@ msgstr "После этого вы автоматически войдете в msgid "This verification link will expire in 10 minutes." msgstr "Срок действия ссылки истекает через 10 минут." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3110,44 +3244,52 @@ msgstr "Опубликовано от" msgid "Published Date To" msgstr "Опубликовано до" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Исключить теги" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Исключить серии" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Исключить серии" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Исключить языки" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Расширения" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Исключить расширения" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Рейтинг больше чем" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Рейтинг меньше чем" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3239,10 +3381,6 @@ msgstr "Прогресс" msgid "Run Time" msgstr "Время выполнения" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Время начала" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3319,17 +3457,17 @@ msgstr "Выберите имя пользователя" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Ваш email-адрес" +msgid "Enter Email" +msgstr "Тестовый e-mail" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "Отправить на Kindle Адрес электронной почты" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Тестовый e-mail" #: cps/templates/user_table.html:137 @@ -3399,10 +3537,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Показывать выбор серии" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Показывать случайные книги" - diff --git a/cps/translations/sk/LC_MESSAGES/messages.mo b/cps/translations/sk/LC_MESSAGES/messages.mo new file mode 100644 index 00000000..b4467aa7 Binary files /dev/null and b/cps/translations/sk/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/sk/LC_MESSAGES/messages.po b/cps/translations/sk/LC_MESSAGES/messages.po new file mode 100644 index 00000000..a183e00f --- /dev/null +++ b/cps/translations/sk/LC_MESSAGES/messages.po @@ -0,0 +1,3460 @@ +# Slovak (Slovakia) translations for . +# Copyright (C) 2023 ORGANIZATION +# This file is distributed under the same license as the project. +# Branislav Hanáček , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Calibre-Web\n" +"Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" +"PO-Revision-Date: 2023-11-01 06:12+0100\n" +"Last-Translator: Branislav Hanáček \n" +"Language: sk_SK\n" +"Language-Team: \n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n>=2 && n<=4 ? 1 : 2);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.13.1\n" + +#: cps/about.py:84 +msgid "Statistics" +msgstr "Štatistika" + +#: cps/admin.py:149 +msgid "Server restarted, please reload page." +msgstr "Server bol reštartovaný, znovu načítajte stránku." + +#: cps/admin.py:151 +msgid "Performing Server shutdown, please close window." +msgstr "Vypínam server, zavrite prosím okno." + +#: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "Spojenie s databázovo bolo úspešne znovu naviazané" + +#: cps/admin.py:162 +msgid "Unknown command" +msgstr "Neznámy príkaz" + +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Úspech! Knihy boli zaradená do zálohovania metadát, skontrolujte si Úlohy na kontrolu" + +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 +msgid "Unknown" +msgstr "Neznámy" + +#: cps/admin.py:231 +msgid "Admin page" +msgstr "Stránka správcu" + +#: cps/admin.py:251 +msgid "Basic Configuration" +msgstr "Základná konfigurácia" + +#: cps/admin.py:289 +msgid "UI Configuration" +msgstr "Konfigurácia používateľského rozhrania" + +#: cps/admin.py:323 cps/templates/admin.html:51 +msgid "Edit Users" +msgstr "Upraviť používateľov" + +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 +#: cps/templates/list.html:13 +msgid "All" +msgstr "Všetko" + +#: cps/admin.py:394 cps/admin.py:1405 +msgid "User not found" +msgstr "Používateľ sa nenašiel" + +#: cps/admin.py:408 +msgid "{} users deleted successfully" +msgstr "Zmazaných {} používateľov" + +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 +#: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 +msgid "Show All" +msgstr "Zobraziť všetko" + +#: cps/admin.py:452 cps/admin.py:458 +msgid "Malformed request" +msgstr "Chybne vytvorená žiadosť" + +#: cps/admin.py:470 cps/admin.py:2023 +msgid "Guest Name can't be changed" +msgstr "Meno hosťa nie je možné zmeniť" + +#: cps/admin.py:482 +msgid "Guest can't have this role" +msgstr "Hosť nemôže mať túto rolu" + +#: cps/admin.py:494 cps/admin.py:1977 +msgid "No admin user remaining, can't remove admin role" +msgstr "Nezostáva žiadny správca, nie je možné odobrať rolu správcu" + +#: cps/admin.py:498 cps/admin.py:512 +msgid "Value has to be true or false" +msgstr "Hodnota musí byť pravda alebo nepravda" + +#: cps/admin.py:500 +msgid "Invalid role" +msgstr "Neplatná rola" + +#: cps/admin.py:504 +msgid "Guest can't have this view" +msgstr "Hosť nemôže mať toto zobrazenie" + +#: cps/admin.py:514 +msgid "Invalid view" +msgstr "Neplatné zobrazenie" + +#: cps/admin.py:517 +msgid "Guest's Locale is determined automatically and can't be set" +msgstr "Nastavenie jazyka pre hosťa sa určí automaticky a nie je možné ho nastaviť" + +#: cps/admin.py:521 +msgid "No Valid Locale Given" +msgstr "Nebolo poskytnuté platné nastavenie jazyka" + +#: cps/admin.py:532 +msgid "No Valid Book Language Given" +msgstr "Nebolo poskytnuté platné jazykové nastavenie pre knihu" + +#: cps/admin.py:534 cps/editbooks.py:453 +msgid "Parameter not found" +msgstr "Parameter sa nenašiel" + +#: cps/admin.py:571 +msgid "Invalid Read Column" +msgstr "Neplatný stĺpec na čítanie" + +#: cps/admin.py:577 +msgid "Invalid Restricted Column" +msgstr "Neplatný stĺpec na obmedzenie" + +#: cps/admin.py:597 cps/admin.py:1848 +msgid "Calibre-Web configuration updated" +msgstr "Konfigurácia Calibre-Web bola aktualizovaná" + +#: cps/admin.py:609 +msgid "Do you really want to delete the Kobo Token?" +msgstr "Naozaj chcete zmazať Kobo-žetón?" + +#: cps/admin.py:611 +msgid "Do you really want to delete this domain?" +msgstr "Naozaj chcete zmazať túto doménu?" + +#: cps/admin.py:613 +msgid "Do you really want to delete this user?" +msgstr "Naozaj chcete zmazať tohot používateľa?" + +#: cps/admin.py:615 +msgid "Are you sure you want to delete this shelf?" +msgstr "Naozaj chcete zmazať túto poličku?" + +#: cps/admin.py:617 +msgid "Are you sure you want to change locales of selected user(s)?" +msgstr "Naozaj chcete zmeniť nastavenia jazykov pre vybraných používateľov?" + +#: cps/admin.py:619 +msgid "Are you sure you want to change visible book languages for selected user(s)?" +msgstr "Naozaj chcete zmeniť viditeľné jazkyky pre knihy pre vybraných používateľov?" + +#: cps/admin.py:621 +msgid "Are you sure you want to change the selected role for the selected user(s)?" +msgstr "Naozaj chcete zmeniť vybrané role pre vybraných používateľov?" + +#: cps/admin.py:623 +msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" +msgstr "Naozaj chcete zmeniť vybrané obmedzenia pre vybraných používateľov?" + +#: cps/admin.py:625 +msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" +msgstr "Naozaj chcete zmeniť vybrané obmedzenia viditeľnosti pre vybraných používateľov?" + +#: cps/admin.py:628 +msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" +msgstr "Naozaj chcete zmeniť synchronizačné správanie sa police pre vybraných používateľov?" + +#: cps/admin.py:630 +msgid "Are you sure you want to change Calibre library location?" +msgstr "Naozaj chcete zmenit umiestnenie pre knižnicu Calibre?" + +#: cps/admin.py:632 +msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" +msgstr "Calilbre-Web vyhľadá aktualizované obálky a aktualizuje ich náhľady, môže to chvíľu trvať?" + +#: cps/admin.py:635 +msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" +msgstr "Naozaj chcete zmazať synchronizačnú databázu Calibre-Web aby ste vynútili úplnú synchronizáciu s vašou Kobo čítačkou?" + +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 +#: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 +#: cps/templates/user_table.html:58 +msgid "Deny" +msgstr "Odmietnuť" + +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 +#: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 +#: cps/templates/user_table.html:61 +msgid "Allow" +msgstr "Povoliť" + +#: cps/admin.py:921 +msgid "{} sync entries deleted" +msgstr "Zmazalo sa {} synchronizačných položiek" + +#: cps/admin.py:969 +msgid "Tag not found" +msgstr "Štítok sa nenašiel" + +#: cps/admin.py:981 +msgid "Invalid Action" +msgstr "Neplatná akcia" + +#: cps/admin.py:1111 +msgid "client_secrets.json Is Not Configured For Web Application" +msgstr "client_secrets.json nie je nakonfiguraovaný pre webovú aplikáciu" + +#: cps/admin.py:1156 +msgid "Logfile Location is not Valid, Please Enter Correct Path" +msgstr "Umiestnenie denníkového súboru je neplatné, zadajte prosím správnu cestu" + +#: cps/admin.py:1162 +msgid "Access Logfile Location is not Valid, Please Enter Correct Path" +msgstr "Umiestnenie súbor denníka prístupov nie je platné, zadajte prosím správnu cestu" + +#: cps/admin.py:1196 +msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" +msgstr "Zadajte prosím poskytovateľa LDAP, port, DN a identifikátor používateľa" + +#: cps/admin.py:1202 +msgid "Please Enter a LDAP Service Account and Password" +msgstr "Zadajte prosím konto a heslo pre LDAP službu" + +#: cps/admin.py:1205 +msgid "Please Enter a LDAP Service Account" +msgstr "Zadajte prosím konto pre LDAP službu" + +#: cps/admin.py:1210 +#, python-format +msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" +msgstr "Filter pre LDAP objekt skupiny potrebuje jeden \"%s\" formátový identifikátor" + +#: cps/admin.py:1212 +msgid "LDAP Group Object Filter Has Unmatched Parenthesis" +msgstr "Filter pre LDAP objekt skupiny má nezhodu v zátvorkách" + +#: cps/admin.py:1216 +#, python-format +msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" +msgstr "Filter pre LDAP objekt používateľa potrebuje jeden \"%s\" formátový identifikátor" + +#: cps/admin.py:1218 +msgid "LDAP User Object Filter Has Unmatched Parenthesis" +msgstr "Filter pre LDAP objekt používateľa má nezhodu v zátvorkách" + +#: cps/admin.py:1225 +#, python-format +msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" +msgstr "Filter pre LDAP členstvo používateľa potrebuje jeden \"%s\" formátový identifikátor" + +#: cps/admin.py:1227 +msgid "LDAP Member User Filter Has Unmatched Parenthesis" +msgstr "Filter pre LDAP členstvo používateľa má nezhodu v zátvorkách" + +#: cps/admin.py:1234 +msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" +msgstr "LDAP CA-certifikát, certifikát alebo umiestnenie kľúča nie je platné. Zadajte prosím správnu cestu" + +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "Pridať nového používateľa" + +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" +msgstr "Upraviť nastavenie pre poštový server" + +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Úspech! Gmail konto bolo verifikované." + +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 +#, python-format +msgid "Oops! Database Error: %(error)s." +msgstr "Chyba databázy: %(error)s." + +#: cps/admin.py:1323 +#, python-format +msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" +msgstr "Testovací e-mail bol zaradený na odoslanie na %(email)s, skontrolujte si výsledok v sekcii Úlohy" + +#: cps/admin.py:1326 +#, python-format +msgid "There was an error sending the Test e-mail: %(res)s" +msgstr "Pri odosielaní testovacieho e-mailu sa vyskytla chyba: %(res)s" + +#: cps/admin.py:1328 +msgid "Please configure your e-mail address first..." +msgstr "Prosím, najskôr si nastavte e-mailovú adresu..." + +#: cps/admin.py:1330 +msgid "Email Server Settings updated" +msgstr "Nastavenia poštového servera boli aktualizované" + +#: cps/admin.py:1353 cps/templates/admin.html:195 +msgid "Edit Scheduled Tasks Settings" +msgstr "Upraviť nastavenia naplánovaných úloh" + +#: cps/admin.py:1365 +msgid "Invalid start time for task specified" +msgstr "Bol uvedený neplatný čas spustenia" + +#: cps/admin.py:1370 +msgid "Invalid duration for task specified" +msgstr "Bol uvedený neplatný doba behu" + +#: cps/admin.py:1380 +msgid "Scheduled tasks settings updated" +msgstr "Nastavenia naplánovaných úloh boli aktualizované" + +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." +msgstr "Vyskytla sa neočakávaná chyba. Prosím, skúste to opäť neskôr." + +#: cps/admin.py:1394 +msgid "Settings DB is not Writeable" +msgstr "Nie je možné zapisovať do databázy nastavení" + +#: cps/admin.py:1424 cps/admin.py:2039 +#, python-format +msgid "Edit User %(nick)s" +msgstr "Upraviť používateľa %(nick)s" + +#: cps/admin.py:1436 +#, python-format +msgid "Success! Password for user %(user)s reset" +msgstr "Úspech! Heslo pre používateľa %(user)s bolo resetované" + +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." +msgstr "Nastavte prosím poštový server." + +#: cps/admin.py:1453 +msgid "Logfile viewer" +msgstr "Prezerač denníkového súboru" + +#: cps/admin.py:1519 +msgid "Requesting update package" +msgstr "Žiadosť o aktualizačný balík" + +#: cps/admin.py:1520 +msgid "Downloading update package" +msgstr "Sťahuje sa aktualizačný balík" + +#: cps/admin.py:1521 +msgid "Unzipping update package" +msgstr "Rozbaľuje sa aktualizačný balík" + +#: cps/admin.py:1522 +msgid "Replacing files" +msgstr "Nahradzujú sa súbory" + +#: cps/admin.py:1523 +msgid "Database connections are closed" +msgstr "Spojenia s databázou sú uzavreté" + +#: cps/admin.py:1524 +msgid "Stopping server" +msgstr "Zastavuje sa server" + +#: cps/admin.py:1525 +msgid "Update finished, please press okay and reload page" +msgstr "Aktualizácia dokončená, stlačte prosím OK a znovu načítajte stránku" + +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 +msgid "Update failed:" +msgstr "Aktualizácia zlyhala:" + +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +msgid "HTTP Error" +msgstr "HTTP chyba" + +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 +msgid "Connection error" +msgstr "Chyba spojenia" + +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 +msgid "Timeout while establishing connection" +msgstr "Časový limit pre naviazanie spojenia vypršal" + +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 +msgid "General error" +msgstr "Všeobecná chyba" + +#: cps/admin.py:1530 +msgid "Update file could not be saved in temp dir" +msgstr "Súbor aktualizácie nebolo možné uložiť do dočasného adresára" + +#: cps/admin.py:1531 +msgid "Files could not be replaced during update" +msgstr "Nebolo možné nahradiť súbory počas aktualizácie" + +#: cps/admin.py:1555 +msgid "Failed to extract at least One LDAP User" +msgstr "Extrakcia minimálne jedného LDAP používateľa zlyhala" + +#: cps/admin.py:1600 +msgid "Failed to Create at Least One LDAP User" +msgstr "Vytvorenie minimálne jedného LDAP používateľa zlyhalo" + +#: cps/admin.py:1613 +#, python-format +msgid "Error: %(ldaperror)s" +msgstr "Chyba: %(ldaperror)s" + +#: cps/admin.py:1617 +msgid "Error: No user returned in response of LDAP server" +msgstr "Chyba: Odpoveď LDAP servera neobsahuje žiadneho používateľa" + +#: cps/admin.py:1650 +msgid "At Least One LDAP User Not Found in Database" +msgstr "Minimálne jeden LDAP používateľ sa nenachádza v databáze" + +#: cps/admin.py:1652 +msgid "{} User Successfully Imported" +msgstr "Používateľ bol naimportovaný" + +#: cps/admin.py:1710 +msgid "DB Location is not Valid, Please Enter Correct Path" +msgstr "Umiestnenie databáze nie je platné, zadajte prosím správnu cestu" + +#: cps/admin.py:1730 +msgid "DB is not Writeable" +msgstr "Do databázy nie je možné zapisovať" + +#: cps/admin.py:1743 +msgid "Keyfile Location is not Valid, Please Enter Correct Path" +msgstr "Umiestnenie súboru s kľúčmi nie je platné, zadajte prosím správnu cestu" + +#: cps/admin.py:1747 +msgid "Certfile Location is not Valid, Please Enter Correct Path" +msgstr "Umiestnenie súboru s certifikátmi nie je platné, zadajte prosím správnu cestu" + +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "Heslo musí byť dlhé 1 až 40 znakov" + +#: cps/admin.py:1871 +msgid "Database Settings updated" +msgstr "Nastavenia databáze boli aktualizované" + +#: cps/admin.py:1879 +msgid "Database Configuration" +msgstr "Konfigurácia databázy" + +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." +msgstr "Vyplňte prosím všetky polia." + +#: cps/admin.py:1903 +msgid "E-mail is not from valid domain" +msgstr "E-mail nie je z platnej domény" + +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Pridať nového používateľa" + +#: cps/admin.py:1920 +#, python-format +msgid "User '%(user)s' created" +msgstr "Používateľ '%(user)s' bol vytvorený" + +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "Účet s týmto menom alebo e-mailovou adresou už existuje." + +#: cps/admin.py:1956 +#, python-format +msgid "User '%(nick)s' deleted" +msgstr "Používateľ '%(nick)s' bol zmazaný" + +#: cps/admin.py:1959 +msgid "Can't delete Guest User" +msgstr "Nie je možné zmazať používateľa Hosť" + +#: cps/admin.py:1962 +msgid "No admin user remaining, can't delete user" +msgstr "Nezostáva žiadny používateľ, nie je možné odobrať rolu správcu" + +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" +msgstr "E-mailová adresa nemôže byť prázdna a musí byť platná" + +#: cps/admin.py:2043 +#, python-format +msgid "User '%(nick)s' updated" +msgstr "Používateľ '%(nick)s' bol aktualizovaný" + +#: cps/converter.py:31 +msgid "not installed" +msgstr "nie je naištalované" + +#: cps/converter.py:32 +msgid "Execution permissions missing" +msgstr "Chýba právo na vykonanie" + +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 +#, python-format +msgid "Custom Column No.%(column)d does not exist in calibre database" +msgstr "Používateľom definovaný stĺpec č. %(column)d v Calibre databáze neexistuje" + +#: cps/db.py:993 cps/templates/config_edit.html:204 +#: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 +msgid "None" +msgstr "Žiadne" + +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" +msgstr "Vybraná kniha nie je dostupná. Súbor neexistuje alebo sa k nemu nedá pristupovať" + +#: cps/editbooks.py:164 cps/editbooks.py:1239 +msgid "User has no rights to upload cover" +msgstr "Používateľ nemá práva nahrať obálku knihy" + +#: cps/editbooks.py:184 cps/editbooks.py:729 +msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" +msgstr "Identifikátory nerozlišujú malé a veľké písmená, prepisuje sa starý identifikátor" + +#: cps/editbooks.py:226 +msgid "Metadata successfully updated" +msgstr "Metadáta boli úspešne aktualizované" + +#: cps/editbooks.py:244 +msgid "Error editing book: {}" +msgstr "Chyba pri úprave knihy: {}" + +#: cps/editbooks.py:301 +#, python-format +msgid "File %(file)s uploaded" +msgstr "Súbor %(file)s bol nahraný" + +#: cps/editbooks.py:329 +msgid "Source or destination format for conversion missing" +msgstr "Chýba zdrojový alebo cieľový formát pre prevod" + +#: cps/editbooks.py:337 +#, python-format +msgid "Book successfully queued for converting to %(book_format)s" +msgstr "Kniha bola úspešne zaradená na prevod do %(book_format)s" + +#: cps/editbooks.py:341 +#, python-format +msgid "There was an error converting this book: %(res)s" +msgstr "Vyskytla sa chyba pri prevode tejto knihy: %(res)s" + +#: cps/editbooks.py:648 +msgid "Uploaded book probably exists in the library, consider to change before upload new: " +msgstr "Nahrávaná kniha pravdepodobne existuje v knižnici, zvážte zmenu pred nahraním novej: " + +#: cps/editbooks.py:703 cps/editbooks.py:1031 +#, python-format +msgid "'%(langname)s' is not a valid language" +msgstr "'%(langname)s' nie je platný jazyk" + +#: cps/editbooks.py:741 cps/editbooks.py:1179 +#, python-format +msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" +msgstr "Prípona súboru '%(ext)s' nemôže byť nahraná na tento server" + +#: cps/editbooks.py:745 cps/editbooks.py:1183 +msgid "File to be uploaded must have an extension" +msgstr "Súbor ktorý sa má nahrať musí mať príponu" + +#: cps/editbooks.py:753 +#, python-format +msgid "File %(filename)s could not saved to temp dir" +msgstr "Súbor %(filename)s nebolo možné uložiť do dočasného adresára" + +#: cps/editbooks.py:773 +#, python-format +msgid "Failed to Move Cover File %(file)s: %(error)s" +msgstr "Zlyhal presun súboru obalky %(file)s: %(error)s" + +#: cps/editbooks.py:830 cps/editbooks.py:832 +msgid "Book Format Successfully Deleted" +msgstr "Kniha s formátom bola úspešne zmazaná" + +#: cps/editbooks.py:839 cps/editbooks.py:841 +msgid "Book Successfully Deleted" +msgstr "Kniha bola úspešne zmazaná" + +#: cps/editbooks.py:893 +msgid "You are missing permissions to delete books" +msgstr "Nemáte oprávnenia na mazanie kníh" + +#: cps/editbooks.py:943 +msgid "edit metadata" +msgstr "upraviť metadáta" + +#: cps/editbooks.py:992 +#, python-format +msgid "%(seriesindex)s is not a valid number, skipping" +msgstr "%(seriesindex)s nie je platné číslo, preskakuje sa" + +#: cps/editbooks.py:1174 +msgid "User has no rights to upload additional file formats" +msgstr "Používateľ nemá práva na nahranie dodatočných súborových formátov" + +#: cps/editbooks.py:1195 +#, python-format +msgid "Failed to create path %(path)s (Permission denied)." +msgstr "Nebolo možné vytvoriť cestu %(path)s (Povolenie zamietnuté)." + +#: cps/editbooks.py:1200 +#, python-format +msgid "Failed to store file %(file)s." +msgstr "Zlyhalo uloženie súboru: %(file)s." + +#: cps/editbooks.py:1224 +#, python-format +msgid "File format %(ext)s added to %(book)s" +msgstr "Súborový formát %(ext)s bol pridaný k %(book)s" + +#: cps/gdrive.py:58 +msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" +msgstr "Nastavenie Google Drive nie je dokončené, skúste deaktivovať a znovu aktivovať Google Drive" + +#: cps/gdrive.py:95 +msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" +msgstr "Doména spätného volania nie je verifikovaná, prosím, vykonajte kroky na verifikáciu domény v konzole Google vývojára" + +#: cps/helper.py:81 +#, python-format +msgid "%(format)s format not found for book id: %(book)d" +msgstr "Formát %(format)s sa nenašiel pre knihu s ID: %(book)d" + +#: cps/helper.py:88 cps/tasks/convert.py:75 +#, python-format +msgid "%(format)s not found on Google Drive: %(fn)s" +msgstr "%(format)s sa nenašiel na Google Drive: %(fn)s" + +#: cps/helper.py:93 +#, python-format +msgid "%(format)s not found: %(fn)s" +msgstr "%(format)s sa nenašiel: %(fn)s" + +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" +msgstr "Poslať do čítačky" + +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +msgid "This Email has been sent via Calibre-Web." +msgstr "Tento e-mail bol odoslaný skrz Calibre-Web." + +#: cps/helper.py:115 +msgid "Calibre-Web Test Email" +msgstr "Testovací e-mail Calibre-Web" + +#: cps/helper.py:116 +msgid "Test Email" +msgstr "Testovací e-mail" + +#: cps/helper.py:133 +msgid "Get Started with Calibre-Web" +msgstr "Začnite s aplikáciu Calibre-Web" + +#: cps/helper.py:138 +#, python-format +msgid "Registration Email for user: %(name)s" +msgstr "Registračný e-mail pre používateľa: %(name)s" + +#: cps/helper.py:149 cps/helper.py:155 +#, python-format +msgid "Convert %(orig)s to %(format)s and send to eReader" +msgstr "Previesť %(orig)s na %(format)s a odoslať do čítačky" + +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, python-format +msgid "Send %(format)s to eReader" +msgstr "Odoslať %(format)s do čítačky" + +#: cps/helper.py:222 +#, python-format +msgid "%(book)s send to eReader" +msgstr "%(book)s odoslaná do čítačky" + +#: cps/helper.py:227 +msgid "The requested file could not be read. Maybe wrong permissions?" +msgstr "Požadovaný súbor sa nedá čítať. Možne zlé oprávnenia?" + +#: cps/helper.py:342 +msgid "Read status could not set: {}" +msgstr "Status čítania nie je možné nastaviť: {}" + +#: cps/helper.py:365 +#, python-format +msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" +msgstr "Mazanie zložky pre knihu %(id)s zlyhalo, cesta má vnorené adresáre: %(path)s" + +#: cps/helper.py:371 +#, python-format +msgid "Deleting book %(id)s failed: %(message)s" +msgstr "Mazanie knihy %(id)s zlyhalo: %(message)s" + +#: cps/helper.py:382 +#, python-format +msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" +msgstr "Mazanie knihy %(id)s iba z databázy, cesta ku knihe v databáze nie je platná: %(path)s" + +#: cps/helper.py:447 +#, python-format +msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Premenovanie autora z: '%(src)s' na '%(dest)s' zlyhalo s chybou: %(error)s" + +#: cps/helper.py:519 cps/helper.py:528 +#, python-format +msgid "File %(file)s not found on Google Drive" +msgstr "Súbor %(file)s sa nenašiel na Google Drive" + +#: cps/helper.py:562 +#, python-format +msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" +msgstr "Zmena názvu knihy z: '%(src)s' na '%(dest)s' zlyhalo s chybou: %(error)s" + +#: cps/helper.py:582 +msgid "Error in rename file in path: {}" +msgstr "Chyba pri premenovaní v ceste: {}" + +#: cps/helper.py:600 +#, python-format +msgid "Book path %(path)s not found on Google Drive" +msgstr "Cesta ku knihe %(path)s sa nenašla na Google Drive" + +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "Pre túto poštovú adresu sa našiel existujúci účet" + +#: cps/helper.py:673 +msgid "This username is already taken" +msgstr "Toto meno používateľa sa už používa" + +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "Neplatný formát poštovej adresy" + +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "Heslo nedodržiava pravidlá validácie" + +#: cps/helper.py:852 +msgid "Python module 'advocate' is not installed but is needed for cover uploads" +msgstr "Python modul 'advocate' nie je nainštalovaný ale je potrebný pre nahrávanie obálok kníh" + +#: cps/helper.py:862 +msgid "Error Downloading Cover" +msgstr "Chyba pri sťahovaní obálky knihy" + +#: cps/helper.py:865 +msgid "Cover Format Error" +msgstr "Chyba formátu obálky knihy" + +#: cps/helper.py:868 +msgid "You are not allowed to access localhost or the local network for cover uploads" +msgstr "Nemáte povolené pristupovať na lokálneho hostiteľa alebo lokálnu sieť na pre nahrávanie obálok kníh" + +#: cps/helper.py:878 +msgid "Failed to create path for cover" +msgstr "Vytváranie cesty k obálke knihy zlyhalo" + +#: cps/helper.py:894 +msgid "Cover-file is not a valid image file, or could not be stored" +msgstr "Súbor obálky knihy nie je platný súbor s obrázkom alebo nie je uložený" + +#: cps/helper.py:905 +msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" +msgstr "Ako súbor obálky knihy sú podporované iba súbory jpg/jpeg/png/webp/bmp" + +#: cps/helper.py:917 +msgid "Invalid cover file content" +msgstr "Neplatný obsah súboru obalky knihy" + +#: cps/helper.py:921 +msgid "Only jpg/jpeg files are supported as coverfile" +msgstr "Ako súbor obálky knihy sú podporované iba súbory jpg/jpeg" + +#: cps/helper.py:973 +msgid "Unrar binary file not found" +msgstr "Binárny súbor pre Unrar sa nenašiel" + +#: cps/helper.py:984 +msgid "Error executing UnRar" +msgstr "Chyba pri spustení Unrar" + +#: cps/helper.py:1077 +msgid "Cover" +msgstr "Obálka knihy" + +#: cps/helper.py:1079 cps/templates/admin.html:216 +msgid "Queue all books for metadata backup" +msgstr "Zaradiť všetky knihy na zálohovanie metadát" + +#: cps/kobo_auth.py:90 +msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" +msgstr "Prosím, pristupujte k Calibre-Web z nie lokálneho hostiteľa aby ste získali platný API koncový bod pre Kobo zariadenie" + +#: cps/kobo_auth.py:116 +msgid "Kobo Setup" +msgstr "Nastavenie Kobo" + +#: cps/oauth_bb.py:77 +#, python-format +msgid "Register with %(provider)s" +msgstr "Zaregistrovať s %(provider)s" + +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 +#, python-format +msgid "Success! You are now logged in as: %(nickname)s" +msgstr "Úspech! Teraz ste prihlásený ako: %(nickname)s" + +#: cps/oauth_bb.py:148 +#, python-format +msgid "Link to %(oauth)s Succeeded" +msgstr "Spojenie na %(oauth)s bolo úspešné" + +#: cps/oauth_bb.py:155 +msgid "Login failed, No User Linked With OAuth Account" +msgstr "Prihlásenie zlyhalo, s OAuth účtom nie je spojený žiadny používateľ" + +#: cps/oauth_bb.py:197 +#, python-format +msgid "Unlink to %(oauth)s Succeeded" +msgstr "Odpojenie z %(oauth)s bolo úspešné" + +#: cps/oauth_bb.py:202 +#, python-format +msgid "Unlink to %(oauth)s Failed" +msgstr "Odpojenie z %(oauth)s zlyhalo" + +#: cps/oauth_bb.py:205 +#, python-format +msgid "Not Linked to %(oauth)s" +msgstr "Nie je pripojený k %(oauth)s" + +#: cps/oauth_bb.py:261 +msgid "Failed to log in with GitHub." +msgstr "Prihlásenie na GitHub zlyhalo." + +#: cps/oauth_bb.py:267 +msgid "Failed to fetch user info from GitHub." +msgstr "Získanie používateľa z GitHub-u zlyhalo." + +#: cps/oauth_bb.py:279 +msgid "Failed to log in with Google." +msgstr "Prihlásenie na Google zlyhalo." + +#: cps/oauth_bb.py:285 +msgid "Failed to fetch user info from Google." +msgstr "Získanie používateľa z Google zlyhalo." + +#: cps/oauth_bb.py:332 +msgid "GitHub Oauth error, please retry later." +msgstr "Chyba GitHub OAuth, skúste to prosím neskôr." + +#: cps/oauth_bb.py:335 +msgid "GitHub Oauth error: {}" +msgstr "Chyba GitHub OAuth: {}" + +#: cps/oauth_bb.py:356 +msgid "Google Oauth error, please retry later." +msgstr "Chyba Google OAuth, skúste to prosím neskôr." + +#: cps/oauth_bb.py:359 +msgid "Google Oauth error: {}" +msgstr "Chyba Google OAuth: {}" + +#: cps/opds.py:274 +msgid "{} Stars" +msgstr "{} Hviezdičiek" + +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 +msgid "Login" +msgstr "Prihlásiť sa" + +#: cps/remotelogin.py:74 cps/remotelogin.py:108 +msgid "Token not found" +msgstr "Žetón sa nenašiel" + +#: cps/remotelogin.py:83 cps/remotelogin.py:116 +msgid "Token has expired" +msgstr "Žetón expiroval" + +#: cps/remotelogin.py:92 +msgid "Success! Please return to your device" +msgstr "Úspech! Vráťte sa k vašemu zariadeniu" + +#: cps/render_template.py:42 cps/web.py:414 +msgid "Books" +msgstr "Knihy" + +#: cps/render_template.py:44 +msgid "Show recent books" +msgstr "Zobraziť nedávno čítané knihy" + +#: cps/render_template.py:45 cps/templates/index.xml:26 +msgid "Hot Books" +msgstr "Horúce knihy" + +#: cps/render_template.py:47 +msgid "Show Hot Books" +msgstr "Zobraziť horúce knihy" + +#: cps/render_template.py:49 cps/render_template.py:54 +msgid "Downloaded Books" +msgstr "Stiahnuté knihy" + +#: cps/render_template.py:51 cps/render_template.py:56 +#: cps/templates/user_table.html:167 +msgid "Show Downloaded Books" +msgstr "Zobraziť stiahnuté knihy" + +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 +msgid "Top Rated Books" +msgstr "Najlepšie hodnotené knihy" + +#: cps/render_template.py:61 cps/templates/user_table.html:161 +msgid "Show Top Rated Books" +msgstr "Zobraziť najlepšie hodnotené knihy" + +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 +msgid "Read Books" +msgstr "Prečítané knihy" + +#: cps/render_template.py:64 +msgid "Show Read and Unread" +msgstr "Zobraziť prečítané a neprečítané" + +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 +msgid "Unread Books" +msgstr "Neprečítané knihy" + +#: cps/render_template.py:68 +msgid "Show unread" +msgstr "Zobraziť neprečítané" + +#: cps/render_template.py:69 +msgid "Discover" +msgstr "Objaviť" + +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 +msgid "Show Random Books" +msgstr "Zobraziť náhodné knihy" + +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 +msgid "Categories" +msgstr "Kategórie" + +#: cps/render_template.py:74 cps/templates/user_table.html:158 +msgid "Show Category Section" +msgstr "Zobraziť časť Kategórie" + +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 +msgid "Series" +msgstr "Série" + +#: cps/render_template.py:77 cps/templates/user_table.html:157 +msgid "Show Series Section" +msgstr "Zobraziť časť Série" + +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 +msgid "Authors" +msgstr "Autori" + +#: cps/render_template.py:80 cps/templates/user_table.html:160 +msgid "Show Author Section" +msgstr "Zobraziť časť Autori" + +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 +msgid "Publishers" +msgstr "Vydavatelia" + +#: cps/render_template.py:84 cps/templates/user_table.html:163 +msgid "Show Publisher Section" +msgstr "Zobraziť časť vydavatelia" + +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 +msgid "Languages" +msgstr "Jazyky" + +#: cps/render_template.py:88 cps/templates/user_table.html:155 +msgid "Show Language Section" +msgstr "Zobraziť časť Jazyky" + +#: cps/render_template.py:89 cps/templates/index.xml:105 +msgid "Ratings" +msgstr "Hodnotenia" + +#: cps/render_template.py:91 cps/templates/user_table.html:164 +msgid "Show Ratings Section" +msgstr "Zobraziť časť Hodnotenia" + +#: cps/render_template.py:92 cps/templates/index.xml:113 +msgid "File formats" +msgstr "Súborové formáty" + +#: cps/render_template.py:94 cps/templates/user_table.html:165 +msgid "Show File Formats Section" +msgstr "Zobraziť časť Súborové formáty" + +#: cps/render_template.py:96 cps/web.py:776 +msgid "Archived Books" +msgstr "Archivované knihy" + +#: cps/render_template.py:98 cps/templates/user_table.html:166 +msgid "Show Archived Books" +msgstr "Zobraziť archivované knihy" + +#: cps/render_template.py:101 cps/web.py:807 +msgid "Books List" +msgstr "Zoznam kníh" + +#: cps/render_template.py:103 cps/templates/user_table.html:168 +msgid "Show Books List" +msgstr "Zobraziť zoznam kníh" + +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 +#: cps/templates/layout.html:46 cps/templates/layout.html:49 +#: cps/templates/search_form.html:227 +msgid "Search" +msgstr "Hľadať" + +#: cps/search.py:188 +msgid "Published after " +msgstr "Vydané po " + +#: cps/search.py:195 +msgid "Published before " +msgstr "Vydané pred " + +#: cps/search.py:217 +#, python-format +msgid "Rating <= %(rating)s" +msgstr "Hodnotenie <= %(rating)s" + +#: cps/search.py:219 +#, python-format +msgid "Rating >= %(rating)s" +msgstr "Hodnotenie >= %(rating)s" + +#: cps/search.py:221 +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" +msgstr "Status čítania = %(status)s" + +#: cps/search.py:324 +msgid "Error on search for custom columns, please restart Calibre-Web" +msgstr "Chyba pri čítaní používateľom definovaných stĺpcov, reštartujte prosím Calibre-Web" + +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 +msgid "Advanced Search" +msgstr "Rozšírené hľadanie" + +#: cps/shelf.py:49 cps/shelf.py:103 +msgid "Invalid shelf specified" +msgstr "Vybraná neplatná polica" + +#: cps/shelf.py:55 +msgid "Sorry you are not allowed to add a book to that shelf" +msgstr "Ľutujeme, do tejto police nemôžete pridať knihu" + +#: cps/shelf.py:64 +#, python-format +msgid "Book is already part of the shelf: %(shelfname)s" +msgstr "Kniha je už na polici: %(shelfname)s" + +#: cps/shelf.py:89 +#, python-format +msgid "Book has been added to shelf: %(sname)s" +msgstr "Kniha bola pridaná do police: %(sname)s" + +#: cps/shelf.py:108 +msgid "You are not allowed to add a book to the shelf" +msgstr "Nemáte povolené pridať knihu do tejto police" + +#: cps/shelf.py:126 +#, python-format +msgid "Books are already part of the shelf: %(name)s" +msgstr "Táto polica už obssahuje knihu: %(name)s" + +#: cps/shelf.py:138 +#, python-format +msgid "Books have been added to shelf: %(sname)s" +msgstr "Do police sa pridala kniha: %(sname)s" + +#: cps/shelf.py:145 +#, python-format +msgid "Could not add books to shelf: %(sname)s" +msgstr "Nemôžem pridať knihu do police: %(sname)s" + +#: cps/shelf.py:191 +#, python-format +msgid "Book has been removed from shelf: %(sname)s" +msgstr "Kniha bola odstránená z police: %(sname)s" + +#: cps/shelf.py:200 +msgid "Sorry you are not allowed to remove a book from this shelf" +msgstr "Ľutujeme, ale nie ste oprávnený odstrániť knihu z tejto police" + +#: cps/shelf.py:210 cps/templates/layout.html:157 +msgid "Create a Shelf" +msgstr "Vytvoriť policu" + +#: cps/shelf.py:218 +msgid "Sorry you are not allowed to edit this shelf" +msgstr "Ľutujeme, ale nie ste oprávnený upravovať túto policu" + +#: cps/shelf.py:220 +msgid "Edit a shelf" +msgstr "Upraviť policu" + +#: cps/shelf.py:229 +msgid "Error deleting Shelf" +msgstr "Chyba pri mazaní police" + +#: cps/shelf.py:231 +msgid "Shelf successfully deleted" +msgstr "Polica bol úspešne vymazaná" + +#: cps/shelf.py:281 +#, python-format +msgid "Change order of Shelf: '%(name)s'" +msgstr "Zmeniť poradie police: '%(name)s'" + +#: cps/shelf.py:316 +msgid "Sorry you are not allowed to create a public shelf" +msgstr "Ľutujeme, ale nie ste oprávnený vytvoriť verejnú policu" + +#: cps/shelf.py:333 +#, python-format +msgid "Shelf %(title)s created" +msgstr "Polica %(title)s bola vytvorená" + +#: cps/shelf.py:336 +#, python-format +msgid "Shelf %(title)s changed" +msgstr "Polica %(title)s bola zmenená" + +#: cps/shelf.py:350 +msgid "There was an error" +msgstr "Nastala chyba" + +#: cps/shelf.py:372 +#, python-format +msgid "A public shelf with the name '%(title)s' already exists." +msgstr "Verejná polica s názvom '%(title)s' už existuje." + +#: cps/shelf.py:383 +#, python-format +msgid "A private shelf with the name '%(title)s' already exists." +msgstr "Súkromná polica s názvom '%(title)s' už existuje." + +#: cps/shelf.py:465 +#, python-format +msgid "Shelf: '%(name)s'" +msgstr "Polica: '%(name)s'" + +#: cps/shelf.py:469 +msgid "Error opening shelf. Shelf does not exist or is not accessible" +msgstr "Chyba pri otváraní police. Polica neexistuje alebo je neprístupná" + +#: cps/tasks_status.py:46 cps/templates/layout.html:88 +#: cps/templates/tasks.html:7 +msgid "Tasks" +msgstr "Úlohy" + +#: cps/tasks_status.py:62 +msgid "Waiting" +msgstr "Čakajúca" + +#: cps/tasks_status.py:64 +msgid "Failed" +msgstr "Neúspešná" + +#: cps/tasks_status.py:66 +msgid "Started" +msgstr "Spustená" + +#: cps/tasks_status.py:68 +msgid "Finished" +msgstr "Hotová" + +#: cps/tasks_status.py:70 +msgid "Ended" +msgstr "Ukončená" + +#: cps/tasks_status.py:72 +msgid "Cancelled" +msgstr "Zrušená" + +#: cps/tasks_status.py:74 +msgid "Unknown Status" +msgstr "Neznámy stav" + +#: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 +msgid "Unexpected data while reading update information" +msgstr "Čítanie aktualizačnej informácie narazilo na neočakávané údaje" + +#: cps/updater.py:438 cps/updater.py:550 +msgid "No update available. You already have the latest version installed" +msgstr "Nie je dostupná žiadna aktualizácia. Máte nainštalovanú najnovšiu verziu" + +#: cps/updater.py:456 +msgid "A new update is available. Click on the button below to update to the latest version." +msgstr "Je dostupná nová aktualizácia. Ak chcete aktualizovať na najnovšiu verziu, kliknite na tlačidlo dolu." + +#: cps/updater.py:474 +msgid "Could not fetch update information" +msgstr "Nebolo možné stiahnuť aktualizačnú informáciu" + +#: cps/updater.py:484 +msgid "Click on the button below to update to the latest stable version." +msgstr "Ak chcete aktualizovať na najnovšiu stabilnú verziu, kliknite na tlačidlo dolu." + +#: cps/updater.py:493 cps/updater.py:507 cps/updater.py:518 +#, python-format +msgid "A new update is available. Click on the button below to update to version: %(version)s" +msgstr "Je dostupná nová aktualizácia. Kliknite na tlačidlo dolu, ak chcete aktualizovať na verziu: %(version)s" + +#: cps/updater.py:536 +msgid "No release information available" +msgstr "Nie je dostupná informácia o vydaní" + +#: cps/templates/index.html:6 cps/web.py:441 +msgid "Discover (Random Books)" +msgstr "Objaviť (Náhodné knihy)" + +#: cps/web.py:477 +msgid "Hot Books (Most Downloaded)" +msgstr "Horúce knihy (Najviac sťahované)" + +#: cps/web.py:508 +#, python-format +msgid "Downloaded books by %(user)s" +msgstr "Knihy stiahnuté: %(user)s" + +#: cps/web.py:541 +#, python-format +msgid "Author: %(name)s" +msgstr "Author: %(name)s" + +#: cps/web.py:577 +#, python-format +msgid "Publisher: %(name)s" +msgstr "Vydavateľ: %(name)s" + +#: cps/web.py:605 +#, python-format +msgid "Series: %(serie)s" +msgstr "Série: %(serie)s" + +#: cps/web.py:620 +msgid "Rating: None" +msgstr "Hodnotenie: Žiadne" + +#: cps/web.py:629 +#, python-format +msgid "Rating: %(rating)s stars" +msgstr "Hodnotenie: %(rating)s hviezdičiek" + +#: cps/web.py:645 +#, python-format +msgid "File format: %(format)s" +msgstr "Súborový formát: %(format)s" + +#: cps/web.py:682 +#, python-format +msgid "Category: %(name)s" +msgstr "Kategória: %(name)s" + +#: cps/web.py:711 +#, python-format +msgid "Language: %(name)s" +msgstr "Jazyk: %(name)s" + +#: cps/templates/admin.html:16 cps/web.py:949 +msgid "Downloads" +msgstr "Stiahnutia" + +#: cps/web.py:1051 +msgid "Ratings list" +msgstr "Zoznam hodnotení" + +#: cps/web.py:1078 +msgid "File formats list" +msgstr "Zoznam súborových formátov" + +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "Najskôr nastavte poštový server, prosím..." + +#: cps/web.py:1240 +#, python-format +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Úspech! Kniha bola zaradená na odoslanie do %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" +msgstr "Vyskytla sa chyba pri posielaní knihy: %(res)s" + +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "Nastavte vo vašom profile platnú e-mailovú adresu pre vašu čítačku." + +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "Počkajte, prosím minútku pred registráciou ďalšieho používateľa" + +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 +msgid "Register" +msgstr "Registrovať" + +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "Poštový server nie je nastavený, kontaktujte prosím správcu." + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." +msgstr "Vaša e-mailová adresa nie je povolená." + +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "Úspech! Potvrdzujúci e-mail bol odoslaný." + +#: cps/web.py:1348 cps/web.py:1366 +msgid "Cannot activate LDAP authentication" +msgstr "Nie je možné aktivovať LDAP autentifikáciu" + +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "Počkajte, prosím minútku pred opätovným prihlásením" + +#: cps/web.py:1376 +#, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "ste prihlásený ako: '%(nickname)s'" + +#: cps/web.py:1383 +#, python-format +msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" +msgstr "Záložné prihlásenie ako: '%(nickname)s', LDAP server je nedostupný alebo používateľ je neznámy" + +#: cps/web.py:1388 +#, python-format +msgid "Could not login: %(message)s" +msgstr "Nemôžem prihlásiť: %(message)s" + +#: cps/web.py:1392 cps/web.py:1417 +msgid "Wrong Username or Password" +msgstr "Nesprávne používateľské meno alebo heslo" + +#: cps/web.py:1399 +msgid "New Password was send to your email address" +msgstr "Na vašu e-mailovú adresu bolo odoslané nové heslo" + +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "Vyskytla sa neočakávaná chyba. Prosím, skúste to opäť neskôr." + +#: cps/web.py:1405 +msgid "Please enter valid username to reset password" +msgstr "Na resetovanie hesla zadajte platné používateľské meno" + +#: cps/web.py:1413 +#, python-format +msgid "You are now logged in as: '%(nickname)s'" +msgstr "Teraz ste prihlásený ako: '%(nickname)s'" + +#: cps/web.py:1471 cps/web.py:1521 +#, python-format +msgid "%(name)s's Profile" +msgstr "Profil pre %(name)s" + +#: cps/web.py:1487 +msgid "Success! Profile Updated" +msgstr "Úspech! Profil bol aktualizovaný" + +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Účet s touto e-mailovou adresou už existuje." + +#: cps/services/gmail.py:58 +msgid "Found no valid gmail.json file with OAuth information" +msgstr "Nenašiel sa súbor gmail.json s OAuth informáciou" + +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s bol odoslaný do čítačky" + +#: cps/tasks/convert.py:153 +#, python-format +msgid "Calibre ebook-convert %(tool)s not found" +msgstr "Nástroj pre prevod ebook-convert %(tool)s sa nenašiel" + +#: cps/tasks/convert.py:186 +#, python-format +msgid "%(format)s format not found on disk" +msgstr "Formát %(format)s sa nenachádza na disku" + +#: cps/tasks/convert.py:190 +msgid "Ebook converter failed with unknown error" +msgstr "Prevádzač e-kníh zlyhal s neznámou chybou" + +#: cps/tasks/convert.py:202 +#, python-format +msgid "Kepubify-converter failed: %(error)s" +msgstr "Prevádzač Kepubify zlyhal: %(error)s" + +#: cps/tasks/convert.py:224 +#, python-format +msgid "Converted file not found or more than one file in folder %(folder)s" +msgstr "Prevádzaný súbor sa nenašiel alebo viac ako jeden súbor v zložke %(folder)s" + +#: cps/tasks/convert.py:247 +#, python-format +msgid "Ebook-converter failed: %(error)s" +msgstr "Prevádzač e-kníh zlyhal: %(error)s" + +#: cps/tasks/convert.py:270 +#, python-format +msgid "Calibre failed with error: %(error)s" +msgstr "Calibre zlyhal s chybou: %(error)s" + +#: cps/tasks/convert.py:275 +msgid "Convert" +msgstr "Previesť" + +#: cps/tasks/database.py:28 +msgid "Reconnecting Calibre database" +msgstr "Spojenie s databázou sa znovu naväzuje" + +#: cps/tasks/mail.py:269 +msgid "E-mail" +msgstr "E-mail" + +#: cps/tasks/metadata_backup.py:46 +msgid "Backing up Metadata" +msgstr "Zálohovať metadáta" + +#: cps/tasks/thumbnail.py:96 +#, python-format +msgid "Generated %(count)s cover thumbnails" +msgstr "Bolo vygenerovaných %(count)s náhľadov obálok kníh" + +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 +msgid "Cover Thumbnails" +msgstr "Náhľad obálky knihy" + +#: cps/tasks/thumbnail.py:289 +msgid "Generated {0} series thumbnails" +msgstr "Bolo vygenerovaných {0} náhľadov pre série" + +#: cps/tasks/thumbnail.py:454 +msgid "Clearing cover thumbnail cache" +msgstr "Vyrovnávacia pamäť pre obálky kníh sa vyprázdňuje" + +#: cps/tasks/upload.py:38 cps/templates/admin.html:20 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 +msgid "Upload" +msgstr "Nahrať" + +#: cps/templates/admin.html:9 +msgid "Users" +msgstr "Používatelia" + +#: cps/templates/admin.html:13 cps/templates/login.html:9 +#: cps/templates/login.html:10 cps/templates/register.html:9 +#: cps/templates/user_edit.html:10 cps/templates/user_table.html:134 +msgid "Username" +msgstr "Meno používateľa" + +#: cps/templates/admin.html:14 cps/templates/register.html:14 +#: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 +msgid "Email" +msgstr "E-mail" + +#: cps/templates/admin.html:15 cps/templates/user_edit.html:28 +msgid "Send to eReader Email" +msgstr "Poslať na e-mail čítačky" + +#: cps/templates/admin.html:17 cps/templates/layout.html:91 +#: cps/templates/user_table.html:143 +msgid "Admin" +msgstr "Správca" + +#: cps/templates/admin.html:18 cps/templates/login.html:13 +#: cps/templates/login.html:14 cps/templates/user_edit.html:23 +msgid "Password" +msgstr "Heslo" + +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 +#: cps/templates/user_table.html:146 +msgid "Download" +msgstr "Stiahnuť" + +#: cps/templates/admin.html:23 +msgid "View Books" +msgstr "Zobraziť knihy" + +#: cps/templates/admin.html:24 cps/templates/user_table.html:131 +#: cps/templates/user_table.html:148 +msgid "Edit" +msgstr "Upraviť" + +#: cps/templates/admin.html:25 cps/templates/book_edit.html:17 +#: cps/templates/book_table.html:100 cps/templates/modal_dialogs.html:63 +#: cps/templates/modal_dialogs.html:116 cps/templates/user_edit.html:67 +#: cps/templates/user_table.html:149 +msgid "Delete" +msgstr "Zmazať" + +#: cps/templates/admin.html:26 +msgid "Public Shelf" +msgstr "Verejná polica" + +#: cps/templates/admin.html:55 +msgid "Import LDAP Users" +msgstr "Importovať LDAP používateľov" + +#: cps/templates/admin.html:62 +msgid "Email Server Settings" +msgstr "Nastavenia poštového servera" + +#: cps/templates/admin.html:67 cps/templates/email_edit.html:31 +msgid "SMTP Hostname" +msgstr "SMTP hostiteľ" + +#: cps/templates/admin.html:71 cps/templates/email_edit.html:35 +msgid "SMTP Port" +msgstr "SMTP port" + +#: cps/templates/admin.html:75 cps/templates/email_edit.html:39 +msgid "Encryption" +msgstr "Šifrovanie" + +#: cps/templates/admin.html:79 cps/templates/email_edit.html:47 +msgid "SMTP Login" +msgstr "SMTP prihlásenie" + +#: cps/templates/admin.html:83 cps/templates/admin.html:94 +#: cps/templates/email_edit.html:55 +msgid "From Email" +msgstr "Z poštovej adresy" + +#: cps/templates/admin.html:90 +msgid "Email Service" +msgstr "Poštová služba" + +#: cps/templates/admin.html:91 +msgid "Gmail via Oauth2" +msgstr "GMail skrz OAuthľ" + +#: cps/templates/admin.html:106 +msgid "Configuration" +msgstr "Konfigurácia" + +#: cps/templates/admin.html:109 +msgid "Calibre Database Directory" +msgstr "Adresár databázy Calibre" + +#: cps/templates/admin.html:113 cps/templates/config_edit.html:68 +msgid "Log Level" +msgstr "Úroveň denníka" + +#: cps/templates/admin.html:117 +msgid "Port" +msgstr "Port" + +#: cps/templates/admin.html:122 +msgid "External Port" +msgstr "Externý port" + +#: cps/templates/admin.html:129 cps/templates/config_view_edit.html:28 +msgid "Books per Page" +msgstr "Kníh na stránku" + +#: cps/templates/admin.html:133 +msgid "Uploads" +msgstr "Nahrávania" + +#: cps/templates/admin.html:137 +msgid "Anonymous Browsing" +msgstr "Anonymné prezeranie" + +#: cps/templates/admin.html:141 +msgid "Public Registration" +msgstr "Verejná registrácia" + +#: cps/templates/admin.html:145 +msgid "Magic Link Remote Login" +msgstr "Vzdialené prihlásenie Magic Link" + +#: cps/templates/admin.html:149 +msgid "Reverse Proxy Login" +msgstr "Prihlásenie na reverznú proxy" + +#: cps/templates/admin.html:154 cps/templates/config_edit.html:173 +msgid "Reverse Proxy Header Name" +msgstr "Meno hlavičky pre reverznú proxy" + +#: cps/templates/admin.html:159 +msgid "Edit Calibre Database Configuration" +msgstr "Upraviť configuráciu databázy Calibre" + +#: cps/templates/admin.html:160 +msgid "Edit Basic Configuration" +msgstr "Upraviť základnú konfiguráciu" + +#: cps/templates/admin.html:161 +msgid "Edit UI Configuration" +msgstr "Upraviť konfiguráciu používateľského rozhrania" + +#: cps/templates/admin.html:167 +msgid "Scheduled Tasks" +msgstr "Naplánované úlohy" + +#: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 +#: cps/templates/tasks.html:18 +msgid "Start Time" +msgstr "Začiatok" + +#: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 +msgid "Maximum Duration" +msgstr "Maximálne trvanie" + +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" +msgstr "Generovať náhľady" + +#: cps/templates/admin.html:182 +msgid "Generate series cover thumbnails" +msgstr "Generovať náhľady obálok pre série" + +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "Znovu naviazať spojenie s Calibre databázou" + +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "Vygenerovať záložné súbory pre metadáta" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "Obnoviť vyrovnávaciu pamäť pre náhľady" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Správa" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Stiahnuť ladiaci balík" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Zobraziť denníky" + +#: cps/templates/admin.html:211 +msgid "Restart" +msgstr "Reštart" + +#: cps/templates/admin.html:212 +msgid "Shutdown" +msgstr "Vypnúť" + +#: cps/templates/admin.html:221 +msgid "Version Information" +msgstr "Informácia o verzii" + +#: cps/templates/admin.html:225 +msgid "Version" +msgstr "Verzia" + +#: cps/templates/admin.html:226 +msgid "Details" +msgstr "Detaily" + +#: cps/templates/admin.html:232 +msgid "Current Version" +msgstr "Aktuálna verzia" + +#: cps/templates/admin.html:239 +msgid "Check for Update" +msgstr "Kontrola aktualizácie" + +#: cps/templates/admin.html:240 +msgid "Perform Update" +msgstr "Vykonať aktualizáciu" + +#: cps/templates/admin.html:253 +msgid "Are you sure you want to restart?" +msgstr "Skutočne chcete reštartovať?" + +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 +msgid "OK" +msgstr "V poriadku" + +#: cps/templates/admin.html:259 cps/templates/admin.html:273 +#: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 +#: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 +#: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 +#: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 +#: cps/templates/user_edit.html:144 +msgid "Cancel" +msgstr "Zrušiť" + +#: cps/templates/admin.html:271 +msgid "Are you sure you want to shutdown?" +msgstr "Skutočne chcete vypnúťť?" + +#: cps/templates/admin.html:283 +msgid "Updating, please do not reload this page" +msgstr "Aktualizuje sa, neskúšajte znovu načítať stránku" + +#: cps/templates/author.html:15 +msgid "via" +msgstr "cez" + +#: cps/templates/author.html:23 +msgid "In Library" +msgstr "V knižnici" + +#: cps/templates/author.html:26 cps/templates/index.html:74 +#: cps/templates/search.html:31 cps/templates/shelf.html:20 +msgid "Sort according to book date, newest first" +msgstr "Triediť podľa dátumu knihy, najnovšie najskôr" + +#: cps/templates/author.html:27 cps/templates/index.html:75 +#: cps/templates/search.html:32 cps/templates/shelf.html:21 +msgid "Sort according to book date, oldest first" +msgstr "Triediť podľa dátumu knihy, najstaršie najskôr" + +#: cps/templates/author.html:28 cps/templates/index.html:76 +#: cps/templates/search.html:33 cps/templates/shelf.html:22 +msgid "Sort title in alphabetical order" +msgstr "Triediť podľa názvu v abecednom poradí" + +#: cps/templates/author.html:29 cps/templates/index.html:77 +#: cps/templates/search.html:34 cps/templates/shelf.html:23 +msgid "Sort title in reverse alphabetical order" +msgstr "Triediť podľa názvu v obrátenom abecednom poradí" + +#: cps/templates/author.html:30 cps/templates/index.html:80 +#: cps/templates/search.html:37 cps/templates/shelf.html:26 +msgid "Sort according to publishing date, newest first" +msgstr "Triediť podľa dátumu vydania, najnovšie najskôr" + +#: cps/templates/author.html:31 cps/templates/index.html:81 +#: cps/templates/search.html:38 cps/templates/shelf.html:27 +msgid "Sort according to publishing date, oldest first" +msgstr "Triediť podľa dátumu vydania, najstaršie najskôr" + +#: cps/templates/author.html:56 cps/templates/author.html:115 +#: cps/templates/index.html:30 cps/templates/index.html:113 +#: cps/templates/search.html:67 cps/templates/shelf.html:55 +msgid "reduce" +msgstr "znížiť" + +#: cps/templates/author.html:99 +msgid "More by" +msgstr "Viac od" + +#: cps/templates/book_edit.html:11 +msgid "Delete Book" +msgstr "Zmazať knihu" + +#: cps/templates/book_edit.html:14 +msgid "Delete formats:" +msgstr "Zmazať formáty:" + +#: cps/templates/book_edit.html:25 +msgid "Convert book format:" +msgstr "Previesť knihu s formátom:" + +#: cps/templates/book_edit.html:30 +msgid "Convert from:" +msgstr "Previesť z:" + +#: cps/templates/book_edit.html:32 cps/templates/book_edit.html:39 +msgid "select an option" +msgstr "vybrať možnosť" + +#: cps/templates/book_edit.html:37 +msgid "Convert to:" +msgstr "Previesť do:" + +#: cps/templates/book_edit.html:46 +msgid "Convert book" +msgstr "Previesť knihu" + +#: cps/templates/book_edit.html:56 cps/templates/search_form.html:8 +msgid "Book Title" +msgstr "Názov knihy" + +#: cps/templates/book_edit.html:63 cps/templates/book_edit.html:271 +#: cps/templates/book_edit.html:289 cps/templates/search_form.html:12 +msgid "Author" +msgstr "Autor" + +#: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 +msgid "Description" +msgstr "Popis" + +#: cps/templates/book_edit.html:73 +msgid "Identifiers" +msgstr "Identifikátory" + +#: cps/templates/book_edit.html:77 cps/templates/book_edit.html:300 +msgid "Identifier Type" +msgstr "Typ identifikátora" + +#: cps/templates/book_edit.html:78 cps/templates/book_edit.html:301 +msgid "Identifier Value" +msgstr "Hodnota identifikátora" + +#: cps/templates/book_edit.html:79 cps/templates/book_edit.html:302 +#: cps/templates/user_table.html:24 +msgid "Remove" +msgstr "Odstrániť" + +#: cps/templates/book_edit.html:83 +msgid "Add Identifier" +msgstr "Pridať identifikátor" + +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 +msgid "Tags" +msgstr "Značka" + +#: cps/templates/book_edit.html:95 +msgid "Series ID" +msgstr "ID série" + +#: cps/templates/book_edit.html:99 +msgid "Rating" +msgstr "Hodnotenie" + +#: cps/templates/book_edit.html:104 +msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" +msgstr "Načítať obálku z URL (JPEG-obrázok sa stiahne a uloží v databáze)" + +#: cps/templates/book_edit.html:108 +msgid "Upload Cover from Local Disk" +msgstr "Nahrať obálku knihy z miestneho disku" + +#: cps/templates/book_edit.html:113 +msgid "Published Date" +msgstr "Dátum vydania" + +#: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 +msgid "Publisher" +msgstr "Vydavateľ" + +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 +msgid "Language" +msgstr "Jazyk" + +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 +msgid "Yes" +msgstr "Áno" + +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 +msgid "No" +msgstr "Nie" + +#: cps/templates/book_edit.html:201 +msgid "Upload Format" +msgstr "Formát nahrávania" + +#: cps/templates/book_edit.html:209 +msgid "View Book on Save" +msgstr "Zobraziť knihu pri ukladaní" + +#: cps/templates/book_edit.html:212 cps/templates/book_edit.html:230 +msgid "Fetch Metadata" +msgstr "Načítať metadáta" + +#: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 +#: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 +#: cps/templates/user_edit.html:142 +msgid "Save" +msgstr "Uložiť" + +#: cps/templates/book_edit.html:233 +msgid "Keyword" +msgstr "Kľúčové slovo" + +#: cps/templates/book_edit.html:234 +msgid "Search keyword" +msgstr "Vyhľadať kľúčové slovo" + +#: cps/templates/book_edit.html:240 +msgid "Click the cover to load metadata to the form" +msgstr "Kliknite na oblálku aby ste načítali metadáta do formulára" + +#: cps/templates/book_edit.html:247 cps/templates/book_edit.html:286 +msgid "Loading..." +msgstr "Načítava sa..." + +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 +#: cps/templates/user_edit.html:163 +msgid "Close" +msgstr "Zatvoriť" + +#: cps/templates/book_edit.html:278 cps/templates/book_edit.html:292 +msgid "Source" +msgstr "Zdroj" + +#: cps/templates/book_edit.html:287 +msgid "Search error!" +msgstr "Chyba pri vyhľadávaní!" + +#: cps/templates/book_edit.html:288 +msgid "No Result(s) found! Please try another keyword." +msgstr "Nič sa nenaslo! Skúste, prosím iné kľúčové slovo." + +#: cps/templates/book_table.html:12 cps/templates/book_table.html:69 +#: cps/templates/user_table.html:14 cps/templates/user_table.html:77 +#: cps/templates/user_table.html:100 +msgid "This Field is Required" +msgstr "Toto pole je povinné" + +#: cps/templates/book_table.html:37 +msgid "Merge selected books" +msgstr "Zlúčiť vybrané knihy" + +#: cps/templates/book_table.html:38 cps/templates/user_table.html:124 +msgid "Remove Selections" +msgstr "Odstrániť výbery" + +#: cps/templates/book_table.html:41 +msgid "Exchange author and title" +msgstr "Vymeniť autora a názov" + +#: cps/templates/book_table.html:47 +msgid "Update Title Sort automatically" +msgstr "Automaticky aktualizovať triedenie podľa názvu" + +#: cps/templates/book_table.html:51 +msgid "Update Author Sort automatically" +msgstr "Automaticky aktualizovať triedeni podľa autora" + +#: cps/templates/book_table.html:63 cps/templates/book_table.html:69 +msgid "Enter Title" +msgstr "Zadajte názov" + +#: cps/templates/book_table.html:63 cps/templates/config_view_edit.html:24 +#: cps/templates/shelf_edit.html:8 +msgid "Title" +msgstr "Názov" + +#: cps/templates/book_table.html:64 +msgid "Enter Title Sort" +msgstr "Zadajte triedenie podľa názvu knihy" + +#: cps/templates/book_table.html:64 +msgid "Title Sort" +msgstr "Triedenie podľa názvu knihy" + +#: cps/templates/book_table.html:65 +msgid "Enter Author Sort" +msgstr "Zadajte triedenie podľa autora knihy" + +#: cps/templates/book_table.html:65 +msgid "Author Sort" +msgstr "Triedenie podľa autora knihy" + +#: cps/templates/book_table.html:66 +msgid "Enter Authors" +msgstr "Zadajte autorov" + +#: cps/templates/book_table.html:67 +msgid "Enter Categories" +msgstr "Zadajte kategórie" + +#: cps/templates/book_table.html:68 +msgid "Enter Series" +msgstr "Zadajte série" + +#: cps/templates/book_table.html:69 +msgid "Series Index" +msgstr "Číslo v sérii" + +#: cps/templates/book_table.html:70 +msgid "Enter Languages" +msgstr "Zadajte jazyky" + +#: cps/templates/book_table.html:71 +msgid "Publishing Date" +msgstr "Dátum vydania" + +#: cps/templates/book_table.html:72 +msgid "Enter Publishers" +msgstr "Zadajte vydavateľov" + +#: cps/templates/book_table.html:73 +msgid "Enter comments" +msgstr "Zadajte komentáre" + +#: cps/templates/book_table.html:73 +msgid "Comments" +msgstr "Komentáre" + +#: cps/templates/book_table.html:75 +msgid "Archive Status" +msgstr "Stav archivácie" + +#: cps/templates/book_table.html:77 cps/templates/search_form.html:42 +msgid "Read Status" +msgstr "Stav čítania" + +#: cps/templates/book_table.html:80 cps/templates/book_table.html:82 +#: cps/templates/book_table.html:84 cps/templates/book_table.html:86 +#: cps/templates/book_table.html:90 cps/templates/book_table.html:92 +#: cps/templates/book_table.html:96 +msgid "Enter " +msgstr "Zadať " + +#: cps/templates/book_table.html:113 cps/templates/modal_dialogs.html:46 +#: cps/templates/tasks.html:36 +msgid "Are you really sure?" +msgstr "Naozaj to chcete?" + +#: cps/templates/book_table.html:117 +msgid "Books with Title will be merged from:" +msgstr "Kniha z názvom bude zlúčená s:" + +#: cps/templates/book_table.html:121 +msgid "Into Book with Title:" +msgstr "Na knihu s názvom:" + +#: cps/templates/book_table.html:126 +msgid "Merge" +msgstr "Zlúčiť" + +#: cps/templates/config_db.html:12 +msgid "Location of Calibre Database" +msgstr "Umiestnenie databázy Calibre" + +#: cps/templates/config_db.html:22 +msgid "Use Google Drive?" +msgstr "Používať Google Drive?" + +#: cps/templates/config_db.html:27 +msgid "Authenticate Google Drive" +msgstr "Autentifikovať Google Drive" + +#: cps/templates/config_db.html:32 +msgid "Google Drive Calibre folder" +msgstr "Calibre zložka na Google Drive" + +#: cps/templates/config_db.html:40 +msgid "Metadata Watch Channel ID" +msgstr "ID kanála na sledovanie metadát" + +#: cps/templates/config_db.html:43 +msgid "Revoke" +msgstr "Zrušiť" + +#: cps/templates/config_db.html:68 +msgid "New db location is invalid, please enter valid path" +msgstr "Nové umiestnenie databáze nie je platné, zadajte prosím správnu cestu" + +#: cps/templates/config_edit.html:18 +msgid "Server Configuration" +msgstr "Konfigurácia servera" + +#: cps/templates/config_edit.html:25 +msgid "Server Port" +msgstr "Port servera" + +#: cps/templates/config_edit.html:28 +msgid "SSL certfile location (leave it empty for non-SSL Servers)" +msgstr "Umiestnenie SSL certifikačného súboru (ponechať prázdne pre nie-SSL servery)" + +#: cps/templates/config_edit.html:35 +msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" +msgstr "Umiestnenie SSL súboru s kľúčom (ponechať prázdne pre nie-SSL servery)" + +#: cps/templates/config_edit.html:43 +msgid "Update Channel" +msgstr "Aktualizovať kanál" + +#: cps/templates/config_edit.html:45 +msgid "Stable" +msgstr "Stabilný" + +#: cps/templates/config_edit.html:46 +msgid "Nightly" +msgstr "Nočný" + +#: cps/templates/config_edit.html:50 +msgid "Trusted Hosts (Comma Separated)" +msgstr "Hostitelia s dôverou (oddelené čiarkou)" + +#: cps/templates/config_edit.html:61 +msgid "Logfile Configuration" +msgstr "Konfigurácia súboru denníka" + +#: cps/templates/config_edit.html:77 +msgid "Location and name of logfile (calibre-web.log for no entry)" +msgstr "Umiestnenie a meno denníkového súboru (calibre-web.log keď nezadané)" + +#: cps/templates/config_edit.html:82 +msgid "Enable Access Log" +msgstr "Povoliť denník pristupu" + +#: cps/templates/config_edit.html:85 +msgid "Location and name of access logfile (access.log for no entry)" +msgstr "Umiestnenie a meno denníkového súboru pre prístup (access.log keď nezadané)" + +#: cps/templates/config_edit.html:96 +msgid "Feature Configuration" +msgstr "Konfigurácia funkčnosti" + +#: cps/templates/config_edit.html:104 +msgid "Convert non-English characters in title and author while saving to disk" +msgstr "Previesť neanglické znaky v názve a mene autora počas ukladania na disk" + +#: cps/templates/config_edit.html:108 +msgid "Enable Uploads" +msgstr "Povoliť nahrávanie" + +#: cps/templates/config_edit.html:108 +msgid "(Please ensure that users also have upload permissions)" +msgstr "(Zaistite, prosím, že používateľ má tiež právo nahrávať)" + +#: cps/templates/config_edit.html:112 +msgid "Allowed Upload Fileformats" +msgstr "Povolené formáty pre nahrávanie" + +#: cps/templates/config_edit.html:118 +msgid "Enable Anonymous Browsing" +msgstr "Povoliť anonymné prechádzanie" + +#: cps/templates/config_edit.html:122 +msgid "Enable Public Registration" +msgstr "Povoliť verejnú registráciu" + +#: cps/templates/config_edit.html:127 +msgid "Use Email as Username" +msgstr "Použiť e-mailovú adresu ako meno používateľa" + +#: cps/templates/config_edit.html:132 +msgid "Enable Magic Link Remote Login" +msgstr "Povoliť vzdialené prihlasovanie Magic Link" + +#: cps/templates/config_edit.html:137 +msgid "Enable Kobo sync" +msgstr "Povoliť synchronizáciu Kobo" + +#: cps/templates/config_edit.html:142 +msgid "Proxy unknown requests to Kobo Store" +msgstr "Proxy neznáme žiadosti na obchod Kobo" + +#: cps/templates/config_edit.html:145 +msgid "Server External Port (for port forwarded API calls)" +msgstr "Externý port servera (pre portovo preposielané API volania)" + +#: cps/templates/config_edit.html:153 +msgid "Use Goodreads" +msgstr "Použiť Goodreads" + +#: cps/templates/config_edit.html:154 +msgid "Create an API Key" +msgstr "Vytvoriť kľúč API" + +#: cps/templates/config_edit.html:158 +msgid "Goodreads API Key" +msgstr "Goodreads API kľúč" + +#: cps/templates/config_edit.html:162 +msgid "Goodreads API Secret" +msgstr "Goodreads API tajomstvo" + +#: cps/templates/config_edit.html:169 +msgid "Allow Reverse Proxy Authentication" +msgstr "Povoliť reverznú proxy autentifikáciu" + +#: cps/templates/config_edit.html:180 +msgid "Login type" +msgstr "Typ prihlásenia" + +#: cps/templates/config_edit.html:182 +msgid "Use Standard Authentication" +msgstr "Použiť štandardnú autentifikáciu" + +#: cps/templates/config_edit.html:184 +msgid "Use LDAP Authentication" +msgstr "Použiť LDAP autentifikáciu" + +#: cps/templates/config_edit.html:187 +msgid "Use OAuth" +msgstr "Použiť OAuth" + +#: cps/templates/config_edit.html:194 +msgid "LDAP Server Host Name or IP Address" +msgstr "Hostiteľské meno alebo IP adresa LDAP servera" + +#: cps/templates/config_edit.html:198 +msgid "LDAP Server Port" +msgstr "Port LDAP servera" + +#: cps/templates/config_edit.html:202 +msgid "LDAP Encryption" +msgstr "LDAP šifrovanie" + +#: cps/templates/config_edit.html:205 +msgid "TLS" +msgstr "TLS" + +#: cps/templates/config_edit.html:206 +msgid "SSL" +msgstr "SSL" + +#: cps/templates/config_edit.html:210 +msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" +msgstr "Cesta k LDAP CA-certifikátu (potrebná iba pre autentifikáciu certifikátom klienta)" + +#: cps/templates/config_edit.html:217 +msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" +msgstr "Cesta k LDAP certifikátu (potrebná iba pre autentifikáciu certifikátom klienta)" + +#: cps/templates/config_edit.html:224 +msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" +msgstr "Cesta k LDAP súboru kľúča (potrebná iba pre autentifikáciu certifikátom klienta)" + +#: cps/templates/config_edit.html:233 +msgid "LDAP Authentication" +msgstr "LDAP autentifikácia" + +#: cps/templates/config_edit.html:235 +msgid "Anonymous" +msgstr "Anonymný" + +#: cps/templates/config_edit.html:236 +msgid "Unauthenticated" +msgstr "Neautentifikovaný" + +#: cps/templates/config_edit.html:237 +msgid "Simple" +msgstr "Jednoduchý" + +#: cps/templates/config_edit.html:242 +msgid "LDAP Administrator Username" +msgstr "Meno používateľa pre LDAP správcu" + +#: cps/templates/config_edit.html:248 +msgid "LDAP Administrator Password" +msgstr "Heslo pre LDAP správcu" + +#: cps/templates/config_edit.html:253 +msgid "LDAP Distinguished Name (DN)" +msgstr "LDAP rozlišovacie meno (DN)" + +#: cps/templates/config_edit.html:257 +msgid "LDAP User Object Filter" +msgstr "Filter pre LDAP objekt používateľa" + +#: cps/templates/config_edit.html:262 +msgid "LDAP Server is OpenLDAP?" +msgstr "LDAP server je OpenLDAP?" + +#: cps/templates/config_edit.html:264 +msgid "Following Settings are Needed For User Import" +msgstr "Pre import používateľa sú potrebné nasledovné nastavenia" + +#: cps/templates/config_edit.html:266 +msgid "LDAP Group Object Filter" +msgstr "Filter pre LDAP objekt skupiny" + +#: cps/templates/config_edit.html:270 +msgid "LDAP Group Name" +msgstr "Meno LDAP skupiny" + +#: cps/templates/config_edit.html:274 +msgid "LDAP Group Members Field" +msgstr "Pole členov LDAP skupiny" + +#: cps/templates/config_edit.html:278 +msgid "LDAP Member User Filter Detection" +msgstr "Detekcia filtra pre LDAP členstvo používateľa" + +#: cps/templates/config_edit.html:280 +msgid "Autodetect" +msgstr "Automatická detekcia" + +#: cps/templates/config_edit.html:281 +msgid "Custom Filter" +msgstr "Filter používateľa" + +#: cps/templates/config_edit.html:286 +msgid "LDAP Member User Filter" +msgstr "Filter pre LDAP členstvo požívateľa" + +#: cps/templates/config_edit.html:297 +#, python-format +msgid "Obtain %(provider)s OAuth Credential" +msgstr "Získať OAuth prístupové údaje pre %(provider)s" + +#: cps/templates/config_edit.html:300 +#, python-format +msgid "%(provider)s OAuth Client Id" +msgstr "%(provider)s OAuth klientské ID" + +#: cps/templates/config_edit.html:304 +#, python-format +msgid "%(provider)s OAuth Client Secret" +msgstr "%(provider)s OAuth klientské tajomstvo" + +#: cps/templates/config_edit.html:320 +msgid "External binaries" +msgstr "Externé binárky" + +#: cps/templates/config_edit.html:326 +msgid "Path to Calibre E-Book Converter" +msgstr "Cesta k Calibre prevádzaču e-kníh" + +#: cps/templates/config_edit.html:334 +msgid "Calibre E-Book Converter Settings" +msgstr "Nastavenie Calibre prevádzača e-kníh" + +#: cps/templates/config_edit.html:337 +msgid "Path to Kepubify E-Book Converter" +msgstr "Cesta Kepubify prevádzaču e-kníh" + +#: cps/templates/config_edit.html:345 +msgid "Location of Unrar binary" +msgstr "Binárny súbor pre Unrar sa nenašiel" + +#: cps/templates/config_edit.html:361 +msgid "Security Settings" +msgstr "Bezpečnostné nastavenia" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "Obmedziť neúspešné pokusy o prihlásenie" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "Ochrana sedenia" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "Základná" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "Silná" + +#: cps/templates/config_edit.html:380 +msgid "User Password policy" +msgstr "Zásady pre používateľské heslá" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "Minimálna dĺžka hesla" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "Vyžadovať číslo" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "Vyžadovať malé písmená" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "Vyžadovať veľké písmená" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "Vyžadovať špeciálne znaky" + +#: cps/templates/config_view_edit.html:17 +msgid "View Configuration" +msgstr "Zobraziť konfiguráciu" + +#: cps/templates/config_view_edit.html:32 +msgid "No. of Random Books to Display" +msgstr "Počet kníh na náhodné zobrazenie" + +#: cps/templates/config_view_edit.html:36 +msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" +msgstr "Počet autorov na zobrazenie pred ukrytím (0=Zakázať ukrývanie)" + +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 +msgid "Theme" +msgstr "Téma" + +#: cps/templates/config_view_edit.html:42 +msgid "Standard Theme" +msgstr "Štandardná téma" + +#: cps/templates/config_view_edit.html:43 +msgid "caliBlur! Dark Theme" +msgstr "tmavá téma caliBlur!" + +#: cps/templates/config_view_edit.html:47 +msgid "Regular Expression for Ignoring Columns" +msgstr "Regulárny výraz pre ignorované stĺpce" + +#: cps/templates/config_view_edit.html:51 +msgid "Link Read/Unread Status to Calibre Column" +msgstr "Prepojiť stav Prečítané/Neprečítané do Calibre stĺpca" + +#: cps/templates/config_view_edit.html:60 +msgid "View Restrictions based on Calibre column" +msgstr "Zobraziť obmedzenia založené na Calibre stĺpcoch" + +#: cps/templates/config_view_edit.html:69 +msgid "Regular Expression for Title Sorting" +msgstr "Regulárny výraz pre triedenie podľa názvu knihy" + +#: cps/templates/config_view_edit.html:80 +msgid "Default Settings for New Users" +msgstr "Predvolené nastavenia pre nových používateľov" + +#: cps/templates/config_view_edit.html:88 cps/templates/user_edit.html:96 +msgid "Admin User" +msgstr "Používateľ Správca" + +#: cps/templates/config_view_edit.html:92 cps/templates/user_edit.html:101 +msgid "Allow Downloads" +msgstr "Povoliť sťahovanie" + +#: cps/templates/config_view_edit.html:96 cps/templates/user_edit.html:105 +msgid "Allow eBook Viewer" +msgstr "Povoliť zobrazovač e-knihy" + +#: cps/templates/config_view_edit.html:101 cps/templates/user_edit.html:110 +msgid "Allow Uploads" +msgstr "Povoliť nahrávanie" + +#: cps/templates/config_view_edit.html:106 cps/templates/user_edit.html:115 +msgid "Allow Edit" +msgstr "Povoliť úpravu" + +#: cps/templates/config_view_edit.html:111 cps/templates/user_edit.html:120 +msgid "Allow Delete Books" +msgstr "Povoliť mazanie kníh" + +#: cps/templates/config_view_edit.html:116 cps/templates/user_edit.html:126 +msgid "Allow Changing Password" +msgstr "Povoliť zmenu hesla" + +#: cps/templates/config_view_edit.html:120 cps/templates/user_edit.html:130 +msgid "Allow Editing Public Shelves" +msgstr "Povoliť úpravu verejných políc" + +#: cps/templates/config_view_edit.html:123 +msgid "Default Language" +msgstr "Predvolený jazyk" + +#: cps/templates/config_view_edit.html:131 +msgid "Default Visible Language of Books" +msgstr "Predvolené viditeľné jazyky pre knihy" + +#: cps/templates/config_view_edit.html:147 +msgid "Default Visibilities for New Users" +msgstr "Predvolené viditeľnosti pre nových používateľov" + +#: cps/templates/config_view_edit.html:163 cps/templates/user_edit.html:84 +#: cps/templates/user_table.html:154 +msgid "Show Random Books in Detail View" +msgstr "Ukázať náhodné knihy v detailnom zobrazení" + +#: cps/templates/config_view_edit.html:166 cps/templates/user_edit.html:87 +msgid "Add Allowed/Denied Tags" +msgstr "Pridať Povolené/Zakázané značky" + +#: cps/templates/config_view_edit.html:167 +msgid "Add Allowed/Denied custom column values" +msgstr "Pridať Povolené/Zakázané používateľom definované hodnoty stĺpca" + +#: cps/templates/detail.html:77 cps/templates/detail.html:91 +msgid "Read in Browser" +msgstr "Čítať v prezerači" + +#: cps/templates/detail.html:100 cps/templates/detail.html:120 +msgid "Listen in Browser" +msgstr "Počúvať v prezerači" + +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 +#, python-format +msgid "Book %(index)s of %(range)s" +msgstr "Kniha %(index)s z %(range)s" + +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 +msgid "Published" +msgstr "Vydané" + +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 +msgid "Mark As Unread" +msgstr "Označiť ako neprečítané" + +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 +msgid "Mark As Read" +msgstr "Označiť ako prečítané" + +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 +msgid "Read" +msgstr "Čítať" + +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 +msgid "Restore from archive" +msgstr "Obnoviť z archívu" + +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 +msgid "Add to archive" +msgstr "Pridať do archívu" + +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 +msgid "Archived" +msgstr "Archivovaný" + +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 +msgid "Description:" +msgstr "Popis:" + +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 +msgid "Add to shelf" +msgstr "Pridať do police" + +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 +#: cps/templates/search.html:22 +msgid "(Public)" +msgstr "(Verejné)" + +#: cps/templates/detail.html:339 +msgid "Edit Metadata" +msgstr "Upraviť metadáta" + +#: cps/templates/email_edit.html:13 +msgid "Email Account Type" +msgstr "Typ e-mailového účtu" + +#: cps/templates/email_edit.html:15 +msgid "Standard Email Account" +msgstr "Štandardný e-mailový účet" + +#: cps/templates/email_edit.html:16 +msgid "Gmail Account" +msgstr "Gmail účet" + +#: cps/templates/email_edit.html:22 +msgid "Setup Gmail Account" +msgstr "Nastaviť Gmail účet" + +#: cps/templates/email_edit.html:24 +msgid "Revoke Gmail Access" +msgstr "Zrušiť Gmail účet" + +#: cps/templates/email_edit.html:42 +msgid "STARTTLS" +msgstr "STARTTLS" + +#: cps/templates/email_edit.html:43 +msgid "SSL/TLS" +msgstr "SSL/TLS" + +#: cps/templates/email_edit.html:51 +msgid "SMTP Password" +msgstr "SMTP heslo" + +#: cps/templates/email_edit.html:58 +msgid "Attachment Size Limit" +msgstr "Limit pre veľkosť prílohy" + +#: cps/templates/email_edit.html:66 +msgid "Save and Send Test Email" +msgstr "Uložiť a poslať testovací e-mail" + +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 +#: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 +msgid "Back" +msgstr "Naspäť" + +#: cps/templates/email_edit.html:74 +msgid "Allowed Domains (Whitelist)" +msgstr "Povolené domény (Biely zoznam)" + +#: cps/templates/email_edit.html:78 cps/templates/email_edit.html:105 +msgid "Add Domain" +msgstr "Pridať doménu" + +#: cps/templates/email_edit.html:81 cps/templates/email_edit.html:108 +#: cps/templates/user_table.html:27 +msgid "Add" +msgstr "Pridať" + +#: cps/templates/email_edit.html:86 cps/templates/email_edit.html:96 +msgid "Enter domainname" +msgstr "Zadajte doménové meno" + +#: cps/templates/email_edit.html:92 +msgid "Denied Domains (Blacklist)" +msgstr "Zakázané domény (Čierny zoznam)" + +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 +msgid "Next" +msgstr "Ďalší" + +#: cps/templates/generate_kobo_auth_url.html:6 +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Otvoriť súbor .kobo/Kobo/Kobo eReader.conf v textovom editore a pridať (alebo upraviť):" + +#: cps/templates/generate_kobo_auth_url.html:11 +msgid "Kobo Token:" +msgstr "Kobo žetón:" + +#: cps/templates/grid.html:21 +msgid "List" +msgstr "Zoznam" + +#: cps/templates/http_error.html:34 +msgid "Calibre-Web Instance is unconfigured, please contact your administrator" +msgstr "Inštancia Calibre-Web nie je nastavené, kontaktujte prosím vašeho správcu" + +#: cps/templates/http_error.html:44 +msgid "Create Issue" +msgstr "Vytvoriť hlásenie problému" + +#: cps/templates/http_error.html:51 +msgid "Return to Home" +msgstr "Návrat domov" + +#: cps/templates/http_error.html:53 +msgid "Logout User" +msgstr "Odhlásiť používateľa" + +#: cps/templates/index.html:71 +msgid "Sort ascending according to download count" +msgstr "Zotriediť podľa počtu stiahnutí vzostupne" + +#: cps/templates/index.html:72 +msgid "Sort descending according to download count" +msgstr "Zotriediť podľa počtu stiahnutí zostupne" + +#: cps/templates/index.html:78 cps/templates/search.html:35 +#: cps/templates/shelf.html:24 +msgid "Sort authors in alphabetical order" +msgstr "Zotriediť autorov v abecednom poradí" + +#: cps/templates/index.html:79 cps/templates/search.html:36 +#: cps/templates/shelf.html:25 +msgid "Sort authors in reverse alphabetical order" +msgstr "Zotriediť autorov v obrátenom abecednom poradí" + +#: cps/templates/index.html:83 +msgid "Sort ascending according to series index" +msgstr "Zotriediť podľa čísla série vzostupne" + +#: cps/templates/index.html:84 +msgid "Sort descending according to series index" +msgstr "Zotriediť podľa čísla série zostupne" + +#: cps/templates/index.xml:7 +msgid "Start" +msgstr "Začať" + +#: cps/templates/index.xml:19 +msgid "Alphabetical Books" +msgstr "Knihy podľa abecedy" + +#: cps/templates/index.xml:23 +msgid "Books sorted alphabetically" +msgstr "Knihy zotriedené podľa abecedy" + +#: cps/templates/index.xml:30 +msgid "Popular publications from this catalog based on Downloads." +msgstr "Populárne publikácie z tohoto katalógu založené na počte stiahnutí." + +#: cps/templates/index.xml:37 +msgid "Popular publications from this catalog based on Rating." +msgstr "Populárne publikácie z tohoto katalógu založené na hodnotení." + +#: cps/templates/index.xml:40 +msgid "Recently added Books" +msgstr "Naposledy pridané knihy" + +#: cps/templates/index.xml:44 +msgid "The latest Books" +msgstr "Najnovšie knihy" + +#: cps/templates/index.xml:47 +msgid "Random Books" +msgstr "Náhodné knihy" + +#: cps/templates/index.xml:74 +msgid "Books ordered by Author" +msgstr "Knihy usporiadané podľa autora" + +#: cps/templates/index.xml:81 +msgid "Books ordered by publisher" +msgstr "Knihy usporiadané podľa vydavateľa" + +#: cps/templates/index.xml:88 +msgid "Books ordered by category" +msgstr "Knihy usporiadané podľa kategórie" + +#: cps/templates/index.xml:95 +msgid "Books ordered by series" +msgstr "Knihy usporiadané podľa série" + +#: cps/templates/index.xml:102 +msgid "Books ordered by Languages" +msgstr "Knihy usporiadané podľa jazyka" + +#: cps/templates/index.xml:109 +msgid "Books ordered by Rating" +msgstr "Knihy usporiadané podľa hodnotenia" + +#: cps/templates/index.xml:117 +msgid "Books ordered by file formats" +msgstr "Knihy usporiadané podľa súborových formátov" + +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 +msgid "Shelves" +msgstr "Police" + +#: cps/templates/index.xml:124 +msgid "Books organized in shelves" +msgstr "Knihy organizované v policiach" + +#: cps/templates/layout.html:26 cps/templates/login.html:30 +msgid "Home" +msgstr "Domov" + +#: cps/templates/layout.html:32 +msgid "Toggle Navigation" +msgstr "Prepnúť navigáciu" + +#: cps/templates/layout.html:47 +msgid "Search Library" +msgstr "Prehľadávať knižnicu" + +#: cps/templates/layout.html:65 cps/templates/layout.html:94 +msgid "Account" +msgstr "Účet" + +#: cps/templates/layout.html:71 cps/templates/layout.html:96 +msgid "Logout" +msgstr "Odhlásiť sa" + +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Nahráva sa..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Chyba" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Nahrávanie ukončené, spracováva sa, počkajte prosím..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Nastavenia" + +#: cps/templates/layout.html:135 +msgid "Please do not refresh the page" +msgstr "Prosím, neskúšajte znovu načítať stránku" + +#: cps/templates/layout.html:145 +msgid "Browse" +msgstr "Prechádzať" + +#: cps/templates/layout.html:158 cps/templates/stats.html:3 +msgid "About" +msgstr "O programe" + +#: cps/templates/layout.html:172 +msgid "Previous" +msgstr "Predchádzajúci" + +#: cps/templates/layout.html:199 +msgid "Book Details" +msgstr "Detailu o knihe" + +#: cps/templates/list.html:22 +msgid "Grid" +msgstr "Mriežka" + +#: cps/templates/login.html:18 +msgid "Remember Me" +msgstr "Zapamätať si ma" + +#: cps/templates/login.html:23 +msgid "Forgot Password?" +msgstr "Zabudli ste heslo?" + +#: cps/templates/login.html:34 +msgid "Log in with Magic Link" +msgstr "Prihlásiť sa cez Magic Link" + +#: cps/templates/logviewer.html:6 +msgid "Show Calibre-Web Log: " +msgstr "Ukázať Calibre-Web denník " + +#: cps/templates/logviewer.html:8 +msgid "Calibre-Web Log: " +msgstr "Calibre-Web denník: " + +#: cps/templates/logviewer.html:8 +msgid "Stream output, can't be displayed" +msgstr "Prúdový výstup, nedá sa zobraziť" + +#: cps/templates/logviewer.html:12 +msgid "Show Access Log: " +msgstr "Ukázať denník prístupu: " + +#: cps/templates/logviewer.html:18 +msgid "Download Calibre-Web Log" +msgstr "Stiahnuť Calibre-Web denník" + +#: cps/templates/logviewer.html:21 +msgid "Download Access Log" +msgstr "Stiahnuť denník prístupu" + +#: cps/templates/modal_dialogs.html:6 +msgid "Select Allowed/Denied Tags" +msgstr "Vybrať Povolené/Zakázané značky" + +#: cps/templates/modal_dialogs.html:7 +msgid "Select Allowed/Denied Custom Column Values" +msgstr "Vybrať Povolené/Zakázané používateľom definované hodnoty stĺpca" + +#: cps/templates/modal_dialogs.html:8 +msgid "Select Allowed/Denied Tags of User" +msgstr "Vybrať Povolené/Zakázané značky pre používateľa" + +#: cps/templates/modal_dialogs.html:9 +msgid "Select Allowed/Denied Custom Column Values of User" +msgstr "Vybrať Povolené/Zakázané používateľom definované hodnoty stĺpca pre používateľa" + +#: cps/templates/modal_dialogs.html:15 +msgid "Enter Tag" +msgstr "Zadať štítok" + +#: cps/templates/modal_dialogs.html:24 +msgid "Add View Restriction" +msgstr "Pridať obmedzenie zobrazenia" + +#: cps/templates/modal_dialogs.html:50 +msgid "This book format will be permanently erased from database" +msgstr "Tento formát knihy bude navždy vymazaný z databázy" + +#: cps/templates/modal_dialogs.html:51 +msgid "This book will be permanently erased from database" +msgstr "Táto kniha bude navždy vymazaná z databázy" + +#: cps/templates/modal_dialogs.html:52 +msgid "and hard disk" +msgstr "a pevný disk" + +#: cps/templates/modal_dialogs.html:56 +msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." +msgstr "Dôležitá poznámka pre Kobo: zmazané knihy zostanú na každom spárovanom Kobo zariadení." + +#: cps/templates/modal_dialogs.html:57 +msgid "Books must first be archived and the device synced before a book can safely be deleted." +msgstr "Kniha musí byť najskôr archivovaná a zariadenie synchronizované pred tým než môže byť kniha bezpečne zmazaná." + +#: cps/templates/modal_dialogs.html:76 +msgid "Choose File Location" +msgstr "Vyberte umiestnenie súboru" + +#: cps/templates/modal_dialogs.html:82 +msgid "type" +msgstr "typ" + +#: cps/templates/modal_dialogs.html:83 +msgid "name" +msgstr "meno" + +#: cps/templates/modal_dialogs.html:84 +msgid "size" +msgstr "veľkosť" + +#: cps/templates/modal_dialogs.html:90 +msgid "Parent Directory" +msgstr "Rodičovský adresár" + +#: cps/templates/modal_dialogs.html:98 +msgid "Select" +msgstr "Vybrať" + +#: cps/templates/modal_dialogs.html:134 cps/templates/tasks.html:45 +msgid "Ok" +msgstr "Ok" + +#: cps/templates/osd.xml:5 +msgid "Calibre-Web eBook Catalog" +msgstr "Katalóg e-kníh Calibre-Web" + +#: cps/templates/read.html:6 +msgid "epub Reader" +msgstr "čítačka epub" + +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 +msgid "Light" +msgstr "Svetlé" + +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 +msgid "Dark" +msgstr "Tmavé" + +#: cps/templates/read.html:83 +msgid "Sepia" +msgstr "Sépia" + +#: cps/templates/read.html:84 +msgid "Black" +msgstr "Čierne" + +#: cps/templates/read.html:88 +msgid "Reflow text when sidebars are open." +msgstr "Preformátovať text keď sú otvorené bočné panely." + +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "Veľkosť písma" + +#: cps/templates/readcbr.html:8 +msgid "Comic Reader" +msgstr "Čítačka komiksov" + +#: cps/templates/readcbr.html:75 +msgid "Keyboard Shortcuts" +msgstr "Klávesové skratky" + +#: cps/templates/readcbr.html:78 +msgid "Previous Page" +msgstr "Predchádzajúca stránka" + +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 +msgid "Next Page" +msgstr "Nasledujúca stránka" + +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "Zobrazenie na jednej stránke" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "Zobrazenie dlhý pás" + +#: cps/templates/readcbr.html:82 +msgid "Scale to Best" +msgstr "Zmeniť mierku na najlepšie" + +#: cps/templates/readcbr.html:83 +msgid "Scale to Width" +msgstr "Zmeniť mierku na šírku" + +#: cps/templates/readcbr.html:84 +msgid "Scale to Height" +msgstr "Zmeniť mierku na výšku" + +#: cps/templates/readcbr.html:85 +msgid "Scale to Native" +msgstr "Zmeniť mierku na prirodzenú" + +#: cps/templates/readcbr.html:86 +msgid "Rotate Right" +msgstr "Otočiť doprava" + +#: cps/templates/readcbr.html:87 +msgid "Rotate Left" +msgstr "Otočiť doľava" + +#: cps/templates/readcbr.html:88 +msgid "Flip Image" +msgstr "Prevrátiť obrázok" + +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "Zobraziť" + +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "Jedna stránka" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "Dlhý pás" + +#: cps/templates/readcbr.html:119 +msgid "Scale" +msgstr "Mierka" + +#: cps/templates/readcbr.html:122 +msgid "Best" +msgstr "Najlepšie" + +#: cps/templates/readcbr.html:123 +msgid "Width" +msgstr "Na výšku" + +#: cps/templates/readcbr.html:124 +msgid "Height" +msgstr "Na šírku" + +#: cps/templates/readcbr.html:125 +msgid "Native" +msgstr "Prirodzené" + +#: cps/templates/readcbr.html:130 +msgid "Rotate" +msgstr "Otočiť" + +#: cps/templates/readcbr.html:141 +msgid "Flip" +msgstr "Prevrátiť" + +#: cps/templates/readcbr.html:144 +msgid "Horizontal" +msgstr "Horizontálne" + +#: cps/templates/readcbr.html:145 +msgid "Vertical" +msgstr "Vertikálne" + +#: cps/templates/readcbr.html:150 +msgid "Direction" +msgstr "Smer" + +#: cps/templates/readcbr.html:153 +msgid "Left to Right" +msgstr "Zľava doprava" + +#: cps/templates/readcbr.html:154 +msgid "Right to Left" +msgstr "Sprava doľava" + +#: cps/templates/readcbr.html:162 +msgid "Reset to Top" +msgstr "Resetovať na vrch" + +#: cps/templates/readcbr.html:163 +msgid "Remember Position" +msgstr "Zapamätať si pozíciu" + +#: cps/templates/readcbr.html:168 +msgid "Scrollbar" +msgstr "Posúvatko" + +#: cps/templates/readcbr.html:171 +msgid "Show" +msgstr "Ukázať" + +#: cps/templates/readcbr.html:172 +msgid "Hide" +msgstr "Skryť" + +#: cps/templates/readdjvu.html:5 +msgid "DJVU Reader" +msgstr "DJVU čítačka" + +#: cps/templates/readpdf.html:32 +msgid "PDF Reader" +msgstr "PDF čítačka" + +#: cps/templates/readtxt.html:6 +msgid "txt Reader" +msgstr "textová čítačka" + +#: cps/templates/register.html:4 +msgid "Register New Account" +msgstr "Registrovať nový účet" + +#: cps/templates/register.html:10 +msgid "Choose a username" +msgstr "Vyberte si meno používateľa" + +#: cps/templates/register.html:15 +msgid "Your Email" +msgstr "Váš e-mail" + +#: cps/templates/remote_login.html:5 +msgid "Magic Link - Authorise New Device" +msgstr "Magic Link - Autorizovať nové zariadenie" + +#: cps/templates/remote_login.html:7 +msgid "On another device, login and visit:" +msgstr "Na inom zariadení, prihlásiť sa a navštíviť:" + +#: cps/templates/remote_login.html:11 +msgid "Once verified, you will automatically be logged in on this device." +msgstr "Po verifikácii budete automaticky prihlásený na tomto zariadení." + +#: cps/templates/remote_login.html:14 +msgid "This verification link will expire in 10 minutes." +msgstr "Toto verifikačné prepojenie expiruje za 10 minút." + +#: cps/templates/schedule_edit.html:33 +msgid "Generate Series Cover Thumbnails" +msgstr "Vygenerovať náhľady obálok kníh pre série" + +#: cps/templates/search.html:6 +msgid "No Results Found" +msgstr "Nič sa nenašlo" + +#: cps/templates/search.html:7 +msgid "Search Term:" +msgstr "Vyhľadať výraz:" + +#: cps/templates/search.html:9 +msgid "Results for:" +msgstr "Výsledky pre:" + +#: cps/templates/search_form.html:21 +msgid "Published Date From" +msgstr "Dátum vydania od" + +#: cps/templates/search_form.html:31 +msgid "Published Date To" +msgstr "Dátum vydania do" + +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 +msgid "Exclude Tags" +msgstr "Vylúčiť značky" + +#: cps/templates/search_form.html:78 +msgid "Exclude Series" +msgstr "Vylúčiť série" + +#: cps/templates/search_form.html:96 +msgid "Exclude Shelves" +msgstr "Vylúčiť police" + +#: cps/templates/search_form.html:116 +msgid "Exclude Languages" +msgstr "Vylúčiť jazyky" + +#: cps/templates/search_form.html:127 +msgid "Extensions" +msgstr "Rozšírenia" + +#: cps/templates/search_form.html:135 +msgid "Exclude Extensions" +msgstr "Vylúčiť rozšírenia" + +#: cps/templates/search_form.html:145 +msgid "Rating Above" +msgstr "Hodnotenie lepšie ako" + +#: cps/templates/search_form.html:149 +msgid "Rating Below" +msgstr "Hodnotenie horšie ako" + +#: cps/templates/search_form.html:181 +msgid "From:" +msgstr "Od:" + +#: cps/templates/search_form.html:191 +msgid "To:" +msgstr "Do:" + +#: cps/templates/shelf.html:13 +msgid "Delete this Shelf" +msgstr "Zmazať túto poličku" + +#: cps/templates/shelf.html:14 +msgid "Edit Shelf Properties" +msgstr "Upraviť vlastnosti police" + +#: cps/templates/shelf.html:17 +msgid "Arrange books manually" +msgstr "Usporiadať knihy manuálne" + +#: cps/templates/shelf.html:18 +msgid "Disable Change order" +msgstr "Znemožniť zmenu poradia" + +#: cps/templates/shelf.html:18 +msgid "Enable Change order" +msgstr "Povoloť zmenu poradia" + +#: cps/templates/shelf_edit.html:14 +msgid "Share with Everyone" +msgstr "Zdieľať s kýmkoľvek" + +#: cps/templates/shelf_edit.html:21 +msgid "Sync this shelf with Kobo device" +msgstr "Synchronizovať túto policu so zariadením Kobo" + +#: cps/templates/shelf_order.html:5 +msgid "Drag to Rearrange Order" +msgstr "Potiahnite pre zmenu poradia" + +#: cps/templates/shelf_order.html:33 +msgid "Hidden Book" +msgstr "Skryté chyby" + +#: cps/templates/stats.html:7 +msgid "Library Statistics" +msgstr "Štatistiky police" + +#: cps/templates/stats.html:12 +msgid "Books in this Library" +msgstr "Knihy v tejto knižnici" + +#: cps/templates/stats.html:16 +msgid "Authors in this Library" +msgstr "Autori v tejto knižnici" + +#: cps/templates/stats.html:20 +msgid "Categories in this Library" +msgstr "Kategórie v tejto knižnici" + +#: cps/templates/stats.html:24 +msgid "Series in this Library" +msgstr "Série v tejto knižnici" + +#: cps/templates/stats.html:29 +msgid "System Statistics" +msgstr "Systémove štatistiky" + +#: cps/templates/stats.html:33 +msgid "Program" +msgstr "Program" + +#: cps/templates/stats.html:34 +msgid "Installed Version" +msgstr "Nainštalovaná verzia" + +#: cps/templates/tasks.html:12 +msgid "User" +msgstr "Používateľ" + +#: cps/templates/tasks.html:14 +msgid "Task" +msgstr "Úloha" + +#: cps/templates/tasks.html:15 +msgid "Status" +msgstr "Stav" + +#: cps/templates/tasks.html:16 +msgid "Progress" +msgstr "Pokrok" + +#: cps/templates/tasks.html:17 +msgid "Run Time" +msgstr "Čas spustenia" + +#: cps/templates/tasks.html:20 +msgid "Actions" +msgstr "Akcie" + +#: cps/templates/tasks.html:40 +msgid "This task will be cancelled. Any progress made by this task will be saved." +msgstr "Táto úloha bude zrušená. Akýkoľvek pokrok vykonaný v tejto úlohe bude uložený." + +#: cps/templates/tasks.html:41 +msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." +msgstr "Ak je toto naplánovaná úloha, bude znovu spustená v najbližšom naplánovanom čase." + +#: cps/templates/user_edit.html:20 +msgid "Reset user Password" +msgstr "Resetovať heslo používateľa" + +#: cps/templates/user_edit.html:43 +msgid "Language of Books" +msgstr "Jazyk kníh" + +#: cps/templates/user_edit.html:54 +msgid "OAuth Settings" +msgstr "Nastavenia OAuth" + +#: cps/templates/user_edit.html:56 +msgid "Link" +msgstr "Pripojiť" + +#: cps/templates/user_edit.html:58 +msgid "Unlink" +msgstr "Odpojiť" + +#: cps/templates/user_edit.html:64 +msgid "Kobo Sync Token" +msgstr "Synchronizačný žetón Kobo" + +#: cps/templates/user_edit.html:66 +msgid "Create/View" +msgstr "Vytvoriť/Zobraziť" + +#: cps/templates/user_edit.html:70 +msgid "Force full kobo sync" +msgstr "Vynútiť úplnú synchronizáciu Kobo" + +#: cps/templates/user_edit.html:88 +msgid "Add allowed/Denied Custom Column Values" +msgstr "Pridať povolené/zakázané užívateľom definovaných hodnôt stĺpca" + +#: cps/templates/user_edit.html:137 +msgid "Sync only books in selected shelves with Kobo" +msgstr "Synchronizovať s Kobo iba knihy vo vybraných policiach" + +#: cps/templates/user_edit.html:147 cps/templates/user_table.html:169 +msgid "Delete User" +msgstr "Zmazať používateľa" + +#: cps/templates/user_edit.html:159 +msgid "Generate Kobo Auth URL" +msgstr "Vygenerovať autentifikačné URL pre Kobo" + +#: cps/templates/user_table.html:80 cps/templates/user_table.html:103 +msgid "Select..." +msgstr "Vybrať..." + +#: cps/templates/user_table.html:131 +msgid "Edit User" +msgstr "Upraviť používateľa" + +#: cps/templates/user_table.html:134 +msgid "Enter Username" +msgstr "Upraviť meno používateľa" + +#: cps/templates/user_table.html:135 +msgid "Enter Email" +msgstr "Zadať e-mail" + +#: cps/templates/user_table.html:136 +msgid "Enter eReader Email" +msgstr "Zadať e-mail pre čítačku" + +#: cps/templates/user_table.html:136 +msgid "eReader Email" +msgstr "e-mail pre čítačku" + +#: cps/templates/user_table.html:137 +msgid "Locale" +msgstr "Nastavenie jazyka" + +#: cps/templates/user_table.html:138 +msgid "Visible Book Languages" +msgstr "Viditeľné jazyky kníh" + +#: cps/templates/user_table.html:139 +msgid "Edit Allowed Tags" +msgstr "Upraviť povolené znaťky" + +#: cps/templates/user_table.html:139 +msgid "Allowed Tags" +msgstr "Povolené značky" + +#: cps/templates/user_table.html:140 +msgid "Edit Denied Tags" +msgstr "Upraviť zakázané značky" + +#: cps/templates/user_table.html:140 +msgid "Denied Tags" +msgstr "Zakázané značky" + +#: cps/templates/user_table.html:141 +msgid "Edit Allowed Column Values" +msgstr "Upraviť povolené hodnoty stĺpca" + +#: cps/templates/user_table.html:141 +msgid "Allowed Column Values" +msgstr "Povolené hodnoty stĺpca" + +#: cps/templates/user_table.html:142 +msgid "Edit Denied Column Values" +msgstr "Upraviť zakázané hodnoty stĺpca" + +#: cps/templates/user_table.html:142 +msgid "Denied Column Values" +msgstr "Zakázané hodnoty stĺpca" + +#: cps/templates/user_table.html:144 +msgid "Change Password" +msgstr "Zmeniť heslo" + +#: cps/templates/user_table.html:147 +msgid "View" +msgstr "Zobraziť" + +#: cps/templates/user_table.html:150 +msgid "Edit Public Shelves" +msgstr "Upraviť verejné police" + +#: cps/templates/user_table.html:152 +msgid "Sync selected Shelves with Kobo" +msgstr "Synchronizovať vybrané police s Kobo" + +#: cps/templates/user_table.html:156 +msgid "Show Read/Unread Section" +msgstr "Zobraziť sekciu Prečítané/Neprečítané" + diff --git a/cps/translations/sv/LC_MESSAGES/messages.mo b/cps/translations/sv/LC_MESSAGES/messages.mo index a934bd8d..f5873c17 100644 Binary files a/cps/translations/sv/LC_MESSAGES/messages.mo and b/cps/translations/sv/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/sv/LC_MESSAGES/messages.po b/cps/translations/sv/LC_MESSAGES/messages.po index 88faf43e..0510f7d6 100644 --- a/cps/translations/sv/LC_MESSAGES/messages.po +++ b/cps/translations/sv/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/Calibre-Web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2021-05-13 11:00+0000\n" "Last-Translator: Jonatan Nyberg \n" "Language: sv\n" @@ -16,496 +16,505 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Statistik" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Server startas om, vänligen uppdatera sidan" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Stänger servern, vänligen stäng fönstret" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Återanslutning lyckades" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Okänt kommando" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "Boken är i kö för att skicka till %(kindlemail)s" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "Testa e-post i kö för att skicka till %(email)s, vänligen kontrollera Uppgifter för resultat" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Okänd" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Administrationssida" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Grundläggande konfiguration" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Användargränssnitt konfiguration" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Redigera användare" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Alla" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Användaren hittades inte" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} användare har tagits bort" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Visa alla" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Felaktig begäran" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Gästnamn kan inte ändras" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Gäst kan inte ha den här rollen" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Ingen administratörsanvändare kvar, kan inte ta bort administratörsrollen" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "Värdet måste vara sant eller falskt" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Ogiltig roll" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Gästen kan inte ha den här vyn" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "Ogiltig vy" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Gästens språk bestäms automatiskt och kan inte ställas in" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Inget giltigt språk anges" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Inget giltigt bokspråk anges" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Parameter hittades inte" -#: cps/admin.py:567 +#: cps/admin.py:571 #, fuzzy msgid "Invalid Read Column" msgstr "Ogiltig roll" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web konfiguration uppdaterad" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Vill du verkligen ta bort Kobo-token?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Vill du verkligen ta bort den här domänen?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Vill du verkligen ta bort den här användaren?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Är du säker på att du vill ta bort hyllan?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Är du säker på att du vill ändra språk för valda användare?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "Är du säker på att du vill ändra synliga bokspråk för valda användare?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Är du säker på att du vill ändra den valda rollen för de valda användarna?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Är du säker på att du vill ändra de valda begränsningarna för de valda användarna?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "Är du säker på att du vill ändra de valda synlighetsbegränsningarna för de valda användarna?" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Är du säker på att du vill ändra den valda rollen för de valda användarna?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Är du säker på att du vill stoppa Calibre-Web?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Förneka" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Tillåt" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Taggen hittades inte" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Ogiltig åtgärd" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json är inte konfigurerad för webbapplikation" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Loggfilens plats är inte giltig, vänligen ange rätt sökväg" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "Åtkomstloggplatsens plats är inte giltig, vänligen ange rätt sökväg" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "Vänligen ange en LDAP-leverantör, port, DN och användarobjektidentifierare" -#: cps/admin.py:1179 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Ange giltigt användarnamn för att återställa lösenordet" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP-gruppobjektfilter måste ha en \"%s\"-formatidentifierare" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP-gruppobjektfilter har omatchande parentes" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP-användarobjektfilter måste ha en \"%s\"-formatidentifierare" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP-användarobjektfilter har omatchad parentes" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "Användarfilter för LDAP-medlemmar måste ha en \"%s\"-formatidentifierare" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "Användarfilter för LDAP-medlemmar har omatchad parentes" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP-certifikat, certifikat eller nyckelplats är inte giltigt, vänligen ange rätt sökväg" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Lägg till ny användare" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Ändra SMTP-inställningar" -#: cps/admin.py:1270 -#, fuzzy -msgid "Gmail Account Verification Successful" -msgstr "Verifiering av G-mail-kontot lyckades" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Databasfel: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "Testa e-post i kö för att skicka till %(email)s, vänligen kontrollera Uppgifter för resultat" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Det gick inte att skicka Testmeddelandet: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Vänligen konfigurera din e-postadress först..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "E-postserverinställningar uppdaterade" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Ett okänt fel uppstod. Försök igen senare." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Redigera användaren %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "Lösenord för användaren %(user)s återställd" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Konfigurera SMTP-postinställningarna först..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Visaren för loggfil" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Begär uppdateringspaketet" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Hämtar uppdateringspaketet" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Packar upp uppdateringspaketet" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Ersätta filer" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Databasanslutningarna är stängda" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Stoppar server" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Uppdatering klar, tryck på okej och uppdatera sidan" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Uppdateringen misslyckades:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP-fel" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Anslutningsfel" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Tiden ute när du etablerade anslutning" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Allmänt fel" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "Uppdateringsfilen kunde inte sparas i Temp Dir" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 #, fuzzy msgid "Failed to extract at least One LDAP User" msgstr "Det gick inte att skapa minst en LDAP-användare" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "Det gick inte att skapa minst en LDAP-användare" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "Fel: %(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "Fel: Ingen användare återges som svar på LDAP-servern" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "Minst en LDAP-användare hittades inte i databasen" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} användare har importerats" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "DB-plats är inte giltig, vänligen ange rätt sökväg" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "DB är inte skrivbar" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "Keyfile-platsen är inte giltig, vänligen ange rätt sökväg" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "Certfile-platsen är inte giltig, vänligen ange rätt sökväg" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "E-postserverinställningar uppdaterade" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Funktion konfiguration" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Fyll i alla fält!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "E-posten är inte från giltig domän" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Lägg till ny användare" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Användaren '%(user)s' skapad" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "Hittade ett befintligt konto för den här e-postadressen eller namnet." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Användaren '%(nick)s' borttagen" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Det går inte att ta bort gästanvändaren" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Ingen adminstratörsanvändare kvar, kan inte ta bort användaren" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Användaren '%(nick)s' uppdaterad" @@ -518,122 +527,122 @@ msgstr "inte installerad" msgid "Execution permissions missing" msgstr "Körningstillstånd saknas" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "Anpassad kolumn n.%(column)d finns inte i calibre-databasen" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Ingen" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Hoppsan! Vald boktitel är inte tillgänglig. Filen finns inte eller är inte tillgänglig" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "Identifierare är inte skiftlägeskänsliga, skriver över gammal identifierare" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadata uppdaterades" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "Filen %(file)s uppladdad" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Källa eller målformat för konvertering saknas" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "Boken är i kö för konvertering till %(book_format)s" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Det gick inte att konvertera den här boken: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Uppladdad bok finns förmodligen i biblioteket, överväg att ändra innan du laddar upp nya: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s är inte ett giltigt språk" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "Filändelsen '%(ext)s' får inte laddas upp till den här servern" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Filen som ska laddas upp måste ha en ändelse" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "Filen %(filename)s kunde inte sparas i temp dir" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "Det gick inte att flytta omslagsfil %(file)s: %(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "Bokformat har tagits bort" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "Boken har tagits bort" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "redigera metadata" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "Det gick inte att skapa sökväg %(path)s (behörighet nekad)." -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Det gick inte att lagra filen %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "Filformatet %(ext)s lades till %(book)s" @@ -646,182 +655,189 @@ msgstr "Installationen av Google Drive är inte klar, försök att inaktivera oc msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Återuppringningsdomänen är inte verifierad, följ stegen för att verifiera domänen i Google utvecklarkonsol" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(format)s formatet hittades inte för bok-id: %(book)d" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(format)s hittades inte på Google Drive: %(fn)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s hittades inte: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Skicka till Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Detta e-postmeddelande har skickats via Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web test e-post" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Test e-post" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Kom igång med Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Registrera e-post för användare: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Konvertera %(orig)s till %(format)s och skicka till Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Skicka %(format)s till Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Skicka till Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "Den begärda filen kunde inte läsas. Kanske fel behörigheter?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Borttagning av bokmapp för boken %(id)s misslyckades, sökvägen har undermappar: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Borttagning av boken %(id)s misslyckades: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, fuzzy, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "Borttagning av boken %(id)s, boksökväg inte giltig: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Byt namn på titel från: \"%(src)s\" till \"%(dest)s\" misslyckades med fel: %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Filen %(file)s hittades inte på Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Byt namn på titel från: \"%(src)s\" till \"%(dest)s\" misslyckades med fel: %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Boksökvägen %(path)s hittades inte på Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "Hittade ett befintligt konto för den här e-postadressen" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Detta användarnamn är redan taget" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Ogiltigt e-postadressformat" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Fel vid hämtning av omslaget" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Fel på omslagsformat" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Det gick inte att skapa sökväg för omslag" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "Omslagsfilen är inte en giltig bildfil eller kunde inte lagras" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "Endast jpg/jpeg/png/webp/bmp-filer stöds som omslagsfil" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "Endast jpg/jpeg-filer stöds som omslagsfil" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "Unrar binär fil hittades inte" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "Fel vid körning av UnRar" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Upptäck" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "Vänligen få tillgång till calibre-web från icke localhost för att få giltig api_endpoint för Kobo-enhet" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo-installation" @@ -830,9 +846,9 @@ msgstr "Kobo-installation" msgid "Register with %(provider)s" msgstr "Registrera dig med %(provider)s" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "du är nu inloggad som: \"%(nickname)s\"" #: cps/oauth_bb.py:148 @@ -891,12 +907,13 @@ msgstr "Google Oauth-fel, försök igen senare." msgid "Google Oauth error: {}" msgstr "Google Oauth-fel: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} stjärnor" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Logga in" @@ -912,149 +929,158 @@ msgstr "Token har löpt ut" msgid "Success! Please return to your device" msgstr "Lyckades! Vänligen återvänd till din enhet" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Böcker" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Visa senaste böcker" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Heta böcker" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Visa heta böcker" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Hämtade böcker" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Visa hämtade böcker" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Bäst rankade böcker" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Visa böcker med bästa betyg" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Lästa böcker" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Visa lästa och olästa" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Olästa böcker" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Visa olästa" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Upptäck" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Visa slumpmässiga böcker" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Kategorier" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Visa kategorival" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Serier" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Visa serieval" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Författare" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Visa författarval" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Förlag" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Visa urval av förlag" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Språk" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Visa språkval" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Betyg" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Visa val av betyg" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Filformat" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Visa val av filformat" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Arkiverade böcker" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Visa arkiverade böcker" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Boklista" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Visa boklista" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Sök" @@ -1077,15 +1103,15 @@ msgid "Rating >= %(rating)s" msgstr "Betyg >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Lässtatus = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Avancerad sökning" @@ -1136,7 +1162,7 @@ msgstr "Boken har tagits bort från hyllan: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Skapa en hylla" @@ -1163,73 +1189,73 @@ msgstr "Boken har tagits bort" msgid "Change order of Shelf: '%(name)s'" msgstr "Ändra ordning på hyllan: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Hyllan %(title)s skapad" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Hyllan %(title)s ändrad" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Det fanns ett fel" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "En offentlig hylla med namnet \"%(title)s\" finns redan." -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "En privat hylla med namnet \"%(title)s\" finns redan." -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Hylla: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Fel vid öppning av hyllan. Hylla finns inte eller är inte tillgänglig" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Uppgifter" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Väntar" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Misslyckades" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Startad" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Klar" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Okänd status" @@ -1262,146 +1288,185 @@ msgstr "En ny uppdatering är tillgänglig. Klicka på knappen nedan för att up msgid "No release information available" msgstr "Ingen versionsinformation tillgänglig" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Upptäck (slumpmässiga böcker)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Heta böcker (mest hämtade)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "Hämtade böcker av %(user)s" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Författare: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Förlag: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Serier: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Betyg: %(rating)s stars" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Filformat: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategori: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Språk: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Hämtningar" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Betygslista" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Lista över filformat" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "Boken är i kö för att skicka till %(kindlemail)s" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Konfigurera SMTP-postinställningarna först..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "Boken är i kö för att skicka till %(eReadermail)s" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "Det gick inte att skicka den här boken: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "Konfigurera din kindle-e-postadress först..." -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "E-postservern är inte konfigurerad, kontakta din administratör!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Registrera" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "E-postservern är inte konfigurerad, kontakta din administratör!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "Din e-post är inte tillåten att registrera" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Bekräftelsemail skickades till ditt e-postkonto." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "Det går inte att aktivera LDAP-autentisering" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "du är nu inloggad som: \"%(nickname)s\"" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Det gick inte att logga in: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Fel användarnamn eller lösenord" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Nytt lösenord skickades till din e-postadress" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Ett okänt fel uppstod. Försök igen senare." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Ange giltigt användarnamn för att återställa lösenordet" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Du är nu inloggad som: \"%(nickname)s\"" +msgstr "du är nu inloggad som: \"%(nickname)s\"" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)ss profil" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Profilen uppdaterad" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Hittade ett befintligt konto för den här e-postadressen" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "Hittade ingen giltig gmail.json-fil med OAuth-information" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Skicka till Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1444,35 +1509,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "redigera metadata" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Ladda upp" @@ -1488,15 +1553,15 @@ msgstr "Smeknamn" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "E-post" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Administratör" @@ -1506,8 +1571,8 @@ msgstr "Administratör" msgid "Password" msgstr "Lösenord" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Hämta" @@ -1532,16 +1597,12 @@ msgstr "Ta bort" msgid "Public Shelf" msgstr "Publik hylla" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Lägg till ny användare" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "Importera LDAP-användare" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Inställningar för SMTP-e-postserver" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1562,11 +1623,12 @@ msgstr "SMTP-inloggning" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Från meddelande" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "E-posttjänst" #: cps/templates/admin.html:91 @@ -1639,102 +1701,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Administration" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "Hämta felsökningspaketet" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Visa loggfiler" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Anslut till Calibre DB igen" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Starta om Calibre-Web" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Stoppa Calibre-Web" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Version" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detaljer" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Aktuell version" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Sök efter uppdatering" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Utför uppdatering" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Är du säker på att du vill starta om Calibre-Web?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Ok" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Avbryt" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Är du säker på att du vill stoppa Calibre-Web?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Uppdaterar, vänligen uppdatera inte sidan" @@ -1824,7 +1888,7 @@ msgid "Author" msgstr "Författare" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Beskrivning" @@ -1849,7 +1913,7 @@ msgstr "Ta bort" msgid "Add Identifier" msgstr "Lägg till identifierare" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Taggar" @@ -1874,23 +1938,23 @@ msgid "Published Date" msgstr "Publiceringsdatum" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Förlag" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Språk" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Ja" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Nej" @@ -1907,8 +1971,8 @@ msgid "Fetch Metadata" msgstr "Hämta metadata" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1931,8 +1995,8 @@ msgstr "Klicka på omslaget för att läsa in metadata till formuläret" msgid "Loading..." msgstr "Läser in..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Stäng" @@ -2160,7 +2224,7 @@ msgid "Enable Uploads" msgstr "Aktivera uppladdning" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2176,7 +2240,7 @@ msgid "Enable Public Registration" msgstr "Aktivera offentlig registrering" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "Använd e-post som användarnamn" #: cps/templates/config_edit.html:132 @@ -2366,6 +2430,52 @@ msgstr "Sökväg till Kepubify calibre e-bokkonverterare" msgid "Location of Unrar binary" msgstr "Plats för Unrar-binär" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth-inställningar" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Återställ användarlösenordet" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Visa konfiguration" @@ -2378,7 +2488,7 @@ msgstr "Antal slumpmässiga böcker att visa" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "Antal författare att visa innan de döljs (0 = inaktivera dölja)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Tema" @@ -2469,81 +2579,84 @@ msgstr "Lägg till tillåtna/avvisade taggar" msgid "Add Allowed/Denied custom column values" msgstr "Lägg till tillåtna/avvisade anpassade kolumnvärden" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Läs i webbläsaren" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Lyssna i webbläsaren" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, fuzzy, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Publicerad" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Markera som oläst" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Markera som läst" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Läst" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Återställ från arkivet" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Lägg till i arkivet" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Arkiverad" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Beskrivning:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Lägg till hyllan" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Publik)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Redigera metadata" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Välj servertyp" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Använd standard e-postkonto" #: cps/templates/email_edit.html:16 #, fuzzy -msgid "Gmail Account with OAuth2 Verification" -msgstr "Gmail-konto med OAuth2-verifiering" +msgid "Gmail Account" +msgstr "Välj servertyp" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Ställ in Gmail-kontot som e-postserver" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2566,10 +2679,11 @@ msgid "Attachment Size Limit" msgstr "Gräns för bilagestorlek" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Spara inställningarna och skicka test-e-post" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Tillbaka" @@ -2595,13 +2709,13 @@ msgstr "Ange domännamn" msgid "Denied Domains (Blacklist)" msgstr "Avvisade domäner för registrering" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Nästa" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "Öppna filen .kobo/Kobo eReader.conf i en textredigerare och lägg till (eller redigera):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "Öppna filen .kobo/Kobo/Kobo eReader.conf i en textredigerare och lägg till (eller redigera):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2612,20 +2726,20 @@ msgstr "Kobo Sync Token" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "E-postservern är inte konfigurerad, kontakta din administratör!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "Skapa ärende" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Tillbaka till hemmet" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2655,80 +2769,80 @@ msgstr "Sortera stigande enligt serieindex" msgid "Sort descending according to series index" msgstr "Sortera fallande enligt serieindex" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Starta" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "Alfabetiska böcker" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "Böcker sorterade alfabetiskt" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Populära publikationer från den här katalogen baserad på hämtningar." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Populära publikationer från den här katalogen baserad på betyg." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Senaste tillagda böcker" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "De senaste böckerna" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Slumpmässiga böcker" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Böcker ordnade efter författare" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Böcker ordnade efter förlag" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Böcker ordnade efter kategori" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Böcker ordnade efter serier" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Böcker ordnade efter språk" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Böcker sorterade efter Betyg" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Böcker ordnade av filformat" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Hyllor" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Böcker organiserade i hyllor" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Hem" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Växla navigering" @@ -2736,48 +2850,48 @@ msgstr "Växla navigering" msgid "Search Library" msgstr "Sök i bibliotek" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Laddar upp..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Fel" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Uppladdning klar, bearbetning, vänligen vänta ..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Inställningar" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Konto" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Logga ut" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Laddar upp..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Fel" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Uppladdning klar, bearbetning, vänligen vänta ..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Inställningar" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Vänligen uppdatera inte sidan" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Bläddra" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Om" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Föregående" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Bokdetaljer" @@ -2793,7 +2907,7 @@ msgstr "Kom ihåg mig" msgid "Forgot Password?" msgstr "Glömt lösenord?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Logga in med magisk länk" @@ -2902,137 +3016,162 @@ msgstr "Calibre-Web e-bokkatalog" msgid "epub Reader" msgstr "PDF-läsare" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Ljust" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Mörkt" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Tillbaka" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Fyll i texten igen när sidofält är öppna." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "PDF-läsare" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Kortkommandon" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Föregående sida" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Nästa sida" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "Skala till bäst" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Skala till bredd" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Skala till höjd" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Skala till ursprunglig" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Rotera åt höger" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Rotera åt vänster" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Vänd bilden" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Administrationssida" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Skala" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Bäst" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Bredd" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Höjd" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Ursprunglig" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Rotera" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Vänd" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Horisontell" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Vertikal" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Riktning" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Vänster till höger" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Höger till vänster" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3041,7 +3180,7 @@ msgstr "" msgid "DJVU Reader" msgstr "PDF-läsare" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "PDF-läsare" @@ -3060,7 +3199,7 @@ msgid "Choose a username" msgstr "Välj ett användarnamn" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Din e-postadress" #: cps/templates/remote_login.html:5 @@ -3079,10 +3218,6 @@ msgstr "När du gör det kommer du automatiskt att logga in på den här enheten msgid "This verification link will expire in 10 minutes." msgstr "Länken går ut efter 10 minuter." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3107,43 +3242,51 @@ msgstr "Publiceringsdatum från" msgid "Published Date To" msgstr "Publiceringsdatum till" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Uteslut taggar" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Uteslut serier" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "Uteslut hyllor" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Uteslut språk" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Tillägg" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Uteslut tillägg" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Betyg större än" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Betyg mindre än" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3235,10 +3378,6 @@ msgstr "Förlopp" msgid "Run Time" msgstr "Drifttid" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Starttid" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3312,17 +3451,18 @@ msgid "Enter Username" msgstr "Ange användarnamn" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "Ange e-postadress" +#, fuzzy +msgid "Enter Email" +msgstr "Test e-post" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "Ange Kindle e-postadress" +msgid "Enter eReader Email" +msgstr "Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Test e-post" #: cps/templates/user_table.html:137 @@ -3384,10 +3524,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "Visa läst/oläst val" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Visa slumpmässiga böcker" - diff --git a/cps/translations/tr/LC_MESSAGES/messages.mo b/cps/translations/tr/LC_MESSAGES/messages.mo index 92518e7b..ea6e63b0 100644 Binary files a/cps/translations/tr/LC_MESSAGES/messages.mo and b/cps/translations/tr/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/tr/LC_MESSAGES/messages.po b/cps/translations/tr/LC_MESSAGES/messages.po index 1d37e164..5e4ea0ef 100644 --- a/cps/translations/tr/LC_MESSAGES/messages.po +++ b/cps/translations/tr/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-04-23 22:47+0300\n" "Last-Translator: iz \n" "Language: tr\n" @@ -16,492 +16,502 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "İstatistikler" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Sunucu yeniden başlatıldı, lütfen sayfayı yeniden yükleyin" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Sunucu kapatıyor, lütfen pencereyi kapatın" -#: cps/admin.py:156 -msgid "Reconnect successful" +#: cps/admin.py:159 +msgid "Success! Database Reconnected" msgstr "" -#: cps/admin.py:159 +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "%(kindlemail)s'a gönderilmek üzere başarıyla sıraya alındı" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "%(eReadermail)s'a gönderilmek üzere başarıyla sıraya alındı" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Bilinmeyen" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Yönetim sayfası" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Temel Ayarlar" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Arayüz Ayarları" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Tümü" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web yapılandırması güncellendi" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1179 +#: cps/admin.py:1202 #, fuzzy msgid "Please Enter a LDAP Service Account and Password" msgstr "Şifrenizi sıfırlayabilmek için lütfen geçerli bir kullanıcı adı giriniz" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Yeni kullanıcı ekle" - -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" + +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "Deneme e-postası gönderilirken bir hata oluştu: %(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "Lütfen önce e-posta adresinizi ayarlayın..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "E-posta sunucusu ayarları güncellendi" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Bilinmeyen bir hata oluştu. Lütfen daha sonra tekrar deneyiniz." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "%(nick)s kullanıcısını düzenle" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "%(user)s kullanıcısının şifresi sıfırlandı" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Lütfen önce SMTP e-posta ayarlarını ayarlayın..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "Log dosyası görüntüleyici" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Güncelleme paketi isteniyor" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Güncelleme paketi indiriliyor" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Güncelleme paketi ayıklanıyor" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Dosyalar değiştiriliyor" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Veritabanı bağlantıları kapalı" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Sunucu durduruyor" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Güncelleme tamamlandı, sayfayı yenilemek için lütfen Tamam'a tıklayınız" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Güncelleme başarısız:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP Hatası" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Bağlantı hatası" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "Bağlantı kurulmaya çalışırken zaman aşımına uğradı" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Genel hata" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "%(filename)s dosyası geçici dizine kaydedilemedi" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "E-posta sunucusu ayarları güncellendi" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Özellik Yapılandırması" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Lütfen tüm alanları doldurun!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "E-posta izin verilen bir servisten değil" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Yeni kullanıcı ekle" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "'%(user)s' kullanıcısı oluşturuldu" -#: cps/admin.py:1885 +#: cps/admin.py:1926 #, fuzzy -msgid "Found an existing account for this e-mail address or name." +msgid "Oops! An account already exists for this Email. or name." msgstr "Bu e-posta adresi veya kullanıcı adı için zaten bir hesap var." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Kullanıcı '%(nick)s' silindi" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "Başka yönetici kullanıcı olmadığından silinemedi" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "'%(nick)s' kullanıcısı güncellendi" @@ -514,122 +524,122 @@ msgstr "yüklü değil" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Hiçbiri" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metaveri başarıyla güncellendi" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "%(file)s dosyası yüklendi" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Dönüştürme için kaynak ya da hedef biçimi eksik" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "eKitap %(book_format)s formatlarına dönüştürülmek üzere başarıyla sıraya alındı" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Bu eKitabı dönüştürürken bir hata oluştu: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "Yüklenen eKitap muhtemelen kitaplıkta zaten var. Yenisini yüklemeden değiştirmeyi düşünün: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s geçerli bir dil değil" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "'%(ext)s' uzantılı dosyaların bu sunucuya yüklenmesine izin verilmiyor" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Yüklenecek dosyanın mutlaka bir uzantısı olması gerekli" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "%(filename)s dosyası geçici dizine kaydedilemedi" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "metaveri düzenle" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "%(path)s dizini oluşturulamadı. (İzin reddedildi)" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "%(file)s dosyası kaydedilemedi." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "%(book)s kitabına %(ext)s dosya biçimi eklendi" @@ -642,181 +652,186 @@ msgstr "Google Drive kurulumu tamamlanmadı, Google Drive'ı devre dışı bıra msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Geri yönlendirme alanı (callback domain) doğrulanamadı, lütfen Google geliştirici konsolunda alan adını doğrulamak için gerekli adımları izleyin." -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "%(book)d nolu kitap için %(format)s biçimi bulunamadı" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "%(fn)s eKitabı için %(format)s biçimi Google Drive'da bulunamadı" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s bulunamadı: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Kindle'a gönder" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "Bu e-Posta Calibre-Web ile gönderilmiştir." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web deneme e-Postası" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Deneme e-Postası" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Calibre-Web'i Kullanmaya Başlayın" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Kullanıcı Kayıt e-Postası: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "%(orig)s'dan %(format)s biçimine çevir ve Kindle'a gönder" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "%(format)s biçimlerini Kindle'a gönder" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Kindle'a gönder" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "İstenilen dosya okunamadı. Yanlış izinlerden kaynaklanabilir?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Kitap adını değiştirme sırasında hata oluştu ('%(src)s' → '%(dest)s'): %(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "%(file)s dosyası Google Drive'da bulunamadı" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "Kitap adını değiştirme sırasında hata oluştu ('%(src)s' → '%(dest)s'): %(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "eKitap yolu %(path)s Google Drive'da bulunamadı" -#: cps/helper.py:644 cps/web.py:1414 -#, fuzzy -msgid "Found an existing account for this e-mail address" -msgstr "Bu e-posta adresi için bir hesap mevcut." +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Bu kullanıcı adı zaten alındı" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Keşfet" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -825,9 +840,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "%(provider)s ile Kaydol" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "giriş yaptınız: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -886,12 +901,13 @@ msgstr "Google Oauth hatası, lütfen tekrar deneyin." msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Giriş" @@ -907,149 +923,158 @@ msgstr "Token süresi doldu" msgid "Success! Please return to your device" msgstr "Başarılı! Lütfen cihazınıza dönün" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "eKitaplar" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Son eKitapları göster" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Popüler" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Okunanlar" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Okunan ve okunmayanları göster" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Okunmamışlar" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Okunmamışları göster" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Keşfet" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Rastgele Kitap Göster" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Kategoriler" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Kategori seçimini göster" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Seriler" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Seri seçimini göster" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Yazarlar" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Yazar seçimini göster" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Yayıncılar" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Yayıncı seçimini göster" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Diller" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Dil seçimini göster" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Değerlendirmeler" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Değerlendirme seçimini göster" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Biçimler" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Dosya biçimi seçimini göster" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" -msgstr "" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Son eKitapları göster" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Ara" @@ -1073,14 +1098,14 @@ msgstr "Değerlendirme >= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Gelişmiş Arama" @@ -1131,7 +1156,7 @@ msgstr "eKitap kitaplıktan silindi: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Kitaplık oluştur" @@ -1158,73 +1183,73 @@ msgstr "Metaveri başarıyla güncellendi" msgid "Change order of Shelf: '%(name)s'" msgstr "Kitaplık sıralamasını değiştir: '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "%(title)s kitaplığı oluşturuldu." -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "%(title)s kitaplığı değiştirildi" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Bir hata oluştu" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Kitaplık: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Kitaplık açılırken hata oluştu. Kitaplık mevcut değil ya da erişilebilir değil" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Görevler" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Bekleniyor" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Başarısız" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Başladı" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Bitti" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Bilinmeyen Durum" @@ -1257,146 +1282,185 @@ msgstr "Yeni bir güncelleme mevcut. Son sürüme güncellemek için aşağıdak msgid "No release information available" msgstr "Sürüm bilgisi mevcut değil" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Keşfet (Rastgele)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "Yazar: %(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Yayınevi: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Seri: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Değerlendirme: %(rating)s yıldız" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Biçim: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Kategori: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Dil: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Değerlendirme listesi" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Biçim listesi" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "%(kindlemail)s'a gönderilmek üzere başarıyla sıraya alındı" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Lütfen önce SMTP e-posta ayarlarını ayarlayın..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "%(eReadermail)s'a gönderilmek üzere başarıyla sıraya alındı" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "E-Posta sunucusu ayarlanmadı, lütfen yöneticinizle iletişime geçin!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Kayıt ol" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "E-Posta sunucusu ayarlanmadı, lütfen yöneticinizle iletişime geçin!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "E-posta adresinizle kaydolunmasına izin verilmiyor" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "Onay e-Postası hesabınıza gönderildi." -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "LDAP Kimlik Doğrulaması etkinleştirilemiyor" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "giriş yaptınız: '%(nickname)s'" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Yanlış Kullanıcı adı ya da Şifre" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Yeni şifre e-Posta adresinize gönderildi" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Bilinmeyen bir hata oluştu. Lütfen daha sonra tekrar deneyiniz." + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "Şifrenizi sıfırlayabilmek için lütfen geçerli bir kullanıcı adı giriniz" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "Giriş yaptınız: '%(nickname)s'" +msgstr "giriş yaptınız: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s Profili" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Profil güncellendi" +#: cps/web.py:1491 +#, fuzzy +msgid "Oops! An account already exists for this Email." +msgstr "Bu e-posta adresi için bir hesap mevcut." + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Kindle'a gönder" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1439,35 +1503,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "metaveri düzenle" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Yükleme" @@ -1483,15 +1547,15 @@ msgstr "Kullanıcı adı" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "E-Posta adresiniz" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Yönetim" @@ -1501,8 +1565,8 @@ msgstr "Yönetim" msgid "Password" msgstr "Şifre" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "İndirme" @@ -1527,16 +1591,12 @@ msgstr "Sil" msgid "Public Shelf" msgstr "" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1557,11 +1617,11 @@ msgstr "" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1634,102 +1694,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" -msgstr "" - -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" -msgstr "" - -#: cps/templates/admin.html:199 -msgid "Administration" -msgstr "Yönetim" - -#: cps/templates/admin.html:200 -msgid "Download Debug Package" -msgstr "" - -#: cps/templates/admin.html:201 -msgid "View Logs" -msgstr "" - -#: cps/templates/admin.html:204 +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Yönetim" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "" + +#: cps/templates/admin.html:211 msgid "Restart" msgstr "" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Sürüm" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Detaylar" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Geçerli sürüm" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Güncelle" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "" @@ -1819,7 +1881,7 @@ msgid "Author" msgstr "Yazar" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Açıklama" @@ -1844,7 +1906,7 @@ msgstr "" msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Etiketler" @@ -1869,23 +1931,23 @@ msgid "Published Date" msgstr "" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Yayınevi" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Dil" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Evet" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Hayır" @@ -1902,8 +1964,8 @@ msgid "Fetch Metadata" msgstr "" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1926,8 +1988,8 @@ msgstr "Forma metaveri yüklemek için kapağa tıklayın" msgid "Loading..." msgstr "Yükleniyor..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Kapak" @@ -2154,7 +2216,7 @@ msgid "Enable Uploads" msgstr "" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2170,7 +2232,7 @@ msgid "Enable Public Registration" msgstr "" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2360,6 +2422,52 @@ msgstr "" msgid "Location of Unrar binary" msgstr "Unrar aracı konumu" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth Ayarları" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Kullanıcı şifresini sıfırla" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Yapılandırmayı Göster" @@ -2372,7 +2480,7 @@ msgstr "" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Tema" @@ -2462,79 +2570,82 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Okunmadı olarak işaretle" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Okundu olarak işaretle" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Okudum" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Açıklama:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Kitaplığa ekle" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "" +#, fuzzy +msgid "Gmail Account" +msgstr "Hesap" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2558,10 +2669,10 @@ msgid "Attachment Size Limit" msgstr "" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +msgid "Save and Send Test Email" msgstr "" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Geri" @@ -2587,12 +2698,12 @@ msgstr "Servis adı girin" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Sonraki" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2603,20 +2714,20 @@ msgstr "" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 #, fuzzy msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "E-Posta sunucusu ayarlanmadı, lütfen yöneticinizle iletişime geçin!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2646,80 +2757,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Başlangıç" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "İndirilme sayısına göre bu katalogdaki popüler yayınlar." -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Değerlendirmeye göre bu katalogdaki popüler yayınlar." -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Yeni eklenen eKitaplar" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "En en eKitaplar" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Rastgele eKitaplar" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Yazara göre sıralanmış eKitaplar" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Yayınevine göre sıralanmış eKitaplar" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Kategoriye göre sıralanmış eKitaplar" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Seriye göre sıralanmış eKitaplar" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Dile göre sıralanmış eKitaplar" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Biçime göre sıralanmış eKitaplar" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Anasayfa" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "" @@ -2727,48 +2838,48 @@ msgstr "" msgid "Search Library" msgstr "" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Yükleniyor..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Hata" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Yükleme tamamlandı, işleniyor, lütfen bekleyin..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Ayarlar" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Hesap" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Çıkış" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Yükleniyor..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Hata" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Yükleme tamamlandı, işleniyor, lütfen bekleyin..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Ayarlar" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Gözat" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Hakkında" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Önceki" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "eKitap Detayları" @@ -2784,7 +2895,7 @@ msgstr "" msgid "Forgot Password?" msgstr "" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "" @@ -2894,137 +3005,162 @@ msgstr "" msgid "epub Reader" msgstr "PDF Okuyucu" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Açık" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Koyu" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Geri" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Kenar çubukları açıkken metni kaydır" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 #, fuzzy msgid "Comic Reader" msgstr "PDF Okuyucu" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Klavye Kısayolları" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Önceki Sayfa" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Sonraki Sayfa" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "En İyiye Ölçeklendir" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "Genişliğe Ölçeklendir" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "Yüksekliğe Ölçeklendir" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "Asıla göre ölçeklendir" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Sağa çevir" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Sola çevir" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Resmi döndir" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Yönetim sayfası" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "Ölçeklendir" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "En İyi" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Genişlik" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Yükseklik" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "Asıl" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Çevir" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Döndür" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Yatay" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Dikey" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Yön" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Soldan Sağa" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Sağdan Sola" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3033,7 +3169,7 @@ msgstr "" msgid "DJVU Reader" msgstr "PDF Okuyucu" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 #, fuzzy msgid "PDF Reader" msgstr "PDF Okuyucu" @@ -3052,7 +3188,7 @@ msgid "Choose a username" msgstr "Kullanıcı adı seç" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "E-Posta adresiniz" #: cps/templates/remote_login.html:5 @@ -3071,10 +3207,6 @@ msgstr "" msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3099,44 +3231,52 @@ msgstr "" msgid "Published Date To" msgstr "" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Etiketleri Hariç Tut" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Serileri Hariç Tut" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Serileri Hariç Tut" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Dilleri Hariç Tut" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Uzantılar" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "Uzantıları Hariç Tut" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3228,10 +3368,6 @@ msgstr "İlerleme" msgid "Run Time" msgstr "" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3307,17 +3443,17 @@ msgstr "Kullanıcı adı seç" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" +msgid "Enter Email" +msgstr "Deneme e-Postası" + +#: cps/templates/user_table.html:136 +#, fuzzy +msgid "Enter eReader Email" msgstr "E-Posta adresiniz" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "E-Posta adresiniz" - -#: cps/templates/user_table.html:136 -#, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Deneme e-Postası" #: cps/templates/user_table.html:137 @@ -3381,10 +3517,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Seri seçimini göster" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Rastgele eKitap göster" - diff --git a/cps/translations/uk/LC_MESSAGES/messages.mo b/cps/translations/uk/LC_MESSAGES/messages.mo index 81e1667a..a951b3b8 100644 Binary files a/cps/translations/uk/LC_MESSAGES/messages.mo and b/cps/translations/uk/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/uk/LC_MESSAGES/messages.po b/cps/translations/uk/LC_MESSAGES/messages.po index 0589bc4f..dc11c40a 100644 --- a/cps/translations/uk/LC_MESSAGES/messages.po +++ b/cps/translations/uk/LC_MESSAGES/messages.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2017-04-30 00:47+0300\n" "Last-Translator: ABIS Team \n" "Language: uk\n" @@ -15,493 +15,503 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Статистика" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Сервер перезавантажено, будь-ласка, перезавантажте сторінку" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Виконується зупинка серверу, будь-ласка, закрийте вікно" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Підключення успішне" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Невідома команда" -#: cps/admin.py:169 -msgid "Books successfully queued for Metadata Backup" +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" msgstr "" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Невідомий" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Сторінка адміністратора" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Настройки сервера" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Конфігурація інтерфейсу" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 #, fuzzy msgid "Edit Users" msgstr "Керування сервером" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Всі" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Користувача не знайдено" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} користувачі видалені успішно" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Показати всі" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Не правильна роль" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:613 +#: cps/admin.py:617 #, fuzzy msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 #, fuzzy msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 #, fuzzy msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:626 +#: cps/admin.py:630 #, fuzzy msgid "Are you sure you want to change Calibre library location?" msgstr "Ви справді хочете видалити книжкову полицю?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Заборонити" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Дозволити" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Тег не знайдено" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" -msgstr "Додати користувача" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" +msgstr "" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "Змінити налаштування SMTP" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "" -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Змінити користувача %(nick)s" -#: cps/admin.py:1411 +#: cps/admin.py:1436 #, python-format -msgid "Password for user %(user)s reset" +msgid "Success! Password for user %(user)s reset" msgstr "" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "Будь-ласка, спочатку сконфігуруйте параметри SMTP" -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "Перевірка оновлень" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "Завантаження оновлень" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Розпакування оновлення" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "Заміна файлів" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "З'єднання з базою даних закрите" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Сервер зупиняється" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Оновлення встановлені, натисніть ok і перезавантажте сторінку" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Оновлення неуспішне:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP помилка" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Помилка зʼєднання" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Помилка" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "З'єднання з базою даних закрите" -#: cps/admin.py:1838 +#: cps/admin.py:1879 #, fuzzy msgid "Database Configuration" msgstr "Особливі налаштування" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Будь-ласка, заповніть всі поля!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Додати користувача" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Користувач '%(user)s' додан" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "" -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Користувача '%(nick)s' видалено" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Користувача '%(nick)s' оновлено" @@ -514,122 +524,122 @@ msgstr "не встановлено" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "Ні" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "Неможливо відкрити книгу. Файл не існує або немає доступу." -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "Завантажувальний файл повинен мати розширення" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "змінити метадані" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "" -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "" @@ -642,180 +652,183 @@ msgstr "" msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "Домен зворотнього зв'язку не підтверджено. Виконайте дії для підтвердження домену, будь-ласка" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Відправити на Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." -msgstr "" - -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +msgid "This Email has been sent via Calibre-Web." msgstr "" #: cps/helper.py:115 -msgid "Test e-mail" +msgid "Calibre-Web Test Email" msgstr "" -#: cps/helper.py:132 +#: cps/helper.py:116 +msgid "Test Email" +msgstr "" + +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "" -#: cps/helper.py:137 +#: cps/helper.py:138 #, python-format -msgid "Registration e-mail for user: %(name)s" +msgid "Registration Email for user: %(name)s" msgstr "" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 -#, python-format -msgid "Send %(format)s to E-Reader" +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 +#, fuzzy, python-format +msgid "Send %(format)s to eReader" msgstr "Надіслати %(format)s до E-Reader" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "Відправити на Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Огляд" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -824,9 +837,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "Ви увійшли як користувач: '%(nickname)s'" #: cps/oauth_bb.py:148 @@ -885,12 +898,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} зірок" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Ім'я користувача" @@ -906,149 +920,158 @@ msgstr "Час дії токено вичерпано" msgid "Success! Please return to your device" msgstr "Вдалося! Будь-ласка, поверніться до вашого пристрою" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Книжки" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Показувати останні книги" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Популярні книги" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Показувати популярні книги" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Книги з найкращим рейтингом" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Показувати книги з найвищим рейтингом" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Прочитані книги" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Показувати прочитані та непрочитані книги" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Непрочитані книги" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Показати не прочитані" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Огляд" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Показувати випадкові книги" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Категорії" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Показувати вибір категорії" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Серії" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Показувати вибір серії" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Автори" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Показувати вибір автора" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Видавництва" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" -msgstr "" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" +msgstr "Показувати вибір серії" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Мови" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Показувати вибір мови" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Рейтинги" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" -msgstr "" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" +msgstr "Показувати вибір серії" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Формати файлів" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" -msgstr "" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" +msgstr "Показувати вибір серії" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Архівні книжки" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" -msgstr "" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" +msgstr "Архівні книжки" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Список книжок" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Пошук" @@ -1072,14 +1095,14 @@ msgstr "Рейтинг >= %(rating)s" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Розширений пошук" @@ -1130,7 +1153,7 @@ msgstr "Книга видалена з книжкової полиці: %(sname) msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "створити книжкову полицю" @@ -1156,73 +1179,73 @@ msgstr "" msgid "Change order of Shelf: '%(name)s'" msgstr "Змінити розташування книжкової полиці '%(name)s'" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Створена книжкова полиця %(title)s" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Книжкова полиця %(title)s змінена" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Сталась помилка" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "Книжкова полиця: '%(name)s'" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "Помилка при відкриванні полиці. Полиця не існує або до неї відсутній доступ" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Завдання" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Очікує" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Розпочато" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Завершено" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "Закінчено" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "Відмінено" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Невідомий статус" @@ -1255,146 +1278,181 @@ msgstr "" msgid "No release information available" msgstr "" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "Огляд (випадкові книги)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "Популярні книги (найбільш завантажувані)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "Видавництво: %(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "Серії: %(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "Рейтинг: Відсутній" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "Рейтинг: %(rating)s зірок" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "Формат файлу: %(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "Категорія: %(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "Мова: %(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Завантаження" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Список рейтингів" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Список форматів файлу" -#: cps/web.py:1202 +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "Будь-ласка, спочатку сконфігуруйте параметри SMTP" + +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" +msgid "Success! Book queued for sending to %(eReadermail)s" msgstr "" -#: cps/web.py:1206 +#: cps/web.py:1243 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Oops! There was an error sending book: %(res)s" msgstr "Помилка при відправці книги: %(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Зареєструватись" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." msgstr "" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "" -#: cps/web.py:1278 +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "" + +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "Ви увійшли як користувач: '%(nickname)s'" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Помилка в імені користувача або паролі" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1320 +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "" + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" -msgstr "" +msgstr "Помилка в імені користувача або паролі" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "" +msgstr "Ви увійшли як користувач: '%(nickname)s'" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "Профіль %(name)s" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "Профіль оновлено" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "Відправити на Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1437,35 +1495,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "змінити метадані" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Додати нову книгу" @@ -1481,15 +1539,15 @@ msgstr "Ім'я користувача" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Адмін" @@ -1499,8 +1557,8 @@ msgstr "Адмін" msgid "Password" msgstr "Пароль" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Завантажити" @@ -1525,16 +1583,12 @@ msgstr "Видалити" msgid "Public Shelf" msgstr "" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1555,11 +1609,11 @@ msgstr "SMTP логін" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Відправник" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1632,102 +1686,104 @@ msgid "Scheduled Tasks" msgstr "Заплановані завдання" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "Максимальний час завдання" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "Адміністрування" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "Переглянути логи" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "Повторне підключення до БД Calibre" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Перезавантажити" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Вимкнути" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "Інформація про версію" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Версія" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Деталі" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Поточна версія" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Перевірка оновлень" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Встановити оновлення" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Впевнені що хочете перезавантажити?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Ok" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Скасувати" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Встановлення оновлень, будь-ласка, не оновлюйте сторінку" @@ -1817,7 +1873,7 @@ msgid "Author" msgstr "Автор" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Опис" @@ -1842,7 +1898,7 @@ msgstr "Видалити" msgid "Add Identifier" msgstr "Додати ідентифікатор" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Теги" @@ -1867,23 +1923,23 @@ msgid "Published Date" msgstr "Опубліковано" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Видавець" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Мова" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Так" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Ні" @@ -1900,8 +1956,8 @@ msgid "Fetch Metadata" msgstr "Отримати метадані" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1924,8 +1980,8 @@ msgstr "Натисніть на обкладинку, щоб отримати м msgid "Loading..." msgstr "Завантаження..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Закрити" @@ -2151,7 +2207,7 @@ msgid "Enable Uploads" msgstr "Дозволити завантаження книг на сервер" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2167,7 +2223,7 @@ msgid "Enable Public Registration" msgstr "Дозволити публічну реєстрацію" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2357,6 +2413,52 @@ msgstr "" msgid "Location of Unrar binary" msgstr "" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Налаштування OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Скинути пароль користувача" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "Переглянути налаштування" @@ -2369,7 +2471,7 @@ msgstr "Кількість показаних випадкових книг" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "Тема" @@ -2460,79 +2562,81 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Відкрити в браузері" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Прослухати в браузері" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Опубліковано" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Відмітити як не прочитане" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Відмітити як прочитане" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Прочитано" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Відновити з архіву" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Додати в архів" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Заархівовано" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Опис:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Додати на книжкову полицю" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Публічно)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Редагувати метадані" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" +msgid "Gmail Account" msgstr "" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2556,10 +2660,11 @@ msgid "Attachment Size Limit" msgstr "Обмеження розміру вкладення" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Зберегти налаштування і відправити тестове повідомлення" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Назад" @@ -2585,12 +2690,12 @@ msgstr "Введіть домен" msgid "Denied Domains (Blacklist)" msgstr "Заборонені домени (Чорний список)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Далі" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2601,19 +2706,19 @@ msgstr "" msgid "List" msgstr "Список" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2643,80 +2748,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Старт" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "Популярні книги в цьому каталозі, на основі кількості завантажень" -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "Популярні книги з цього каталогу на основі рейтингу" -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Останні книги" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Випадковий список книг" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Книги відсортовані за автором" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Книги відсортовані за категоріями" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Книги відсортовані за серією" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "Включити навігацію" @@ -2724,48 +2829,48 @@ msgstr "Включити навігацію" msgid "Search Library" msgstr "" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Завантаження..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Помилка" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "" - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Налаштування" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "Вийти" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Завантаження..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Помилка" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "" + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Налаштування" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Перегляд" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "Про програму" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Попередній перегляд" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Деталі" @@ -2781,7 +2886,7 @@ msgstr "Запам'ятати мене" msgid "Forgot Password?" msgstr "" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Увійдіть в систему за допомогою magic link" @@ -2890,136 +2995,161 @@ msgstr "" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Назад" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "Переформатувати текст, коли відкриті бічні панелі." -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Сторінка адміністратора" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Краще" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Ширина" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Висота" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Повернути" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Вертикально" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Напрям" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Показати" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Сховати" @@ -3027,7 +3157,7 @@ msgstr "Сховати" msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -3045,7 +3175,7 @@ msgid "Choose a username" msgstr "Виберіть ім'я користувача" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Ваш email-адрес" #: cps/templates/remote_login.html:5 @@ -3064,10 +3194,6 @@ msgstr "Після цього ви автоматично ввійдете в с msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3092,44 +3218,52 @@ msgstr "Дата публікації з" msgid "Published Date To" msgstr "Дата публікації до" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "Виключити теги" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "Виключити серії" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 #, fuzzy msgid "Exclude Shelves" msgstr "Виключити серії" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "Виключити мови" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "Розширення" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "Від:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "До:" @@ -3221,10 +3355,6 @@ msgstr "Прогрес" msgid "Run Time" msgstr "Тривалість" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Час початку" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "Дії" @@ -3301,17 +3431,18 @@ msgstr "Виберіть ім'я користувача" #: cps/templates/user_table.html:135 #, fuzzy -msgid "Enter E-mail Address" -msgstr "Ваш email-адрес" +msgid "Enter Email" +msgstr "Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "Ваш email-адрес" +msgid "Enter eReader Email" +msgstr "Kindle" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" -msgstr "" +#, fuzzy +msgid "eReader Email" +msgstr "Kindle" #: cps/templates/user_table.html:137 msgid "Locale" @@ -3373,10 +3504,6 @@ msgstr "" #: cps/templates/user_table.html:156 #, fuzzy -msgid "Show read/unread selection" +msgid "Show Read/Unread Section" msgstr "Показувати вибір серії" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Показувати випадкові книги" - diff --git a/cps/translations/vi/LC_MESSAGES/messages.mo b/cps/translations/vi/LC_MESSAGES/messages.mo index 99ca8660..5c9e3270 100644 Binary files a/cps/translations/vi/LC_MESSAGES/messages.mo and b/cps/translations/vi/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/vi/LC_MESSAGES/messages.po b/cps/translations/vi/LC_MESSAGES/messages.po index bd01ecb3..59f95fb6 100644 --- a/cps/translations/vi/LC_MESSAGES/messages.po +++ b/cps/translations/vi/LC_MESSAGES/messages.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-web\n" "Report-Msgid-Bugs-To: https://github.com/janeczku/calibre-web\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2022-09-20 21:36+0700\n" "Last-Translator: Ha Link \n" "Language: vi\n" @@ -13,487 +13,496 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "Thống kê" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "Máy chủ đã khởi động lại,hãy tải lại trang" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "Máy chủ đang được tắt, hãy đóng cửa sổ này" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "Kết nối lại thành công" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "Lệnh không tồn tại" -#: cps/admin.py:169 -msgid "Books successfully queued for Metadata Backup" +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" msgstr "" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "Không rõ" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "Trang admin" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "Thiết lập cơ bản" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "Thiết lập UI" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "Chỉnh sửa người dùng" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "Tất cả" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "Không tìm thấy user" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "{} người dung đã đươc xoá thành công" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "Hiển thị tất cả" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "Yêu cầu không đúng định dạng" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "Tên người dung khách không thể thay đổi" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "Khách không thể mang vai trò này" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "Không còn người dùng quản trị, không thể xoá vai trò admin" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "Giá trị phải là true hoặc false" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "Vai trò không hợp lệ" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "Tài khoản khách không có màn hình này" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "View không hợp lệ" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "Ngôn ngữ của khách được xác định tự động và không thể đặt được" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "Địa chỉ cung cấp không hợp lệ" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "Ngôn ngữ sách không hợp lệ" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "Tham số không tồn tại" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "Cột đọc không hợp lệ" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "Cột bị hạn chế không hợp lệ" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Thiết lập Calibre-Web đã cập nhật" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "Bạn có thực sự muốn xóa Kobo Token không?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "Bạn có thực sự muốn xóa miền này không?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "Bạn có thực sự muốn xóa người dùng này không?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "Bạn có chắc chắn muốn xóa giá này không?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "Bạn có chắc chắn muốn thay đổi ngôn ngữ của những người dùng đã chọn?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "Bạn có chắc chắn muốn thay đổi ngôn ngữ sách hiển thị cho (những) người dùng đã chọn không?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "Bạn có chắc chắn muốn thay đổi vai trò đã chọn cho (những) người dùng đã chọn không?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "Bạn có chắc chắn muốn thay đổi những giới hạn đã chọn cho người dung?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "Bạn có chắc chắn muốn thay đổi các giới hạn hiển thị đã chọn cho (những) người dùng đã chọn không?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "Bạn có chắc chắn muốn thay đổi hành vi đồng bộ hóa giá cho (những) người dùng đã chọn không?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "Bạn có chắc chắn muốn thay đổi vị trí thư viện Calibre không?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "Bạn có chắc chắn muốn xóa cơ sở dữ liệu đồng bộ của Calibre-Web để bắt buộc đồng bộ hóa hoàn toàn với Kobo Reader của mình không?" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "Từ chối" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "Cho phép" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} mục nhập đồng bộ hóa đã bị xóa" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "Tag không tồn tại" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "Hành động không hợp lệ" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "Vị trí tệp nhật ký không hợp lệ, vui lòng nhập đường dẫn chính xác" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "Thêm người dùng mới" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "Lỗi cơ sở dữ liệu: %(error)s." -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 #, fuzzy msgid "Scheduled tasks settings updated" msgstr "Thiết lập cơ sở dữ lieu đã được cập nhật" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "Lỗi không xác định xảy ra. Xin hãy thử lại sau." -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "Chỉnh sửa người dùng %(nick)s" -#: cps/admin.py:1411 +#: cps/admin.py:1436 #, python-format -msgid "Password for user %(user)s reset" +msgid "Success! Password for user %(user)s reset" msgstr "" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." msgstr "" -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "Đang giải nén tệp cập nhật" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "They thế tập tin" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "Liên kết cơ sở dữ liệu đã được đóng" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "Đang dừng server" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "Cập nhật hoàn tất, ấn okay và tải lại trang" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "Cập nhật thất bại:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "Lỗi HTTP" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "Lỗi kết nối" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "Lỗi chung" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "File cập nhật không thể được lưu trong thư mục tạm thời" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "Thiết lập cơ sở dữ lieu đã được cập nhật" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "Thiết lập cơ sở dữ lieu :)))" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "Hãy điền hết các trường!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "Địa chỉ email không hợp lệ" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "Thêm người dùng mới" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "Người dùng '%(user)s' đã được tạo" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "Người dùng với địa chỉ email hoặc tên đã tồn tại." -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "Người dùng '%(nick)s' đã bị xoá" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "Không thể xoá người dùng khách" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "Người dùng '%(nick)s' đã được cập nhật" @@ -506,122 +515,122 @@ msgstr "chưa cài đặt" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "None" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "Metadata đã được cập nhật thành công" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "File %(file)s đã được tải lên" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "Thiếu định dạng nguồn hoặc đích để convert" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "Có lỗi xảy ra khi chuyển đổi định dạng cho sach: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s không phải là ngôn ngữ hợp lệ" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "Lưu file thất bại %(file)s." -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "" @@ -634,180 +643,187 @@ msgstr "" msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "%(format)s không tìm thấy: %(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "Gửi tới Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "E-mail này được gửi từ Calibre-Web." -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web test e-mail" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "Test e-mail" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "Bắt đầu với Calibre-Web" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "Email đăng ký cho người dùng: %(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "Chuyển đổi %(orig)s thành %(format)s và chuyển tới Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "Gửi %(format)s tới Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "%(book)s gửi tới Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "File được yêu cầu không thể đọc. Có thể do phân quyền bị sai?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "Xoá thư mục cho sách %(id)s thất bại, đường dẫn có subfolders: %(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "Xoá sách %(id)s thất bại: %(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "File %(file)s không tìm thấy trẻn Google Drive" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Không tìm thấy được dẫn sách %(path)s trên Google Drive" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "Tìm thấy một tài khoản đã toàn tại cho địa chỉ email này" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "Username này đã bị sử dụng" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "Định dạng email address không hợp lệ" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "Lỗi tải xuống ảnh bìa" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "Định dạng ảnh bìa lỗi" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "Tạo đường dẫn cho ảnh bìa thất bại" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "Khám phá" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Thiết lập Kobo" @@ -816,9 +832,9 @@ msgstr "Thiết lập Kobo" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "" #: cps/oauth_bb.py:148 @@ -877,12 +893,13 @@ msgstr "Google Oauth lỗi, làm ơn thử lại sau." msgid "Google Oauth error: {}" msgstr "Google Oauth lỗi: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} sao" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "Đăng nhập" @@ -898,149 +915,158 @@ msgstr "Token đã hết hạn" msgid "Success! Please return to your device" msgstr "Thành công! Hãy quay lại thiết bị của bạn" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "Sách" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "Hiển thị sách gần đây" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "Sách hot" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "Hiển thị sách hot" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "Sách đã tải" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "Hiển thị sách đã tải" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "Top sách được đánh giá cao" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "Hiện thị top những sách được đánh giá cao" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "Sách đã đọc" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "Hiển thị đã đọc và chưa đọc" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "Sách chưa đọc" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "Hiện thị sách chưa đọc" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "Khám phá" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "Hiển thị sách ngẫu nhiên" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "Chủ đề" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "Hiển thị chọn chủ đề" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "Series" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "Hiển thị chọn series" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "Tác giả" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "Hiển thị chọn tác giả" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "Nhà phát hành" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "Hiển thị chọn nhà phát hành" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "Ngôn ngữ" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "Hiển thị chọn ngôn ngữ" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "Đánh giá" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "Hiển thị chọn đánh giá" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "Định dạng file" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "Hiển thị lựa chọn định dạng file" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "Sách đã lưu trữ" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "Hiện thị sách trong kho" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "Danh sách sách" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "Hiển thị danh sách sách" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "Tìm kiếm" @@ -1063,15 +1089,15 @@ msgid "Rating >= %(rating)s" msgstr "Đánh giá >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "Trạng thái đọc = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "Tìm kiếm nâng cao" @@ -1121,7 +1147,7 @@ msgstr "Sách đã được xoá khỏi giá: %(sname)s" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "Xin lỗi bạn không có quyền xoá sách khỏi giá này" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "Tạo một giá sách" @@ -1146,74 +1172,74 @@ msgstr "" msgid "Change order of Shelf: '%(name)s'" msgstr "" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "Xin lỗi bạn không có quyền tạo một giá sách công khai" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "Giá sách %(title)s đã được tạo" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "Giá sách %(title)s đã được thay đổi" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "Có lỗi xảy ra" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "Nhiệm vụ" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "Đang chờ" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "Thất bại" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "Đã bắt đầu" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "Đã hoàn thành" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 #, fuzzy msgid "Cancelled" msgstr "Huỷ bỏ" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "Trạng thái không xác định" @@ -1246,147 +1272,183 @@ msgstr "" msgid "No release information available" msgstr "" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "" -#: cps/web.py:611 +#: cps/web.py:620 #, fuzzy msgid "Rating: None" msgstr "Đánh giá cao hơn" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "Tải xuống" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "Danh sách đánh giá" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "Danh sách định dạng file" -#: cps/web.py:1202 +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "" + +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" +msgid "Success! Book queued for sending to %(eReadermail)s" msgstr "" -#: cps/web.py:1206 +#: cps/web.py:1243 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Oops! There was an error sending book: %(res)s" msgstr "" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "Đăng ký" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" -msgstr "Email của bạn không được cho phép để đăng ký" - -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." msgstr "" -#: cps/web.py:1278 +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." +msgstr "Email của bạn không được cho phép để đăng ký" + +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "" + +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "Không thể đăng nhập: %(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "Tên đăng nhập hoặc mật khẩu không đúng" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "Mật khẩu mới đã được gửi đến email của bạn" -#: cps/web.py:1320 -msgid "Please enter valid username to reset password" -msgstr "" +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "Lỗi không xác định xảy ra. Xin hãy thử lại sau." -#: cps/web.py:1327 +#: cps/web.py:1405 +#, fuzzy +msgid "Please enter valid username to reset password" +msgstr "Tên đăng nhập hoặc mật khẩu không đúng" + +#: cps/web.py:1413 #, python-format msgid "You are now logged in as: '%(nickname)s'" msgstr "" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "" -#: cps/web.py:1410 -msgid "Profile updated" -msgstr "" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" +msgstr "Metadata đã được cập nhật thành công" + +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "Tìm thấy một tài khoản đã toàn tại cho địa chỉ email này" #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s gửi tới Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1431,35 +1493,35 @@ msgstr "Khám phá" msgid "Reconnecting Calibre database" msgstr "Kết nối lại với cơ sở dữ liệu Calibre" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 #, fuzzy msgid "E-mail" msgstr "Test e-mail" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 msgid "Backing up Metadata" msgstr "" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "Tải lên" @@ -1475,15 +1537,15 @@ msgstr "Tên người dùng" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "Địa chỉ email" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "Kindle" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "Admin" @@ -1493,8 +1555,8 @@ msgstr "Admin" msgid "Password" msgstr "Mật khẩu" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "Tải xuống" @@ -1519,16 +1581,12 @@ msgstr "Xoá" msgid "Public Shelf" msgstr "Giá công khai" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "Thêm người dùng mới" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "Thiết lập máy chủ email" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1549,11 +1607,12 @@ msgstr "Đăng nhập SMTP" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "Từ E-mail" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "Dịch vụ E-Mail" #: cps/templates/admin.html:91 @@ -1625,104 +1684,106 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 #, fuzzy -msgid "Reconnect to Calibre Library" -msgstr "Kết nối lại với cơ sở dữ liệu Calibre" - -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" -msgstr "" - -#: cps/templates/admin.html:199 -msgid "Administration" -msgstr "Quản trị" - -#: cps/templates/admin.html:200 -msgid "Download Debug Package" -msgstr "Tải xuống package debug" - -#: cps/templates/admin.html:201 -msgid "View Logs" -msgstr "Xem logs" - -#: cps/templates/admin.html:204 msgid "Reconnect Calibre Database" msgstr "Kết nối lại với cơ sở dữ liệu Calibre" -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "Quản trị" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "Tải xuống package debug" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "Xem logs" + +#: cps/templates/admin.html:211 msgid "Restart" msgstr "Khởi động lại" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "Tắt" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 #, fuzzy msgid "Version Information" msgstr "Thiết lập máy chủ" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "Phiên bản" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "Chi tiết" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "Phiên bản hiện tại" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "Kiểm tra cập nhật" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "Bắt đầu cập nhật" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "Bạn có chắc chắn muốn khởi động lại?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "Ok" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "Huỷ bỏ" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "Bạn có chắc muốn tắt?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "Đang update, làm ơn đừng load lại trang này" @@ -1812,7 +1873,7 @@ msgid "Author" msgstr "Tác giả" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "Mô tả" @@ -1837,7 +1898,7 @@ msgstr "Xoá" msgid "Add Identifier" msgstr "Thêm nhận diện" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "Đánh dấu" @@ -1862,23 +1923,23 @@ msgid "Published Date" msgstr "Ngày xuất bản" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "Nhà xuất bản" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "Ngôn ngữ" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "Có" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "Không" @@ -1895,8 +1956,8 @@ msgid "Fetch Metadata" msgstr "Fetch Metadata" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1918,8 +1979,8 @@ msgstr "Ấn vào ảnh cover để tải metadata vào form" msgid "Loading..." msgstr "Đang tải..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "Đóng" @@ -2144,7 +2205,7 @@ msgid "Enable Uploads" msgstr "" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2160,7 +2221,7 @@ msgid "Enable Public Registration" msgstr "" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2350,6 +2411,52 @@ msgstr "" msgid "Location of Unrar binary" msgstr "" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "Thiết lập OAuth" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "Reset mật khẩu người dùng" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "" @@ -2362,7 +2469,7 @@ msgstr "" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "" @@ -2451,80 +2558,84 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "Thêm cho phép/từ chối giá trị cột tuỳ biến" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "Đọc trên trình duyệt" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "Nghe trên trình duyệt" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "Sách %(index)s của %(range)s" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "Đã phát hành" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "Đánh dấu chưa đọc" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "Đánh dấu đã đọc" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "Đọc" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "Khôi phục từ lưu trữ" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "Thêm vào lưu trữ" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "Lưu trữ" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "Mô tả:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "Thêm vào giá sách" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(Công khai)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "Chỉnh sửa Metadata" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "Chọn kiểu server" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "Dùng tài khoản email tiêu chuẩn" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "Tài khoản Gmail với xác nhận OAuth2" +#, fuzzy +msgid "Gmail Account" +msgstr "Chọn kiểu server" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "Cài đặt tài khoản Gmail làm email Server" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2547,10 +2658,11 @@ msgid "Attachment Size Limit" msgstr "Giới hạn kích thước file đính kèm" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "Lưu và gửi test E-mail" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "Quay lại" @@ -2576,12 +2688,12 @@ msgstr "Nhập tên domain" msgid "Denied Domains (Blacklist)" msgstr "Domain bị từ chối (Blacklist)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "Tiếp tục" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2593,19 +2705,19 @@ msgstr "Token đồng bộ Kobo" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "Quay về trang chủ" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2635,80 +2747,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "Bắt đầu" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "" -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "" -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "Sách mới được thêm gần đây" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "Sách mới nhất" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "Sách ngẫu nhiên" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "Sách sắp xếp theo tác giả" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "Sách sắp xếp theo nhà phát hành" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "Sách sắp xếp theo thể loại" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "Sách sắp xếp theo series" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "Sách sắp xếp theo ngôn ngữ" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "Sách sắp xếp theo xếp hạng" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "Sách sắp xếp theo định dạng" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "Giá sách" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "Sách tổ chức theo giá sách" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "Trang chủ" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "" @@ -2716,48 +2828,48 @@ msgstr "" msgid "Search Library" msgstr "Tìm kiếm thư viện" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "Đang tải lên..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "Lỗi" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "Tải lên xong, đang xử lý, đợi chút ..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "Thiết lập" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "Tài khoản" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" -msgstr "Đăng suất" +msgstr "Đăng xuất" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "Đang tải lên..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "Lỗi" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "Tải lên xong, đang xử lý, đợi chút ..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "Thiết lập" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "Làm ơn đừng load lại trang" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "Tìm kiếm" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "About" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "Trước" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "Chi tiết sách" @@ -2773,7 +2885,7 @@ msgstr "Ghi nhớ tôi" msgid "Forgot Password?" msgstr "Quên mật khẩu?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "Đăng nhập với Magic Link" @@ -2881,136 +2993,161 @@ msgstr "" msgid "epub Reader" msgstr "trình đọc epub" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "Sáng" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "Tối" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "Quay lại" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "Trình đọc truyện tranh" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "Phím tắt" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "Trang trước" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "Trang tiếp theo" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "Xoay phải" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "Xoay trái" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "Lật ảnh" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "Trang admin" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "Tốt nhất" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "Rộng" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "Cao" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "Xoay" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "Lật" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "Ngang" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "Dọc" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "Hướng" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "Trái sang phải" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "Phải sang trái" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "Quay lên trên" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "Ghi nhớ vị trí" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "Thanh cuộn" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "Hiện" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "Ẩn" @@ -3018,7 +3155,7 @@ msgstr "Ẩn" msgid "DJVU Reader" msgstr "Trình đọc DJVU" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "Trình đọc PDF" @@ -3035,7 +3172,7 @@ msgid "Choose a username" msgstr "Chọn tên người dùng" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "Địa chỉ email của bạn" #: cps/templates/remote_login.html:5 @@ -3054,10 +3191,6 @@ msgstr "Một khi xác nhận, bạn sẽ tự động đăng nhập trên thi msgid "This verification link will expire in 10 minutes." msgstr "Link xác nhận này sẽ hết hạn trong 10 phút." -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3082,43 +3215,51 @@ msgstr "Ngày phát hành từ" msgid "Published Date To" msgstr "Ngày phát hành tới" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "Đánh giá cao hơn" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "Đánh giá thấp hơn" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "Từ:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "Tới:" @@ -3210,10 +3351,6 @@ msgstr "Tiến độ" msgid "Run Time" msgstr "Thời gian chạy" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "Thời gian bắt đầu" - #: cps/templates/tasks.html:20 #, fuzzy msgid "Actions" @@ -3288,17 +3425,18 @@ msgid "Enter Username" msgstr "Nhập tên người dùng" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "Nhập địa chỉ E-mail" +#, fuzzy +msgid "Enter Email" +msgstr "Test e-mail" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "Nhập địa chỉ E-mail Kindle" +msgid "Enter eReader Email" +msgstr "Kindle" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "Test e-mail" #: cps/templates/user_table.html:137 @@ -3358,10 +3496,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "Đồng bộ những giá sách đã chọn với Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "Hiển thị đã đọc và chưa đọc" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "Hiển thị sách ngẫu nhiên" - diff --git a/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo b/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo index 8dfd1768..7309e7da 100644 Binary files a/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo and b/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po b/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po index b86b6041..dff01166 100644 --- a/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po +++ b/cps/translations/zh_Hans_CN/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-09-27 22:18+0800\n" "Last-Translator: xlivevil \n" "Language: zh_CN\n" @@ -16,486 +16,493 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "统计" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +msgid "Server restarted, please reload page." msgstr "服务器已重启,请刷新页面" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +msgid "Performing Server shutdown, please close window." msgstr "正在关闭服务器,请关闭窗口" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "重新连接成功" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "数据库重新连接成功" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "未知命令" -#: cps/admin.py:169 -msgid "Books successfully queued for Metadata Backup" -msgstr "书籍已为元数据备份排队" +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "成功!书籍已排队进行元数据备份,请检查任务列表以获取结果" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "未知" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "管理页" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "基本配置" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "界面配置" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "管理用户" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "全部" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "找不到用户" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "成功删除 {} 个用户" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "显示全部" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "格式错误的请求" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "访客名称无法更改" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "游客无法拥有此角色" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "没有其余管理员账户,无法删除管理员角色" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" -msgstr "值必须是 true 或 false" +msgstr "值必须为 true 或 false" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "无效角色" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" -msgstr "游客无法拥有此视图" +msgstr "游客无法查看此页面" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" -msgstr "无效视图" - -#: cps/admin.py:513 -msgid "Guest's Locale is determined automatically and can't be set" -msgstr "游客的本地化是自动侦测而无法设置的" +msgstr "无效页面" #: cps/admin.py:517 +msgid "Guest's Locale is determined automatically and can't be set" +msgstr "无法设置游客的本地化,该项设置的值将自动检测" + +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "无可用本地化" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "无有效书籍语言" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "参数未找到" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" -msgstr "无效的阅读列" +msgstr "无效的阅读栏目" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" -msgstr "无效的限制列" +msgstr "无效的限制栏目" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" -msgstr "Calibre-Web配置已更新" +msgstr "Calibre-Web 配置已更新" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" -msgstr "您确定删除Kobo Token吗?" +msgstr "您确定删除 Kobo 令牌吗?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "您确定要删除此域吗?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "您确定要删除此用户吗?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "您确定要删除此书架吗?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "您确定要修改选定用户的本地化设置吗?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "您确定要修改选定用户的可见书籍语言吗?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "您确定要修改选定用户的选定角色吗?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "您确定要修改选定用户的选定限制吗?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "您确定要修改选定用户的选定可视化限制吗?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "您确定要更改所选用户的书架同步行为吗?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "您确定要更改 Calibre 库位置吗?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "Calibre-Web 将搜索更新封面,并更新缩略图,这可能需要一段时间" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "您确定要删除 Calibre-Web 的同步数据库以强制与您的 Kobo Reader 进行完全同步吗" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "拒绝" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "允许" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "{} 同步项目被删除" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "标签未找到" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "无效的动作" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json 未为 Web 应用程序配置" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "日志文件路径无效,请输入正确的路径" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "访问日志路径无效,请输入正确的路径" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" -msgstr "请输入LDAP主机、端口、DN和用户对象标识符" - -#: cps/admin.py:1179 -msgid "Please Enter a LDAP Service Account and Password" -msgstr "请输入一个LDAP服务账号和密码 " - -#: cps/admin.py:1182 -msgid "Please Enter a LDAP Service Account" -msgstr "请输入一个LDAP服务账号" - -#: cps/admin.py:1187 -#, python-format -msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" -msgstr "LDAP组对象过滤器需要一个具有“%s”格式标识符" - -#: cps/admin.py:1189 -msgid "LDAP Group Object Filter Has Unmatched Parenthesis" -msgstr "LDAP组对象过滤器的括号不匹配" - -#: cps/admin.py:1193 -#, python-format -msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" -msgstr "LDAP用户对象过滤器需要一个具有“%s”格式标识符" - -#: cps/admin.py:1195 -msgid "LDAP User Object Filter Has Unmatched Parenthesis" -msgstr "LDAP用户对象过滤器的括号不匹配" +msgstr "请输入 LDAP 主机、端口、DN 和用户对象标识符" #: cps/admin.py:1202 +msgid "Please Enter a LDAP Service Account and Password" +msgstr "请输入一个 LDAP 服务账号和密码 " + +#: cps/admin.py:1205 +msgid "Please Enter a LDAP Service Account" +msgstr "请输入一个 LDAP 服务账号" + +#: cps/admin.py:1210 +#, python-format +msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" +msgstr "LDAP 组对象过滤器需要一个具有“%s”格式标识符" + +#: cps/admin.py:1212 +msgid "LDAP Group Object Filter Has Unmatched Parenthesis" +msgstr "LDAP 组对象过滤器的括号不匹配" + +#: cps/admin.py:1216 +#, python-format +msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" +msgstr "LDAP 用户对象过滤器需要一个具有“%s”格式标识符" + +#: cps/admin.py:1218 +msgid "LDAP User Object Filter Has Unmatched Parenthesis" +msgstr "LDAP 用户对象过滤器的括号不匹配" + +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" -msgstr "LDAP成员用户过滤器需要有一个“%s”格式标识符" +msgstr "LDAP 成员用户过滤器需要有一个“%s”格式标识符" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" -msgstr "LDAP成员用户过滤器中有不匹配的括号" +msgstr "LDAP 成员用户过滤器中有不匹配的括号" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CA证书、证书或密钥位置无效,请输入正确的路径" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "添加新用户" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "编辑邮件服务器设置" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "G-Mail账号校验成功" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "Gmail 账户验证成功" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." -msgstr "数据库错误:%(error)s。" +msgid "Oops! Database Error: %(error)s." +msgstr "数据库错误:%(error)s" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" -msgstr "发送给%(email)s的测试邮件已进入队列。请检查任务结果" +msgstr "发送给 %(email)s 的测试邮件已加入队列。请检查任务结果" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "发送测试邮件时出错:%(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "请先配置您的邮箱地址..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "邮件服务器设置已更新" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "编辑计划任务设置" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "指定任务的开始时间无效" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "指定任务的持续时间无效" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "已更新计划任务设置" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." -msgstr "发生一个未知错误,请稍后再试。" +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." +msgstr "发生一个未知错误,请稍后再试" -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "设置数据库不可写" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "编辑用户 %(nick)s" -#: cps/admin.py:1411 +#: cps/admin.py:1436 #, python-format -msgid "Password for user %(user)s reset" +msgid "Success! Password for user %(user)s reset" msgstr "用户 %(user)s 的密码已重置" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." -msgstr "请先配置SMTP邮箱设置..." +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." +msgstr "请先配置 SMTP 邮箱设置..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "日志文件查看器" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "正在请求更新包" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "正在下载更新包" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "正在解压更新包" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "正在替换文件" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "数据库连接已关闭" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "正在停止服务器" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "更新完成,请点击确定并刷新页面" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "更新失败:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" -msgstr "HTTP错误" +msgstr "HTTP 错误" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "连接错误" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "建立连接超时" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "一般错误" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "更新文件无法保存在临时目录中" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "更新期间无法替换文件" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" -msgstr "未能提取至少一个LDAP用户" +msgstr "未能获得任何 LDAP 用户" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" -msgstr "未能创建至少一个LDAP用户" +msgstr "未能创建任何 LDAP 用户" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "错误:%(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" -msgstr "错误:在LDAP服务器的响应中没有返回用户" +msgstr "错误:在 LDAP 服务器的响应中没有返回用户" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" -msgstr "数据库中没有找到至少一个LDAP用户" +msgstr "数据库中没有找到任何 LDAP 用户" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} 用户被成功导入" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "数据库路径无效,请输入正确的路径" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "数据库不可写入" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "密钥文件路径无效,请输入正确的路径" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "证书文件路径无效,请输入正确的路径" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "密码长度必须在1到40之间" + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "数据库设置已更新" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "数据库配置" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "请填写所有字段!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "邮箱不在有效域中" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "添加新用户" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "用户“%(user)s”已创建" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." -msgstr "使用此邮箱或用户名的账号已经存在。" +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." +msgstr "使用此邮箱或用户名的账号已经存在" -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "用户“%(nick)s”已删除" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "无法删除游客用户" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "管理员账户不存在,无法删除用户" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "电子邮件地址不能为空,并且必须是有效的电子邮件" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "用户“%(nick)s”已更新" @@ -508,306 +515,309 @@ msgstr "未安装" msgid "Execution permissions missing" msgstr "缺少执行权限" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" -msgstr "自定义列号:%(column)d在Calibre数据库中不存在" +msgstr "自定义列号:%(column)d 在 Calibre 数据库中不存在" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "无" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "糟糕!选择书名无法打开。文件不存在或者文件不可访问" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "用户没有权限上传封面" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "标识符不区分大小写,覆盖旧标识符" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "已成功更新元数据" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "编辑书籍时出错: {}" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "文件 %(file)s 已上传" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" -msgstr "转换的源或目的格式缺失" +msgstr "转换的源格式或目的格式缺失" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" -msgstr "书籍已经被成功加入到 %(book_format)s 格式转换队列" +msgstr "书籍已经被成功加入 %(book_format)s 格式转换队列" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "转换此书籍时出现错误: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "上传的书籍可能已经存在,建议修改后重新上传: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "'%(langname)s' 不是一种有效语言" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "不能上传文件扩展名为“%(ext)s”的文件到此服务器" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "要上传的文件必须具有扩展名" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "文件 %(filename)s 无法保存到临时目录" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "移动封面文件失败 %(file)s:%(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" -msgstr "书籍格式已成功删除" +msgstr "书籍的此格式副本已成功删除" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "书籍已成功删除" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "您没有删除书籍的权限" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "编辑元数据" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s 不是一个有效的数值,忽略" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "用户没有权限上传其他文件格式" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." -msgstr "创建路径 %(path)s 失败(权限拒绝)。" +msgstr "创建路径 %(path)s 失败 (权限不足)" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." -msgstr "保存文件 %(file)s 失败。" +msgstr "保存文件 %(file)s 失败" -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "已添加 %(ext)s 格式到 %(book)s" #: cps/gdrive.py:58 msgid "Google Drive setup not completed, try to deactivate and activate Google Drive again" -msgstr "Google Drive 设置未完成,请尝试停用并再次激活Google云端硬盘" +msgstr "Google Drive 设置未完成,请尝试停用并再次激活 Google 云端硬盘" #: cps/gdrive.py:95 msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" -msgstr "回调域名尚未被校验,请在google开发者控制台按步骤校验域名" +msgstr "回调域名尚未被校验,请在 Google 开发者控制台按步骤校验域名" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" -msgstr "找不到id为 %(book)d 的书籍的 %(format)s 格式" +msgstr "找不到 ID 为 %(book)d 的书籍的 %(format)s 格式" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "Google Drive %(fn)s 上找不到 %(format)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "找不到 %(format)s:%(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 -msgid "Send to E-Reader" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" msgstr "发送到电子阅读器" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." -msgstr "此邮件已经通过Calibre-Web发送。" - -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" -msgstr "Calibre-Web测试邮件" +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +msgid "This Email has been sent via Calibre-Web." +msgstr "此邮件已经通过 Calibre-Web 发送" #: cps/helper.py:115 -msgid "Test e-mail" +msgid "Calibre-Web Test Email" +msgstr "Calibre-Web 测试邮件" + +#: cps/helper.py:116 +msgid "Test Email" msgstr "测试邮件" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" -msgstr "开启Calibre-Web之旅" +msgstr "开启 Calibre-Web 之旅" -#: cps/helper.py:137 +#: cps/helper.py:138 #, python-format -msgid "Registration e-mail for user: %(name)s" +msgid "Registration Email for user: %(name)s" msgstr "用户注册电子邮件:%(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "转换 %(orig)s 到 %(format)s 并发送到电子阅读器" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "发送 %(format)s 到电子阅读器" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to E-Reader" -msgstr "%(book)s发送到电子阅读器" +msgid "%(book)s send to eReader" +msgstr "%(book)s 发送到电子阅读器" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "无法读取请求的文件。可能有错误的权限设置?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "阅读状态无法设置: {}" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" -msgstr "删除书的文件夹%(id)s失败,路径有子文件夹:%(path)s" +msgstr "删除书的文件夹 %(id)s 失败,路径有子文件夹:%(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" -msgstr "删除书籍 %(id)s失败:%(message)s" +msgstr "删除书籍 %(id)s 失败:%(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "仅从数据库中删除书籍 %(id)s,数据库中的书籍路径无效: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "将作者从“%(src)s”改为“%(dest)s”时失败,出错信息:%(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" -msgstr "Google Drive上找不到文件 %(file)s" +msgstr "Google Drive 上找不到文件 %(file)s" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "将标题从“%(src)s”改为“%(dest)s”时失败,出错信息:%(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "重命名此路径: {}文件时出错" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" -msgstr "Google Drive上找不到书籍路径 %(path)s" +msgstr "Google Drive 上找不到书籍路径 %(path)s" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "使用此邮箱的账号已经存在。" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "已存在使用此邮箱的账户" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "此用户名已被使用" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" -msgstr "无效的邮件地址格式" +#: cps/helper.py:685 +msgid "Invalid Email address format" +msgstr "无效的邮箱格式" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "密码不符合密码验证规则" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" -msgstr "上传封面需要的Python模块'advocate'未安装" +msgstr "上传封面所需的 Python 模块 'advocate' 未安装" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "下载封面时出错" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "封面格式出错" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "您没有访问本地主机或本地网络进行封面上传" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "创建封面路径失败" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" -msgstr "封面文件不是有效的图片文件,或者无法存储" +msgstr "封面文件不是有效的图片文件,或者无法存储它" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" -msgstr "封面文件只支持jpg/jpeg/png/webp/bmp文件" +msgstr "封面文件只支持 jpg、jpeg、png、webp、bmp 文件" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "封面文件内容无效" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" -msgstr "仅将jpg、jpeg文件作为封面文件" +msgstr "仅将 jpg、jpeg 文件作为封面文件" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" -msgstr "找不到Unrar执行文件" +msgstr "找不到 Unrar 执行文件" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" -msgstr "执行UnRar时出错" +msgstr "执行 UnRar 时出错" -#: cps/helper.py:1040 +#: cps/helper.py:1077 msgid "Cover" msgstr "封面" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" -msgstr "将所有书籍排队以进行元数据备份" +msgstr "将所有书籍加入元数据备份队列" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" -msgstr "请不要使用localhost访问Calibre-Web,以便Kobo设备能获取有效的api_endpoint" +msgstr "请不要从 localhost 访问 Calibre-Web,以便 Kobo 设备能获取有效的 api_endpoint" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo 设置" @@ -816,54 +826,54 @@ msgstr "Kobo 设置" msgid "Register with %(provider)s" msgstr "使用 %(provider)s 注册" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "您现在已以“%(nickname)s”身份登录" #: cps/oauth_bb.py:148 #, python-format msgid "Link to %(oauth)s Succeeded" -msgstr "链接到%(oauth)s成功" +msgstr "链接到 %(oauth)s 成功" #: cps/oauth_bb.py:155 msgid "Login failed, No User Linked With OAuth Account" -msgstr "登录失败,没有用户与OAuth帐户关联" +msgstr "登录失败,没有用户与 OAuth 帐户关联" #: cps/oauth_bb.py:197 #, python-format msgid "Unlink to %(oauth)s Succeeded" -msgstr "取消链接到%(oauth)s成功" +msgstr "取消链接到 %(oauth)s 成功" #: cps/oauth_bb.py:202 #, python-format msgid "Unlink to %(oauth)s Failed" -msgstr "取消链接到%(oauth)s失败" +msgstr "取消链接到 %(oauth)s 失败" #: cps/oauth_bb.py:205 #, python-format msgid "Not Linked to %(oauth)s" -msgstr "为连接到%(oauth)s" +msgstr "未连接到 %(oauth)s" #: cps/oauth_bb.py:261 msgid "Failed to log in with GitHub." -msgstr "使用Github登录失败。" +msgstr "使用 Github 登录失败" #: cps/oauth_bb.py:267 msgid "Failed to fetch user info from GitHub." -msgstr "从Github获取用户信息失败。" +msgstr "从 Github 获取用户信息失败" #: cps/oauth_bb.py:279 msgid "Failed to log in with Google." -msgstr "使用Google登录失败。" +msgstr "使用 Google 登录失败" #: cps/oauth_bb.py:285 msgid "Failed to fetch user info from Google." -msgstr "从Google获取用户信息失败。" +msgstr "从 Google 获取用户信息失败" #: cps/oauth_bb.py:332 msgid "GitHub Oauth error, please retry later." -msgstr "GitHub Oauth 错误,请重试。" +msgstr "GitHub Oauth 错误,请重试" #: cps/oauth_bb.py:335 msgid "GitHub Oauth error: {}" @@ -871,176 +881,177 @@ msgstr "GitHub Oauth 错误: {}" #: cps/oauth_bb.py:356 msgid "Google Oauth error, please retry later." -msgstr "Google Oauth 错误,请重试。" +msgstr "Google Oauth 错误,请重试" #: cps/oauth_bb.py:359 msgid "Google Oauth error: {}" msgstr "Google Oauth 错误: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} 星" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "登录" #: cps/remotelogin.py:74 cps/remotelogin.py:108 msgid "Token not found" -msgstr "找不到Token" +msgstr "找不到令牌" #: cps/remotelogin.py:83 cps/remotelogin.py:116 msgid "Token has expired" -msgstr "Token已过期" +msgstr "令牌已过期" #: cps/remotelogin.py:92 msgid "Success! Please return to your device" msgstr "成功!请返回您的设备" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "书籍" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" -msgstr "显示最近书籍" +msgstr "显示最近查看的书籍" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "热门书籍" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "显示热门书籍" -#: cps/render_template.py:47 cps/render_template.py:52 -msgid "Downloaded Books" -msgstr "下载历史" - #: cps/render_template.py:49 cps/render_template.py:54 +msgid "Downloaded Books" +msgstr "已下载书籍" + +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "显示下载过的书籍" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "最高评分书籍" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "显示最高评分书籍" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "已读书籍" -#: cps/render_template.py:62 -msgid "Show read and unread" -msgstr "显示阅读状态" +#: cps/render_template.py:64 +msgid "Show Read and Unread" +msgstr "显示已读或未读状态" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "未读书籍" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "显示未读" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "发现" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "显示随机书籍" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "分类" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" -msgstr "显示分类选择" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +msgid "Show Category Section" +msgstr "显示分类栏目" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "丛书" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" -msgstr "显示丛书选择" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +msgid "Show Series Section" +msgstr "显示丛书栏目" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "作者" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" -msgstr "显示作者选择" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +msgid "Show Author Section" +msgstr "显示作者栏目" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "出版社" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" -msgstr "显示出版社选择" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +msgid "Show Publisher Section" +msgstr "显示出版社栏目" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "语言" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" -msgstr "显示语言选择" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +msgid "Show Language Section" +msgstr "显示语言栏目" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "评分" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" -msgstr "显示评分选择" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +msgid "Show Ratings Section" +msgstr "显示评分栏目" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "文件格式" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" -msgstr "显示文件格式选择" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +msgid "Show File Formats Section" +msgstr "显示文件格式栏目" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "归档书籍" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +msgid "Show Archived Books" msgstr "显示归档书籍" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "书籍列表" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "显示书籍列表" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "搜索" @@ -1063,15 +1074,15 @@ msgid "Rating >= %(rating)s" msgstr "评分 >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "阅读状态 = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" -msgstr "搜索自定义列时出错,请重启 Calibre-Web" +msgstr "搜索自定义栏目时出错,请重启 Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "高级搜索" @@ -1121,7 +1132,7 @@ msgstr "此书已从书架 %(sname)s 中删除" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "抱歉,您没有从这个书架删除书籍的权限" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "创建书架" @@ -1146,79 +1157,79 @@ msgstr "书架已成功删除" msgid "Change order of Shelf: '%(name)s'" msgstr "修改书架 %(name)s 顺序" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "抱歉,您没有创建公开书架的权限" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "书架 %(title)s 已创建" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "书架 %(title)s 已修改" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "发生错误" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." -msgstr "公共书架:%(title)s已经存在已经存在。" +msgstr "公共书架:%(title)s 已经存在已经存在" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." -msgstr "私有书架:%(title)s已经存在已经存在。" +msgstr "私有书架:%(title)s 已经存在已经存在" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "书架:%(name)s" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "打开书架出错。书架不存在或不可访问" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "任务列表" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "等待中" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "失败" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "已开始" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "已完成" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "已结束" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "已取消" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "未知状态" #: cps/updater.py:431 cps/updater.py:442 cps/updater.py:543 cps/updater.py:558 msgid "Unexpected data while reading update information" -msgstr "读取更新信息时出现意外数据" +msgstr "读取更新信息时出现异常数据" #: cps/updater.py:438 cps/updater.py:550 msgid "No update available. You already have the latest version installed" @@ -1226,7 +1237,7 @@ msgstr "无可用更新。您已经安装了最新版本" #: cps/updater.py:456 msgid "A new update is available. Click on the button below to update to the latest version." -msgstr "有新的更新。单击下面的按钮以更新到最新版本。" +msgstr "有新的更新。单击下面的按钮以更新到最新版本" #: cps/updater.py:474 msgid "Could not fetch update information" @@ -1234,7 +1245,7 @@ msgstr "无法获取更新信息" #: cps/updater.py:484 msgid "Click on the button below to update to the latest stable version." -msgstr "点击下面按钮更新到最新稳定版本。" +msgstr "点击下面按钮更新到最新稳定版本" #: cps/updater.py:493 cps/updater.py:507 cps/updater.py:518 #, python-format @@ -1245,150 +1256,181 @@ msgstr "有新的更新。单击下面的按钮以更新到版本: %(version)s" msgid "No release information available" msgstr "无可用发布信息" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" -msgstr "发现(随机书籍)" +msgstr "发现 (随机书籍)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "热门书籍(最多下载)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "%(user)s 下载过的书籍" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "作者:%(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "出版社:%(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "丛书:%(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "评分:无" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "评分:%(rating)s 星" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "文件格式:%(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "分类:%(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "语言:%(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "下载次数" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "评分列表" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "文件格式列表" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "书籍已经成功加入 %(kindlemail)s 的发送队列" +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "请先配置 SMTP 邮箱设置..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "书籍已经成功加入 %(eReadermail)s 的发送队列" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "糟糕!发送这本书籍的时候出现错误:%(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." -msgstr "请先配置您的kindle邮箱。" +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." +msgstr "请先配置您的 Kindle 邮箱" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "邮件服务未配置,请联系网站管理员!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "请等待一分钟注册下一个用户" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "注册" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "邮件服务未配置,请联系网站管理员!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "您的电子邮件不允许注册" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." -msgstr "确认邮件已经发送到您的邮箱。" +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "确认邮件已经发送到您的邮箱" -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" -msgstr "无法激活LDAP认证" +msgstr "无法激活 LDAP 认证" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "下次登录前请等待一分钟" + +#: cps/web.py:1376 +#, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "您现在已以“%(nickname)s”身份登录" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" -msgstr "后备登录“%(nickname)s”:无法访问LDAP服务器,或用户未知" +msgstr "后备登录“%(nickname)s”:无法访问 LDAP 服务器,或用户未知" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "无法登录:%(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "用户名或密码错误" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "新密码已发送到您的邮箱" -#: cps/web.py:1320 +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "发生一个未知错误,请稍后再试" + +#: cps/web.py:1405 msgid "Please enter valid username to reset password" msgstr "请输入有效的用户名进行密码重置" -#: cps/web.py:1327 +#: cps/web.py:1413 #, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "您现在已以“%(nickname)s”登录" +msgstr "您现在已以“%(nickname)s”身份登录" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s 的用户配置" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +msgid "Success! Profile Updated" msgstr "资料已更新" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "使用此邮箱的账号已经存在" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "找不到包含 OAuth 信息的有效 gmail.json 文件" +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s 发送到电子阅读器" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" -msgstr "Calibre 电子书转换器%(tool)s没有发现" +msgstr "Calibre 电子书转换器 %(tool)s 没有发现" #: cps/tasks/convert.py:186 #, python-format @@ -1407,7 +1449,7 @@ msgstr "Kepubify 转换失败:%(error)s" #: cps/tasks/convert.py:224 #, python-format msgid "Converted file not found or more than one file in folder %(folder)s" -msgstr "找不到转换后的文件或文件夹%(folder)s中有多个文件" +msgstr "找不到转换后的文件或文件夹 %(folder)s 中有多个文件" #: cps/tasks/convert.py:247 #, python-format @@ -1425,36 +1467,36 @@ msgstr "转换" #: cps/tasks/database.py:28 msgid "Reconnecting Calibre database" -msgstr "正在重新连接到Calibre数据库" +msgstr "正在重新连接到 Calibre 数据库" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "电子邮件" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 msgid "Backing up Metadata" msgstr "正在备份元数据" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "生成了 %(count)s 个封面缩略图" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "封面缩略图" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "生成了 %(count)s 个丛书缩略图" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "正在清理封面缩略图缓存" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "上传书籍" @@ -1470,14 +1512,14 @@ msgstr "用户名" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "邮箱地址" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "接收书籍的电子阅读器邮箱地址" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "管理权限" @@ -1487,8 +1529,8 @@ msgstr "管理权限" msgid "Password" msgstr "密码" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "下载书籍" @@ -1513,25 +1555,21 @@ msgstr "删除数据" msgid "Public Shelf" msgstr "公共书架" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "添加新用户" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" -msgstr "导入LDAP用户" +msgstr "导入 LDAP 用户" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" -msgstr "SMTP邮件服务器设置" +msgid "Email Server Settings" +msgstr "SMTP 邮件服务器设置" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 msgid "SMTP Hostname" -msgstr "SMTP主机名" +msgstr "SMTP 主机名" #: cps/templates/admin.html:71 cps/templates/email_edit.html:35 msgid "SMTP Port" -msgstr "SMTP端口" +msgstr "SMTP 端口" #: cps/templates/admin.html:75 cps/templates/email_edit.html:39 msgid "Encryption" @@ -1539,20 +1577,20 @@ msgstr "加密" #: cps/templates/admin.html:79 cps/templates/email_edit.html:47 msgid "SMTP Login" -msgstr "SMTP用户名" +msgstr "SMTP 用户名" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "发件人邮箱" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "电子邮件服务" #: cps/templates/admin.html:91 msgid "Gmail via Oauth2" -msgstr "通过Oauth2的Gmail" +msgstr "使用 Oauth2 的 Gmail" #: cps/templates/admin.html:106 msgid "Configuration" @@ -1604,7 +1642,7 @@ msgstr "反向代理头部名称" #: cps/templates/admin.html:159 msgid "Edit Calibre Database Configuration" -msgstr "编辑Calibre数据库配置" +msgstr "编辑 Calibre 数据库配置" #: cps/templates/admin.html:160 msgid "Edit Basic Configuration" @@ -1619,102 +1657,104 @@ msgid "Scheduled Tasks" msgstr "计划任务" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "任务开始运行的时间" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "最长任务持续时间" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "生成书籍封面缩略图" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "生成丛书封面缩略图" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" -msgstr "重新连接到Calibre库" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" +msgstr "重新连接到 Calibre 库" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "生成元数据备份文件" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" msgstr "刷新封面缩略图缓存" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:203 msgid "Administration" msgstr "管理" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" -msgstr "下载Debug包" +msgstr "下载 Debug 包" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "查看日志文件" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "重新连接到Calibre数据库" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "重启" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "停止" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "版本信息" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "版本" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "详情" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "当前版本" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "检查更新" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "执行更新" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "您确定要重启吗?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "确定" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "取消" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "您确定要关闭吗?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "正在更新,请不要刷新页面" @@ -1776,7 +1816,7 @@ msgstr "删除格式:" #: cps/templates/book_edit.html:25 msgid "Convert book format:" -msgstr "转换书籍格式:" +msgstr "书籍格式转换:" #: cps/templates/book_edit.html:30 msgid "Convert from:" @@ -1804,7 +1844,7 @@ msgid "Author" msgstr "作者" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "简介" @@ -1829,7 +1869,7 @@ msgstr "移除" msgid "Add Identifier" msgstr "添加书号" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "标签" @@ -1843,7 +1883,7 @@ msgstr "评分" #: cps/templates/book_edit.html:104 msgid "Fetch Cover from URL (JPEG - Image will be downloaded and stored in database)" -msgstr "从URL获取封面(JPEG - 图片将下载并存储在数据库中)" +msgstr "从 URL 获取封面(JPEG - 图片将下载并存储在数据库中)" #: cps/templates/book_edit.html:108 msgid "Upload Cover from Local Disk" @@ -1854,23 +1894,23 @@ msgid "Published Date" msgstr "出版日期" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "出版社" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "语言" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "确认" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "没有" @@ -1887,8 +1927,8 @@ msgid "Fetch Metadata" msgstr "获取元数据" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1910,8 +1950,8 @@ msgstr "单击封面将元数据加载到表单" msgid "Loading..." msgstr "加载中..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "关闭" @@ -1926,7 +1966,7 @@ msgstr "搜索错误!" #: cps/templates/book_edit.html:288 msgid "No Result(s) found! Please try another keyword." -msgstr "无搜索结果!请尝试另一个关键字。" +msgstr "无搜索结果!请尝试另一个关键字" #: cps/templates/book_table.html:12 cps/templates/book_table.html:69 #: cps/templates/user_table.html:14 cps/templates/user_table.html:77 @@ -2053,7 +2093,7 @@ msgstr "Calibre 数据库路径" #: cps/templates/config_db.html:22 msgid "Use Google Drive?" -msgstr "是否使用Google Drive?" +msgstr "是否使用 Google Drive?" #: cps/templates/config_db.html:27 msgid "Authenticate Google Drive" @@ -2065,7 +2105,7 @@ msgstr "Google Drive Calibre 路径" #: cps/templates/config_db.html:40 msgid "Metadata Watch Channel ID" -msgstr "元数据监视通道ID" +msgstr "元数据监视通道 ID" #: cps/templates/config_db.html:43 msgid "Revoke" @@ -2085,11 +2125,11 @@ msgstr "服务器端口" #: cps/templates/config_edit.html:28 msgid "SSL certfile location (leave it empty for non-SSL Servers)" -msgstr "SSL 证书文件路径(非SSL服务器请留空)" +msgstr "SSL 证书文件路径 (非 SSL 服务器请留空)" #: cps/templates/config_edit.html:35 msgid "SSL Keyfile location (leave it empty for non-SSL Servers)" -msgstr "SSL 密钥文件路径(非SSL服务器请留空)" +msgstr "SSL 密钥文件路径 (非 SSL 服务器请留空)" #: cps/templates/config_edit.html:43 msgid "Update Channel" @@ -2113,7 +2153,7 @@ msgstr "日志文件配置" #: cps/templates/config_edit.html:77 msgid "Location and name of logfile (calibre-web.log for no entry)" -msgstr "日志文件路径和名称(默认为calibre-web.log)" +msgstr "日志文件路径和名称 (默认为 calibre-web.log)" #: cps/templates/config_edit.html:82 msgid "Enable Access Log" @@ -2121,7 +2161,7 @@ msgstr "启用访问日志" #: cps/templates/config_edit.html:85 msgid "Location and name of access logfile (access.log for no entry)" -msgstr "访问日志路径和名称(默认为access.log)" +msgstr "访问日志路径和名称 (默认为 access.log)" #: cps/templates/config_edit.html:96 msgid "Feature Configuration" @@ -2136,7 +2176,7 @@ msgid "Enable Uploads" msgstr "启用上传" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "(请确保用户也有上传权限)" #: cps/templates/config_edit.html:112 @@ -2152,7 +2192,7 @@ msgid "Enable Public Registration" msgstr "启用注册" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "使用邮箱或用户名" #: cps/templates/config_edit.html:132 @@ -2161,23 +2201,23 @@ msgstr "启用魔法链接远程登录" #: cps/templates/config_edit.html:137 msgid "Enable Kobo sync" -msgstr "启用Kobo同步" +msgstr "启用 Kobo 同步" #: cps/templates/config_edit.html:142 msgid "Proxy unknown requests to Kobo Store" -msgstr "代理未知请求到Kobo商店" +msgstr "代理未知请求到 Kobo 商店" #: cps/templates/config_edit.html:145 msgid "Server External Port (for port forwarded API calls)" -msgstr "服务器扩展端口(用于转发的API调用的端口)" +msgstr "服务器扩展端口 (用于转发的 API 调用的端口)" #: cps/templates/config_edit.html:153 msgid "Use Goodreads" -msgstr "使用Goodreads" +msgstr "使用 Goodreads" #: cps/templates/config_edit.html:154 msgid "Create an API Key" -msgstr "创建API Key" +msgstr "创建 API Key" #: cps/templates/config_edit.html:158 msgid "Goodreads API Key" @@ -2201,19 +2241,19 @@ msgstr "使用标准认证" #: cps/templates/config_edit.html:184 msgid "Use LDAP Authentication" -msgstr "使用LDAP认证" +msgstr "使用 LDAP 认证" #: cps/templates/config_edit.html:187 msgid "Use OAuth" -msgstr "使用OAuth认证" +msgstr "使用 OAuth 认证" #: cps/templates/config_edit.html:194 msgid "LDAP Server Host Name or IP Address" -msgstr "LDAP服务器主机名或IP地址" +msgstr "LDAP 服务器主机名或 IP 地址" #: cps/templates/config_edit.html:198 msgid "LDAP Server Port" -msgstr "LDAP服务器端口" +msgstr "LDAP 服务器端口" #: cps/templates/config_edit.html:202 msgid "LDAP Encryption" @@ -2221,23 +2261,23 @@ msgstr "LDAP 加密" #: cps/templates/config_edit.html:205 msgid "TLS" -msgstr "TLS协议" +msgstr "TLS 协议" #: cps/templates/config_edit.html:206 msgid "SSL" -msgstr "SSL协议" +msgstr "SSL 协议" #: cps/templates/config_edit.html:210 msgid "LDAP CACertificate Path (Only needed for Client Certificate Authentication)" -msgstr "LDAP CA证书路径(仅用于客户端证书认证)" +msgstr "LDAP CA证书路径 (仅用于客户端证书认证)" #: cps/templates/config_edit.html:217 msgid "LDAP Certificate Path (Only needed for Client Certificate Authentication)" -msgstr "LDAP 证书路径(仅用于客户端证书认证)" +msgstr "LDAP 证书路径 (仅用于客户端证书认证)" #: cps/templates/config_edit.html:224 msgid "LDAP Keyfile Path (Only needed for Client Certificate Authentication)" -msgstr "LDAP密钥文件路径(仅用于客户端证书认证)" +msgstr "LDAP 密钥文件路径 (仅用于客户端证书认证)" #: cps/templates/config_edit.html:233 msgid "LDAP Authentication" @@ -2257,23 +2297,23 @@ msgstr "简单" #: cps/templates/config_edit.html:242 msgid "LDAP Administrator Username" -msgstr "LDAP管理员用户名" +msgstr "LDAP 管理员用户名" #: cps/templates/config_edit.html:248 msgid "LDAP Administrator Password" -msgstr "LDAP管理员密码" +msgstr "LDAP 管理员密码" #: cps/templates/config_edit.html:253 msgid "LDAP Distinguished Name (DN)" -msgstr "LDAP专有名称(DN)" +msgstr "LDAP 专有名称(DN)" #: cps/templates/config_edit.html:257 msgid "LDAP User Object Filter" -msgstr "LDAP用户对象过滤器" +msgstr "LDAP 用户对象过滤器" #: cps/templates/config_edit.html:262 msgid "LDAP Server is OpenLDAP?" -msgstr "LDAP服务器是 OpenLDAP?" +msgstr "LDAP 服务器为 OpenLDAP?" #: cps/templates/config_edit.html:264 msgid "Following Settings are Needed For User Import" @@ -2281,19 +2321,19 @@ msgstr "用户导入需要以下设置" #: cps/templates/config_edit.html:266 msgid "LDAP Group Object Filter" -msgstr "LDAP组对象过滤器" +msgstr "LDAP 组对象过滤器" #: cps/templates/config_edit.html:270 msgid "LDAP Group Name" -msgstr "LDAP组名" +msgstr "LDAP 组名" #: cps/templates/config_edit.html:274 msgid "LDAP Group Members Field" -msgstr "LDAP组成员字段" +msgstr "LDAP 组成员字段" #: cps/templates/config_edit.html:278 msgid "LDAP Member User Filter Detection" -msgstr "LDAP成员用户过滤器探测" +msgstr "LDAP 成员用户过滤器探测" #: cps/templates/config_edit.html:280 msgid "Autodetect" @@ -2305,17 +2345,17 @@ msgstr "自定义过滤器" #: cps/templates/config_edit.html:286 msgid "LDAP Member User Filter" -msgstr "LDAP成员用户过滤器" +msgstr "LDAP 成员用户过滤器" #: cps/templates/config_edit.html:297 #, python-format msgid "Obtain %(provider)s OAuth Credential" -msgstr "获取 %(provider)s OAuth凭证" +msgstr "获取 %(provider)s OAuth 凭证" #: cps/templates/config_edit.html:300 #, python-format msgid "%(provider)s OAuth Client Id" -msgstr "%(provider)s OAuth 客户端 Secret" +msgstr "%(provider)s OAuth 客户端 Id" #: cps/templates/config_edit.html:304 #, python-format @@ -2340,7 +2380,51 @@ msgstr "KEpubify 电子书转换器路径" #: cps/templates/config_edit.html:345 msgid "Location of Unrar binary" -msgstr "Unrar程序路径" +msgstr "Unrar 程序路径" + +#: cps/templates/config_edit.html:361 +msgid "Security Settings" +msgstr "安全设置" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "限制失败的登录尝试" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "会话保护" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "基本" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "强" + +#: cps/templates/config_edit.html:380 +msgid "User Password policy" +msgstr "用户密码策略" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "最小密码长度" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "必须使用数字" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "必须使用小写字符" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "必须使用大写字符" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "必须使用特殊字符" #: cps/templates/config_view_edit.html:17 msgid "View Configuration" @@ -2354,7 +2438,7 @@ msgstr "随机书籍显示数量" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "主页中书籍作者的最大显示数量(0=不隐藏)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "主题" @@ -2443,80 +2527,82 @@ msgstr "添加显示或隐藏书籍的标签值" msgid "Add Allowed/Denied custom column values" msgstr "添加显示或隐藏书籍的自定义栏目值" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "在线阅读" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "在线听书" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" -msgstr "%(range)s 第%(index)s册" +msgstr "%(range)s 第 %(index)s 册" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "出版日期" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "标为未读" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "标为已读" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "已读" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "从档案还原" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "添加到归档" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "归档" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "简介:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "添加到书架" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(公共)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "编辑元数据" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "选择服务器类型" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" -msgstr "使用标准电子邮件账号" +msgid "Standard Email Account" +msgstr "标准电子邮件" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "使用Gmail账号" +msgid "Gmail Account" +msgstr "Gmail 账户" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "设置Gmail账号作为电子邮件服务" +msgid "Setup Gmail Account" +msgstr "设置 Gmail 账户" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2524,25 +2610,25 @@ msgstr "撤消 Gmail 访问权限" #: cps/templates/email_edit.html:42 msgid "STARTTLS" -msgstr "STARTTLS协议" +msgstr "STARTTLS 协议" #: cps/templates/email_edit.html:43 msgid "SSL/TLS" -msgstr "SSL/TLS协议" +msgstr "SSL/TLS 协议" #: cps/templates/email_edit.html:51 msgid "SMTP Password" -msgstr "SMTP密码" +msgstr "SMTP 密码" #: cps/templates/email_edit.html:58 msgid "Attachment Size Limit" msgstr "附件大小限制" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +msgid "Save and Send Test Email" msgstr "保存设置并发送测试邮件" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "后退" @@ -2568,13 +2654,13 @@ msgstr "输入域名" msgid "Denied Domains (Blacklist)" msgstr "禁止注册的域名(黑名单)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "下一个" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "在文本编辑器中打开.kobo/Kobo eReader.conf,添加(或编辑):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "在文本编辑器中打开 .kobo/Kobo/Kobo eReader.conf,添加(或编辑):" #: cps/templates/generate_kobo_auth_url.html:11 msgid "Kobo Token:" @@ -2584,19 +2670,19 @@ msgstr "Kobo Token:" msgid "List" msgstr "列表" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Calibre-Web 实例未配置,请联系您的管理员!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "创建问题" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "回到首页" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "登出账号" @@ -2626,80 +2712,80 @@ msgstr "按丛书编号排序" msgid "Sort descending according to series index" msgstr "按丛书编号逆排序" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "开始" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "字母排序书籍" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "按字母排序的书籍" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." -msgstr "基于下载数的热门书籍。" +msgstr "基于下载数的热门书籍" -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." -msgstr "基于评分的热门书籍。" +msgstr "基于评分的热门书籍" -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "最近添加的书籍" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "最新书籍" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "随机书籍" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "书籍按作者排序" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "书籍按出版社排序" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "书籍按分类排序" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "书籍按丛书排序" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "书籍按语言排序" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "书籍按评分排序" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "书籍按文件格式排序" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "书架列表" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "书架上的书" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "首页" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "切换导航" @@ -2707,48 +2793,48 @@ msgstr "切换导航" msgid "Search Library" msgstr "搜索书库" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "正在上传..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "错误" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "上传完成,正在处理,请稍候..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "设置" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "账号" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "注销" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "正在上传..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "错误" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "上传完成,正在处理,请稍候..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "设置" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "请不要刷新页面" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "按条件浏览" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "关于" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "上一个" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "书籍详情" @@ -2764,13 +2850,13 @@ msgstr "记住我" msgid "Forgot Password?" msgstr "忘记密码?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "通过魔法链接登录" #: cps/templates/logviewer.html:6 msgid "Show Calibre-Web Log: " -msgstr "显示Calibre-Web日志: " +msgstr "显示 Calibre-Web 日志: " #: cps/templates/logviewer.html:8 msgid "Calibre-Web Log: " @@ -2786,7 +2872,7 @@ msgstr "显示访问日志: " #: cps/templates/logviewer.html:18 msgid "Download Calibre-Web Log" -msgstr "下载Calibre-Web日志" +msgstr "下载 Calibre-Web 日志" #: cps/templates/logviewer.html:21 msgid "Download Access Log" @@ -2794,19 +2880,19 @@ msgstr "下载访问日志" #: cps/templates/modal_dialogs.html:6 msgid "Select Allowed/Denied Tags" -msgstr "选择标签值显示或隐藏书籍" +msgstr "选择显示的与隐藏的标签" #: cps/templates/modal_dialogs.html:7 msgid "Select Allowed/Denied Custom Column Values" -msgstr "选择自定义栏目值显示或隐藏本用户书籍" +msgstr "选择显示的自定义栏目值与隐藏的自定义栏目值" #: cps/templates/modal_dialogs.html:8 msgid "Select Allowed/Denied Tags of User" -msgstr "选择标签值显示或隐藏书籍" +msgstr "选择此用户显示的标签与隐藏的标签" #: cps/templates/modal_dialogs.html:9 msgid "Select Allowed/Denied Custom Column Values of User" -msgstr "选择自定义栏目值显示或隐藏本用户书籍" +msgstr "选择此用户显示的自定义栏目值与隐藏的自定义栏目值" #: cps/templates/modal_dialogs.html:15 msgid "Enter Tag" @@ -2818,7 +2904,7 @@ msgstr "添加显示或隐藏书籍的值" #: cps/templates/modal_dialogs.html:50 msgid "This book format will be permanently erased from database" -msgstr "此书籍格式将从数据库中永久删除" +msgstr "书籍的此格式副本将从数据库中永久删除" #: cps/templates/modal_dialogs.html:51 msgid "This book will be permanently erased from database" @@ -2830,11 +2916,11 @@ msgstr ",包括从硬盘中" #: cps/templates/modal_dialogs.html:56 msgid "Important Kobo Note: deleted books will remain on any paired Kobo device." -msgstr "Kobo 重要说明:被删除的书籍将保留在任何配对的 Kobo 设备上。" +msgstr "Kobo 重要提示:被删除的书籍将保留在任何配对的 Kobo 设备上" #: cps/templates/modal_dialogs.html:57 msgid "Books must first be archived and the device synced before a book can safely be deleted." -msgstr "必须先将书籍存档并同步设备,然后才能安全地删除书籍。" +msgstr "在安全删除图书之前,必须先将图书归档并与设备同步" #: cps/templates/modal_dialogs.html:76 msgid "Choose File Location" @@ -2866,155 +2952,179 @@ msgstr "完成" #: cps/templates/osd.xml:5 msgid "Calibre-Web eBook Catalog" -msgstr "Caliebre-Web电子书路径" +msgstr "Caliebre-Web 电子书路径" #: cps/templates/read.html:6 msgid "epub Reader" -msgstr "epub阅读器" +msgstr "epub 阅读器" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "浅色" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "深色" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "棕色" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 msgid "Black" msgstr "黑色" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." -msgstr "打开侧栏时重排文本。" +msgstr "打开侧栏时重排文本" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "字体大小" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" -msgstr "Comic阅读器" +msgstr "Comic 阅读器" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "快捷键" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "上一页" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "下一页" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "单页显示" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "长条显示" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "缩放到最佳" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "按宽度缩放" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "按高度缩放" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "缩放到原始大小" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "向右旋转" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "向左旋转" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "翻转图片" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "显示" + +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "单页" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "长条" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "缩放" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "最佳" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "宽度" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "高度" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "原始" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "旋转" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "翻转" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "水平" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "垂直" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "方向" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "从左到右" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "从右到左" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "重置为顶部" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "记住位置" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "工具栏" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "显示" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "隐藏" #: cps/templates/readdjvu.html:5 msgid "DJVU Reader" -msgstr "DJVU阅读器" +msgstr "DJVU 阅读器" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" -msgstr "PDF阅读器" +msgstr "PDF 阅读器" #: cps/templates/readtxt.html:6 msgid "txt Reader" -msgstr "txt阅读器" +msgstr "txt 阅读器" #: cps/templates/register.html:4 msgid "Register New Account" @@ -3025,7 +3135,7 @@ msgid "Choose a username" msgstr "选择一个用户名" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "您的邮箱地址" #: cps/templates/remote_login.html:5 @@ -3038,15 +3148,11 @@ msgstr "在另一个设备上,登录并访问:" #: cps/templates/remote_login.html:11 msgid "Once verified, you will automatically be logged in on this device." -msgstr "验证后,您将自动在新设备上登录。" +msgstr "验证后,您将自动在新设备上登录" #: cps/templates/remote_login.html:14 msgid "This verification link will expire in 10 minutes." -msgstr "此验证链接将在10分钟后失效。" - -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "生成书籍封面缩略图" +msgstr "此验证链接将在10分钟后失效" #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" @@ -3072,43 +3178,51 @@ msgstr "出版日期从" msgid "Published Date To" msgstr "出版日期到" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "排除标签" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "排除丛书" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "排除书架" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "排除语言" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "扩展名" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "排除扩展名" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "评分大于" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "评分小于" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "从:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "到:" @@ -3200,17 +3314,13 @@ msgstr "任务进度" msgid "Run Time" msgstr "运行时间" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "开始时间" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "活动" #: cps/templates/tasks.html:40 msgid "This task will be cancelled. Any progress made by this task will be saved." -msgstr "这个任务将被取消。此任务取得的所有进展都将被保存" +msgstr "这个任务将被取消。此任务所有的更改都将被保存" #: cps/templates/tasks.html:41 msgid "If this is a scheduled task, it will be re-ran during the next scheduled time." @@ -3226,7 +3336,7 @@ msgstr "按语言显示书籍" #: cps/templates/user_edit.html:54 msgid "OAuth Settings" -msgstr "OAuth设置" +msgstr "OAuth 设置" #: cps/templates/user_edit.html:56 msgid "Link" @@ -3246,7 +3356,7 @@ msgstr "新建或查看" #: cps/templates/user_edit.html:70 msgid "Force full kobo sync" -msgstr "强制与kobo完全同步" +msgstr "强制与 Kobo 完全同步" #: cps/templates/user_edit.html:88 msgid "Add allowed/Denied Custom Column Values" @@ -3262,7 +3372,7 @@ msgstr "删除此用户" #: cps/templates/user_edit.html:159 msgid "Generate Kobo Auth URL" -msgstr "生成Kobo Auth 地址" +msgstr "生成 Kobo Auth 地址" #: cps/templates/user_table.html:80 cps/templates/user_table.html:103 msgid "Select..." @@ -3277,15 +3387,15 @@ msgid "Enter Username" msgstr "输入用户名" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "输入邮箱地址" +msgid "Enter Email" +msgstr "输入邮箱" #: cps/templates/user_table.html:136 -msgid "Enter E-Reader E-mail Address" -msgstr "输入电子阅读器邮箱地址" +msgid "Enter eReader Email" +msgstr "接收书籍的电子阅读器邮箱" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "电子阅读器邮箱" #: cps/templates/user_table.html:137 @@ -3306,11 +3416,11 @@ msgstr "允许标签" #: cps/templates/user_table.html:140 msgid "Edit Denied Tags" -msgstr "编辑拒绝标签" +msgstr "编辑被拒绝标签" #: cps/templates/user_table.html:140 msgid "Denied Tags" -msgstr "拒绝标签" +msgstr "被拒绝标签" #: cps/templates/user_table.html:141 msgid "Edit Allowed Column Values" @@ -3345,10 +3455,6 @@ msgid "Sync selected Shelves with Kobo" msgstr "同步所选书架到 Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" -msgstr "显示已读/未读选择" - -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "显示随机书籍" +msgid "Show Read/Unread Section" +msgstr "显示已读、未读栏目" diff --git a/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.mo b/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.mo index 435d0a76..6c2ef935 100644 Binary files a/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.mo and b/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.mo differ diff --git a/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.po b/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.po index b7d043d9..7c340a9b 100644 --- a/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.po +++ b/cps/translations/zh_Hant_TW/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Calibre-Web\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: 2020-09-27 22:18+0800\n" "Last-Translator: xlivevil \n" "Language: zh_TW\n" @@ -16,489 +16,499 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "統計" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +#, fuzzy +msgid "Server restarted, please reload page." msgstr "服務器已重啟,請刷新頁面" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" +#: cps/admin.py:151 +#, fuzzy +msgid "Performing Server shutdown, please close window." msgstr "正在關閉服務器,請關閉窗口" -#: cps/admin.py:156 -msgid "Reconnect successful" -msgstr "重新連接成功" - #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "未知命令" -#: cps/admin.py:169 +#: cps/admin.py:173 #, fuzzy -msgid "Books successfully queued for Metadata Backup" -msgstr "書籍已經成功加入 %(kindlemail)s 的發送隊列" +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" +msgstr "發送給%(email)s的測試郵件已進入隊列。請檢查任務結果" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "未知" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "管理頁" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "基本配置" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "界面配置" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "管理用戶" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "全部" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "找不到用戶" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "成功刪除 {} 個用戶" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "顯示全部" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "格式錯誤的請求" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "訪客名稱無法更改" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "遊客無法擁有此角色" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "管理員賬戶不存在,無法刪除管理員角色" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "值必須是 true 或 false" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "無效角色" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "遊客無法擁有此視圖" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "無效視圖" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "訪客的本地化是自動偵測而無法設置的" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "無可用本地化" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "無有效書籍語言" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "參數未找到" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "無效的閱讀列" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "無效的限制列" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "Calibre-Web配置已更新" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "您確定刪除Kobo Token嗎?" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "您確定要刪除此網域嗎?" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "您確定要刪除此用戶嗎?" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "您確定要刪除此書架嗎?" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "您確定要修改選定用戶的本地化設置嗎?" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "您確定要修改選定用戶的可見書籍語言嗎?" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "您確定要修改選定用戶的選定角色嗎?" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "您確定要修改選定用戶的選定限制嗎?" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "您確定要修改選定用戶的選定可視化限制嗎?" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "您確定要更改所選用戶的書架同步行為嗎?" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "您確定要更改 Calibre 庫位置嗎?" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "拒絕" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "允許" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "標籤未找到" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "無效的動作" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "client_secrets.json 未為 Web 應用程序配置" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "日誌文件路徑無效,請輸入正確的路徑" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "訪問日誌路徑無效,請輸入正確的路徑" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "請輸入LDAP主機、端口、DN和用戶對象標識符" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "請輸入一個LDAP服務賬號和密碼 " -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "請輸入一個LDAP服務賬號" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "LDAP群組對象過濾器需要一個具有“%s”格式標識符號" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "LDAP群組對象過濾器的括號不匹配" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP用戶對象過濾器需要一個具有“%s”格式標識符" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "LDAP用戶對象過濾器的括號不匹配" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "LDAP成員用戶過濾器需要有一個“%s”格式標識符號" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "LDAP成員用戶過濾器中有不匹配的括號" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "LDAP CA證書、證書或密鑰位置無效,請輸入正確的路徑" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "添加新用戶" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "編輯郵件服務器設置" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" -msgstr "G-Mail賬號驗證成功" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." +msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "數據庫錯誤:%(error)s。" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "發送給%(email)s的測試郵件已進入隊列。請檢查任務結果" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "發送測試郵件時出錯:%(res)s" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "請先配置您的郵箱地址..." -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "郵件服務器設置已更新" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "發生一個未知錯誤,請稍後再試。" -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "編輯用戶 %(nick)s" -#: cps/admin.py:1411 -#, python-format -msgid "Password for user %(user)s reset" +#: cps/admin.py:1436 +#, fuzzy, python-format +msgid "Success! Password for user %(user)s reset" msgstr "用戶 %(user)s 的密碼已重置" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +#, fuzzy +msgid "Oops! Please configure the SMTP mail settings." msgstr "請先配置SMTP郵箱設置..." -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "日誌文件查看器" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "正在請求更新包" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "正在下載更新包" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "正在解壓更新包" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "正在替換文件" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "數據庫連接已關閉" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "正在停止服務器" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "更新完成,請點擊確定並刷新頁面" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "更新失敗:" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "HTTP錯誤" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "連接錯誤" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "建立連接超時" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "一般錯誤" -#: cps/admin.py:1505 +#: cps/admin.py:1530 #, fuzzy msgid "Update file could not be saved in temp dir" msgstr "更新文件無法保存在臨時目錄中" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "更新時檔案無法替換變更" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "未能提取至少一個LDAP用戶" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "未能創建至少一個LDAP用戶" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "錯誤:%(ldaperror)s" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "錯誤:在LDAP服務器的響應中沒有返回用戶" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "數據庫中沒有找到至少一個LDAP用戶" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "{} 用戶被成功導入" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "數據庫路徑無效,請輸入正確的路徑" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "數據庫不可寫入" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "密鑰文件路徑無效,請輸入正確的路徑" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "證書文件路徑無效,請輸入正確的路徑" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 #, fuzzy msgid "Database Settings updated" msgstr "郵件服務器設置已更新" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "數據庫配置" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "請填寫所有欄位!" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "郵箱不在有效網域中" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "添加新用戶" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "用戶“%(user)s”已創建" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "使用此郵箱或用戶名的賬號已經存在。" -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "用戶“%(nick)s”已刪除" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "無法刪除訪客用戶" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "管理員賬戶不存在,無法刪除用戶" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "用戶“%(nick)s”已更新" @@ -511,122 +521,122 @@ msgstr "未安裝" msgid "Execution permissions missing" msgstr "缺少執行權限" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, fuzzy, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "自定義列號:%(column)d在Calibre數據庫中不存在" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "無" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "糟糕!選擇書名無法打開。文件不存在或者文件不可訪問" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "標識符不區分大小寫,覆蓋舊標識符" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "已成功更新元數據" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "文件 %(file)s 已上傳" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "轉換的來源或目的格式不存在" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "書籍已經被成功加入到 %(book_format)s 格式轉換隊列" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "轉換此書籍時出現錯誤: %(res)s" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "上傳的書籍可能已經存在,建議修改後重新上傳: " -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, fuzzy, python-format msgid "'%(langname)s' is not a valid language" msgstr "%(langname)s 不是一種有效語言" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "不能上傳文件附檔名為“%(ext)s”的文件到此服務器" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "要上傳的文件必須具有附檔名" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "文件 %(filename)s 無法保存到臨時目錄" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "移動封面文件失敗 %(file)s:%(error)s" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "書籍格式已成功刪除" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "書籍已成功刪除" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "編輯元數據" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "%(seriesindex)s 不是一個有效的數值,忽略" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "創建路徑 %(path)s 失敗(權限拒絕)。" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "保存文件 %(file)s 失敗。" -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "已添加 %(ext)s 格式到 %(book)s" @@ -639,182 +649,189 @@ msgstr "Google Drive 設置未完成,請嘗試停用並再次激活Google雲 msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "回調網域名稱尚未被驗證,請在google開發者控制台按步驟驗證網域名稱" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "找不到id為 %(book)d 的書籍的 %(format)s 格式" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "Google Drive %(fn)s 上找不到 %(format)s" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "找不到 %(format)s:%(fn)s" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 #, fuzzy -msgid "Send to E-Reader" +msgid "Send to eReader" msgstr "發送到Kindle" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +#, fuzzy +msgid "This Email has been sent via Calibre-Web." msgstr "此郵件已經通過Calibre-Web發送。" -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:115 +#, fuzzy +msgid "Calibre-Web Test Email" msgstr "Calibre-Web測試郵件" -#: cps/helper.py:115 -msgid "Test e-mail" +#: cps/helper.py:116 +#, fuzzy +msgid "Test Email" msgstr "測試郵件" -#: cps/helper.py:132 +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "開啟Calibre-Web之旅" -#: cps/helper.py:137 -#, python-format -msgid "Registration e-mail for user: %(name)s" +#: cps/helper.py:138 +#, fuzzy, python-format +msgid "Registration Email for user: %(name)s" msgstr "用戶註冊電子郵件:%(name)s" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, fuzzy, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "轉換 %(orig)s 到 %(format)s 並發送到Kindle" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, fuzzy, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "發送 %(format)s 到Kindle" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, fuzzy, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "%(book)s發送到Kindle" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "無法讀取請求的文件。可能有錯誤的權限設置?" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "刪除書的文件夾%(id)s失敗,路徑有子文件夾:%(path)s" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "刪除書籍 %(id)s失敗:%(message)s" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "僅從數據庫中刪除書籍 %(id)s,數據庫中的書籍路徑無效: %(path)s" -#: cps/helper.py:450 +#: cps/helper.py:447 #, fuzzy, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "將標題從“%(src)s”改為“%(dest)s”時失敗,錯誤錯信息:%(error)s" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "Google Drive上找不到文件 %(file)s" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "將標題從“%(src)s”改為“%(dest)s”時失敗,錯誤錯信息:%(error)s" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "Google Drive上找不到書籍路徑 %(path)s" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" -msgstr "使用此郵箱的賬號已經存在。" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" +msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "此用戶名已被使用" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +#, fuzzy +msgid "Invalid Email address format" msgstr "無效的郵件地址格式" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "下載封面時出錯" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "封面格式出錯" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "創建封面路徑失敗" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "封面文件不是有效的圖片文件,或者無法儲存" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "封面文件只支持jpg/jpeg/png/webp/bmp格式文件" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "僅將jpg、jpeg文件作為封面文件" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "找不到Unrar執行文件" -#: cps/helper.py:947 +#: cps/helper.py:984 #, fuzzy msgid "Error executing UnRar" msgstr "執行UnRar時出錯" -#: cps/helper.py:1040 +#: cps/helper.py:1077 #, fuzzy msgid "Cover" msgstr "發現" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 #, fuzzy msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "請不要使用localhost訪問Calibre-Web,以便Kobo設備能獲取有效的api_endpoint" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "Kobo 設置" @@ -823,9 +840,9 @@ msgstr "Kobo 設置" msgid "Register with %(provider)s" msgstr "使用 %(provider)s 註冊" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "您現在已以“%(nickname)s”身份登入" #: cps/oauth_bb.py:148 @@ -884,12 +901,13 @@ msgstr "Google Oauth 錯誤,請重試。" msgid "Google Oauth error: {}" msgstr "Google Oauth 錯誤: {}" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "{} 星" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "登入" @@ -905,149 +923,158 @@ msgstr "Token已過期" msgid "Success! Please return to your device" msgstr "成功!請返回您的設備" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "書籍" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "顯示最近書籍" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "熱門書籍" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "顯示熱門書籍" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "已下載書籍" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "顯示下載過的書籍" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "最高評分書籍" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "顯示最高評分書籍" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "已讀書籍" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +#, fuzzy +msgid "Show Read and Unread" msgstr "顯示閱讀狀態" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "未讀書籍" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "顯示未讀" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "發現" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "隨機顯示書籍" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "分類" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +#, fuzzy +msgid "Show Category Section" msgstr "顯示分類選擇" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "叢書" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +#, fuzzy +msgid "Show Series Section" msgstr "顯示叢書選擇" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "作者" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +#, fuzzy +msgid "Show Author Section" msgstr "顯示作者選擇" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "出版社" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +#, fuzzy +msgid "Show Publisher Section" msgstr "顯示出版社選擇" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "語言" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +#, fuzzy +msgid "Show Language Section" msgstr "顯示語言選擇" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "評分" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +#, fuzzy +msgid "Show Ratings Section" msgstr "顯示評分選擇" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "文件格式" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +#, fuzzy +msgid "Show File Formats Section" msgstr "顯示文件格式選擇" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "歸檔書籍" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +#, fuzzy +msgid "Show Archived Books" msgstr "顯示歸檔書籍" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "書籍列表" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "顯示書籍列表" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "搜尋" @@ -1070,15 +1097,15 @@ msgid "Rating >= %(rating)s" msgstr "評分 >= %(rating)s" #: cps/search.py:221 -#, python-format -msgid "Read Status = %(status)s" +#, fuzzy, python-format +msgid "Read Status = '%(status)s'" msgstr "閱讀狀態 = %(status)s" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "搜詢自定義欄位時出錯,請重啟 Calibre-Web" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "進階搜尋" @@ -1128,7 +1155,7 @@ msgstr "此書已從書架 %(sname)s 中刪除" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "創建書架" @@ -1154,73 +1181,73 @@ msgstr "書籍已成功刪除" msgid "Change order of Shelf: '%(name)s'" msgstr "修改書架 %(name)s 順序" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 +#: cps/shelf.py:333 #, python-format msgid "Shelf %(title)s created" msgstr "書架 %(title)s 已創建" -#: cps/shelf.py:333 +#: cps/shelf.py:336 #, python-format msgid "Shelf %(title)s changed" msgstr "書架 %(title)s 已修改" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "發生錯誤" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "公共書架:%(title)s已經存在已經存在。" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "私有書架:%(title)s已經存在。" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "書架:%(name)s" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "打開書架出錯。書架不存在或不可訪問" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "任務列表" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "等待中" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "失敗" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "已開始" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "已完成" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "未知狀態" @@ -1253,146 +1280,185 @@ msgstr "有新的更新。單擊下面的按鈕以更新到版本: %(version)s" msgid "No release information available" msgstr "無可用發佈信息" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "發現(隨機書籍)" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "熱門書籍(最多下載)" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "%(user)s 下載過的書籍" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "作者:%(name)s" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "出版社:%(name)s" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "叢書:%(serie)s" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "評分:%(rating)s 星" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "文件格式:%(format)s" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "分類:%(name)s" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "語言:%(name)s" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "下載次數" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "評分列表" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "文件格式列表" -#: cps/web.py:1202 -#, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" -msgstr "書籍已經成功加入 %(kindlemail)s 的發送隊列" +#: cps/web.py:1233 +#, fuzzy +msgid "Please configure the SMTP mail settings first..." +msgstr "請先配置SMTP郵箱設置..." -#: cps/web.py:1206 +#: cps/web.py:1240 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Success! Book queued for sending to %(eReadermail)s" +msgstr "書籍已經成功加入 %(eReadermail)s 的發送隊列" + +#: cps/web.py:1243 +#, python-format +msgid "Oops! There was an error sending book: %(res)s" msgstr "糟糕!發送這本書籍的時候出現錯誤:%(res)s" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +#, fuzzy +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "請先設置您的kindle郵箱。" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" -msgstr "郵件服務未配置,請聯繫網站管理員!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" +msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "註冊" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." +msgstr "郵件服務未配置,請聯繫網站管理員!" + +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "您的電子郵件不允許註冊" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." msgstr "確認郵件已經發送到您的郵箱。" -#: cps/web.py:1278 +#: cps/web.py:1348 cps/web.py:1366 +#, fuzzy msgid "Cannot activate LDAP authentication" msgstr "無法激活LDAP認證" -#: cps/web.py:1297 -#, python-format +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, fuzzy, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "您現在已以“%(nickname)s”身份登入" + +#: cps/web.py:1383 +#, fuzzy, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "備援登入“%(nickname)s”:無法訪問LDAP伺服器,或用戶未知" -#: cps/web.py:1303 -#, python-format +#: cps/web.py:1388 +#, fuzzy, python-format msgid "Could not login: %(message)s" msgstr "無法登入:%(message)s" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 +#, fuzzy msgid "Wrong Username or Password" msgstr "用戶名或密碼錯誤" -#: cps/web.py:1314 +#: cps/web.py:1399 +#, fuzzy msgid "New Password was send to your email address" msgstr "新密碼已發送到您的郵箱" -#: cps/web.py:1320 +#: cps/web.py:1403 +#, fuzzy +msgid "An unknown error occurred. Please try again later." +msgstr "發生一個未知錯誤,請稍後再試。" + +#: cps/web.py:1405 +#, fuzzy msgid "Please enter valid username to reset password" msgstr "請輸入有效的用戶名進行密碼重置" -#: cps/web.py:1327 -#, python-format +#: cps/web.py:1413 +#, fuzzy, python-format msgid "You are now logged in as: '%(nickname)s'" -msgstr "您現在已以“%(nickname)s”登入" +msgstr "您現在已以“%(nickname)s”身份登入" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "%(name)s 的用戶配置" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +#, fuzzy +msgid "Success! Profile Updated" msgstr "資料已更新" +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." +msgstr "使用此郵箱的賬號已經存在。" + #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "找不到包含 OAuth 信息的有效 gmail.json 文件" +#: cps/tasks/convert.py:92 +#, fuzzy, python-format +msgid "%(book)s send to E-Reader" +msgstr "%(book)s發送到Kindle" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1435,35 +1501,35 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 #, fuzzy msgid "Backing up Metadata" msgstr "編輯元數據" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "上傳書籍" @@ -1479,15 +1545,15 @@ msgstr "用戶名" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "郵箱地址" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 #, fuzzy -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "接收書籍的Kindle郵箱地址" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "管理權限" @@ -1497,8 +1563,8 @@ msgstr "管理權限" msgid "Password" msgstr "密碼" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "下載書籍" @@ -1523,16 +1589,12 @@ msgstr "刪除數據" msgid "Public Shelf" msgstr "公共書架" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "添加新用戶" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "導入LDAP用戶" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "SMTP郵件服務器設置" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1553,11 +1615,12 @@ msgstr "SMTP用戶名" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "發信人郵箱" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +#, fuzzy +msgid "Email Service" msgstr "電子郵件服務" #: cps/templates/admin.html:91 @@ -1629,102 +1692,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 +msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" msgstr "" -#: cps/templates/admin.html:199 +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 msgid "Administration" msgstr "管理" -#: cps/templates/admin.html:200 +#: cps/templates/admin.html:204 msgid "Download Debug Package" msgstr "下載除錯包" -#: cps/templates/admin.html:201 +#: cps/templates/admin.html:205 msgid "View Logs" msgstr "查看日誌文件" -#: cps/templates/admin.html:204 -msgid "Reconnect Calibre Database" -msgstr "重新連接到Calibre數據庫" - -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:211 msgid "Restart" msgstr "重啟" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "停止" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "版本" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "詳情" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "當前版本" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "檢查更新" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "執行更新" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "您確定要重啟嗎?" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "確定" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "取消" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "您確定要關閉嗎?" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "正在更新,請不要刷新頁面" @@ -1814,7 +1879,7 @@ msgid "Author" msgstr "作者" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "簡介" @@ -1839,7 +1904,7 @@ msgstr "移除" msgid "Add Identifier" msgstr "添加書號" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "標籤" @@ -1864,23 +1929,23 @@ msgid "Published Date" msgstr "出版日期" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "出版社" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "語言" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "確認" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "沒有" @@ -1897,8 +1962,8 @@ msgid "Fetch Metadata" msgstr "獲取元數據" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1921,8 +1986,8 @@ msgstr "單擊封面將元數據加載到表單" msgid "Loading..." msgstr "加載中..." -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "關閉" @@ -2149,7 +2214,7 @@ msgid "Enable Uploads" msgstr "啟用上傳" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2165,7 +2230,7 @@ msgid "Enable Public Registration" msgstr "啟用註冊" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "使用郵箱或用戶名" #: cps/templates/config_edit.html:132 @@ -2355,6 +2420,52 @@ msgstr "Kepubify 電子書轉換器路徑" msgid "Location of Unrar binary" msgstr "Unrar程序路徑" +#: cps/templates/config_edit.html:361 +#, fuzzy +msgid "Security Settings" +msgstr "OAuth設置" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +#, fuzzy +msgid "User Password policy" +msgstr "重置用戶密碼" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "查看配置" @@ -2367,7 +2478,7 @@ msgstr "隨機書籍顯示數量" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "主頁中書籍作者的最大顯示數量(0=不隱藏)" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "主題" @@ -2458,80 +2569,84 @@ msgstr "添加顯示或隱藏書籍的標籤值" msgid "Add Allowed/Denied custom column values" msgstr "添加顯示或隱藏書籍的自定義欄位值" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "在線閱讀" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "在線聽書" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "%(range)s 第%(index)s冊" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "出版日期" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "標為未讀" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "標為已讀" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "已讀" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "從歸檔檔案還原" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "添加到歸檔" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "歸檔" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "簡介:" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "添加到書架" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "(公共)" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "編輯元數據" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "選擇伺服器類型" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +#, fuzzy +msgid "Standard Email Account" msgstr "使用標準電子郵件賬號" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" -msgstr "使用Gmail賬號" +#, fuzzy +msgid "Gmail Account" +msgstr "選擇伺服器類型" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" -msgstr "設置Gmail賬號作為電子郵件服務" +msgid "Setup Gmail Account" +msgstr "" #: cps/templates/email_edit.html:24 msgid "Revoke Gmail Access" @@ -2554,10 +2669,11 @@ msgid "Attachment Size Limit" msgstr "附件大小限制" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +#, fuzzy +msgid "Save and Send Test Email" msgstr "保存設置並發送測試郵件" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "後退" @@ -2583,13 +2699,13 @@ msgstr "輸入網域名" msgid "Denied Domains (Blacklist)" msgstr "禁止註冊的網域名(黑名單)" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "下一個" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" -msgstr "在文本編輯器中打開.kobo/Kobo eReader.conf,添加(或編輯):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgstr "在文本編輯器中打開.kobo/Kobo/Kobo eReader.conf,添加(或編輯):" #: cps/templates/generate_kobo_auth_url.html:11 #, fuzzy @@ -2600,19 +2716,19 @@ msgstr "Kobo 同步 Token" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "Calibre-Web 實例未配置,請聯繫您的系統管理員!" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "創建問題" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "回到首頁" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "登出賬號" @@ -2642,80 +2758,80 @@ msgstr "按叢書編號排序" msgid "Sort descending according to series index" msgstr "按叢書編號逆排序" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "開始" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "字母排序書籍" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "按字母排序的書籍" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "基於下載數的熱門書籍。" -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "基於評分的熱門書籍。" -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "最近添加的書籍" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "最新書籍" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "隨機書籍" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "書籍按作者排序" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "書籍按出版社排序" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "書籍按分類排序" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "書籍按叢書排序" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "書籍按語言排序" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "書籍按評分排序" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "書籍按文件格式排序" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "書架列表" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "書架上的書" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "首頁" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "切換導航" @@ -2723,48 +2839,48 @@ msgstr "切換導航" msgid "Search Library" msgstr "搜索書庫" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "正在上傳..." - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "錯誤" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "上傳完成,正在處理中,請稍候..." - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "設置" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "賬號" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "登出" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "正在上傳..." + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "錯誤" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "上傳完成,正在處理中,請稍候..." + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "設置" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "請不要刷新頁面" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "瀏覽" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "關於" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "上一個" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "書籍詳情" @@ -2780,7 +2896,7 @@ msgstr "記住我" msgid "Forgot Password?" msgstr "忘記密碼?" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "通過魔法連接登入" @@ -2888,136 +3004,161 @@ msgstr "Caliebre-Web電子書路徑" msgid "epub Reader" msgstr "epub閱讀器" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "淺色" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "深色" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 #, fuzzy msgid "Black" msgstr "後退" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "打開側欄時重排文本。" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "Comic閱讀器" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "快捷鍵" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "上一頁" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "下一頁" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "縮放到最佳" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "按寬度縮放" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "按高度縮放" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "縮放到原始大小" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "向右旋轉" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "向左旋轉" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "翻轉圖片" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +#, fuzzy +msgid "Single Page" +msgstr "管理頁" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "縮放" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "最佳" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "寬度" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "高度" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "原始" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "旋轉" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "翻轉" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "水平" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "垂直" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "方向" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "從左到右" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "從右到左" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" -msgstr "重置為頂部" +msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" -msgstr "記住位置" +msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "工具欄" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "顯示" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "隱藏" @@ -3025,7 +3166,7 @@ msgstr "隱藏" msgid "DJVU Reader" msgstr "DJVU閱讀器" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "PDF閱讀器" @@ -3042,7 +3183,7 @@ msgid "Choose a username" msgstr "選擇一個用戶名" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "您的郵箱地址" #: cps/templates/remote_login.html:5 @@ -3061,10 +3202,6 @@ msgstr "驗證後,您將自動在新設備上登入。" msgid "This verification link will expire in 10 minutes." msgstr "此驗證連接將在10分鐘後失效。" -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3089,43 +3226,51 @@ msgstr "出版日期從" msgid "Published Date To" msgstr "出版日期到" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "排除標籤" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "排除叢書" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "排除書架" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "排除語言" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "擴展名" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "排除擴展名" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "評分大於" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "評分小於" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "從:" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "到:" @@ -3217,10 +3362,6 @@ msgstr "任務進度" msgid "Run Time" msgstr "運行時間" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "開始時間" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3294,17 +3435,18 @@ msgid "Enter Username" msgstr "輸入用戶名" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" -msgstr "輸入郵箱地址" +#, fuzzy +msgid "Enter Email" +msgstr "測試郵件" #: cps/templates/user_table.html:136 #, fuzzy -msgid "Enter E-Reader E-mail Address" -msgstr "輸入Kindle郵箱地址" +msgid "Enter eReader Email" +msgstr "接收書籍的Kindle郵箱地址" #: cps/templates/user_table.html:136 #, fuzzy -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "測試郵件" #: cps/templates/user_table.html:137 @@ -3364,10 +3506,7 @@ msgid "Sync selected Shelves with Kobo" msgstr "同步所選書架到 Kobo" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" +#, fuzzy +msgid "Show Read/Unread Section" msgstr "顯示已讀/未讀選擇" -#: cps/templates/user_table.html:159 -msgid "Show random books" -msgstr "顯示隨機書籍" - diff --git a/cps/ub.py b/cps/ub.py index 5dd7d646..3e478f99 100644 --- a/cps/ub.py +++ b/cps/ub.py @@ -55,6 +55,7 @@ from werkzeug.security import generate_password_hash from . import constants, logger + log = logger.create() session = None @@ -103,7 +104,7 @@ def check_user_session(user_id, session_key): try: return bool(session.query(User_Sessions).filter(User_Sessions.user_id==user_id, User_Sessions.session_key==session_key).one_or_none()) - except (exc.OperationalError, exc.InvalidRequestError): + except (exc.OperationalError, exc.InvalidRequestError) as e: session.rollback() log.exception(e) @@ -492,7 +493,7 @@ class Registration(Base): allow = Column(Integer) def __repr__(self): - return u"".format(self.domain) + return "".format(self.domain) class RemoteAuthToken(Base): @@ -554,8 +555,9 @@ def add_missing_tables(engine, _session): if not engine.dialect.has_table(engine.connect(), "registration"): Registration.__table__.create(bind=engine) with engine.connect() as conn: + trans = conn.begin() conn.execute("insert into registration (domain, allow) values('%.%',1)") - _session.commit() + trans.commit() # migrate all settings missing in registration table @@ -565,16 +567,18 @@ def migrate_registration_table(engine, _session): _session.commit() except exc.OperationalError: # Database is not compatible, some columns are missing with engine.connect() as conn: - conn.execute("ALTER TABLE registration ADD column 'allow' INTEGER") - conn.execute("update registration set 'allow' = 1") - _session.commit() + trans = conn.begin() + conn.execute(text("ALTER TABLE registration ADD column 'allow' INTEGER")) + conn.execute(text("update registration set 'allow' = 1")) + trans.commit() try: # Handle table exists, but no content cnt = _session.query(Registration).count() if not cnt: with engine.connect() as conn: - conn.execute("insert into registration (domain, allow) values('%.%',1)") - _session.commit() + trans = conn.begin() + conn.execute(text("insert into registration (domain, allow) values('%.%',1)")) + trans.commit() except exc.OperationalError: # Database is not writeable print('Settings database is not writeable. Exiting...') sys.exit(2) @@ -597,11 +601,13 @@ def migrate_shelfs(engine, _session): _session.query(exists().where(Shelf.uuid)).scalar() except exc.OperationalError: with engine.connect() as conn: - conn.execute("ALTER TABLE shelf ADD column 'uuid' STRING") - conn.execute("ALTER TABLE shelf ADD column 'created' DATETIME") - conn.execute("ALTER TABLE shelf ADD column 'last_modified' DATETIME") - conn.execute("ALTER TABLE book_shelf_link ADD column 'date_added' DATETIME") - conn.execute("ALTER TABLE shelf ADD column 'kobo_sync' BOOLEAN DEFAULT false") + trans = conn.begin() + conn.execute(text("ALTER TABLE shelf ADD column 'uuid' STRING")) + conn.execute(text("ALTER TABLE shelf ADD column 'created' DATETIME")) + conn.execute(text("ALTER TABLE shelf ADD column 'last_modified' DATETIME")) + conn.execute(text("ALTER TABLE book_shelf_link ADD column 'date_added' DATETIME")) + conn.execute(text("ALTER TABLE shelf ADD column 'kobo_sync' BOOLEAN DEFAULT false")) + trans.commit() for shelf in _session.query(Shelf).all(): shelf.uuid = str(uuid.uuid4()) shelf.created = datetime.datetime.now() @@ -614,16 +620,16 @@ def migrate_shelfs(engine, _session): _session.query(exists().where(Shelf.kobo_sync)).scalar() except exc.OperationalError: with engine.connect() as conn: - - conn.execute("ALTER TABLE shelf ADD column 'kobo_sync' BOOLEAN DEFAULT false") - _session.commit() - + trans = conn.begin() + conn.execute(text("ALTER TABLE shelf ADD column 'kobo_sync' BOOLEAN DEFAULT false")) + trans.commit() try: _session.query(exists().where(BookShelf.order)).scalar() except exc.OperationalError: # Database is not compatible, some columns are missing with engine.connect() as conn: - conn.execute("ALTER TABLE book_shelf_link ADD column 'order' INTEGER DEFAULT 1") - _session.commit() + trans = conn.begin() + conn.execute(text("ALTER TABLE book_shelf_link ADD column 'order' INTEGER DEFAULT 1")) + trans.commit() def migrate_readBook(engine, _session): @@ -631,12 +637,13 @@ def migrate_readBook(engine, _session): _session.query(exists().where(ReadBook.read_status)).scalar() except exc.OperationalError: with engine.connect() as conn: - conn.execute("ALTER TABLE book_read_link ADD column 'read_status' INTEGER DEFAULT 0") - conn.execute("UPDATE book_read_link SET 'read_status' = 1 WHERE is_read") - conn.execute("ALTER TABLE book_read_link ADD column 'last_modified' DATETIME") - conn.execute("ALTER TABLE book_read_link ADD column 'last_time_started_reading' DATETIME") - conn.execute("ALTER TABLE book_read_link ADD column 'times_started_reading' INTEGER DEFAULT 0") - _session.commit() + trans = conn.begin() + conn.execute(text("ALTER TABLE book_read_link ADD column 'read_status' INTEGER DEFAULT 0")) + conn.execute(text("UPDATE book_read_link SET 'read_status' = 1 WHERE is_read")) + conn.execute(text("ALTER TABLE book_read_link ADD column 'last_modified' DATETIME")) + conn.execute(text("ALTER TABLE book_read_link ADD column 'last_time_started_reading' DATETIME")) + conn.execute(text("ALTER TABLE book_read_link ADD column 'times_started_reading' INTEGER DEFAULT 0")) + trans.commit() test = _session.query(ReadBook).filter(ReadBook.last_modified == None).all() for book in test: book.last_modified = datetime.datetime.utcnow() @@ -649,9 +656,10 @@ def migrate_remoteAuthToken(engine, _session): _session.commit() except exc.OperationalError: # Database is not compatible, some columns are missing with engine.connect() as conn: - conn.execute("ALTER TABLE remote_auth_token ADD column 'token_type' INTEGER DEFAULT 0") - conn.execute("update remote_auth_token set 'token_type' = 0") - _session.commit() + trans = conn.begin() + conn.execute(text("ALTER TABLE remote_auth_token ADD column 'token_type' INTEGER DEFAULT 0")) + conn.execute(text("update remote_auth_token set 'token_type' = 0")) + trans.commit() # Migrate database to current version, has to be updated after every database change. Currently migration from # everywhere to current should work. Migration is done by checking if relevant columns are existing, and than adding @@ -668,52 +676,58 @@ def migrate_Database(_session): _session.query(exists().where(User.sidebar_view)).scalar() except exc.OperationalError: # Database is not compatible, some columns are missing with engine.connect() as conn: - conn.execute("ALTER TABLE user ADD column `sidebar_view` Integer DEFAULT 1") - _session.commit() + trans = conn.begin() + conn.execute(text("ALTER TABLE user ADD column `sidebar_view` Integer DEFAULT 1")) + trans.commit() create = True try: if create: with engine.connect() as conn: - conn.execute("SELECT language_books FROM user") - _session.commit() + trans = conn.begin() + conn.execute(text("SELECT language_books FROM user")) + trans.commit() except exc.OperationalError: with engine.connect() as conn: - conn.execute("UPDATE user SET 'sidebar_view' = (random_books* :side_random + language_books * :side_lang " + trans = conn.begin() + conn.execute(text("UPDATE user SET 'sidebar_view' = (random_books* :side_random + language_books * :side_lang " "+ series_books * :side_series + category_books * :side_category + hot_books * " - ":side_hot + :side_autor + :detail_random)", + ":side_hot + :side_autor + :detail_random)"), {'side_random': constants.SIDEBAR_RANDOM, 'side_lang': constants.SIDEBAR_LANGUAGE, 'side_series': constants.SIDEBAR_SERIES, 'side_category': constants.SIDEBAR_CATEGORY, 'side_hot': constants.SIDEBAR_HOT, 'side_autor': constants.SIDEBAR_AUTHOR, 'detail_random': constants.DETAIL_RANDOM}) - _session.commit() + trans.commit() try: _session.query(exists().where(User.denied_tags)).scalar() except exc.OperationalError: # Database is not compatible, some columns are missing with engine.connect() as conn: - conn.execute("ALTER TABLE user ADD column `denied_tags` String DEFAULT ''") - conn.execute("ALTER TABLE user ADD column `allowed_tags` String DEFAULT ''") - conn.execute("ALTER TABLE user ADD column `denied_column_value` String DEFAULT ''") - conn.execute("ALTER TABLE user ADD column `allowed_column_value` String DEFAULT ''") - _session.commit() + trans = conn.begin() + conn.execute(text("ALTER TABLE user ADD column `denied_tags` String DEFAULT ''")) + conn.execute(text("ALTER TABLE user ADD column `allowed_tags` String DEFAULT ''")) + conn.execute(text("ALTER TABLE user ADD column `denied_column_value` String DEFAULT ''")) + conn.execute(text("ALTER TABLE user ADD column `allowed_column_value` String DEFAULT ''")) + trans.commit() try: _session.query(exists().where(User.view_settings)).scalar() except exc.OperationalError: with engine.connect() as conn: - conn.execute("ALTER TABLE user ADD column `view_settings` VARCHAR(10) DEFAULT '{}'") - _session.commit() + trans = conn.begin() + conn.execute(text("ALTER TABLE user ADD column `view_settings` VARCHAR(10) DEFAULT '{}'")) + trans.commit() try: _session.query(exists().where(User.kobo_only_shelves_sync)).scalar() except exc.OperationalError: with engine.connect() as conn: - conn.execute("ALTER TABLE user ADD column `kobo_only_shelves_sync` SMALLINT DEFAULT 0") - _session.commit() - + trans = conn.begin() + conn.execute(text("ALTER TABLE user ADD column `kobo_only_shelves_sync` SMALLINT DEFAULT 0")) + trans.commit() try: # check if name is in User table instead of nickname _session.query(exists().where(User.name)).scalar() except exc.OperationalError: # Create new table user_id and copy contents of table user into it with engine.connect() as conn: + trans = conn.begin() conn.execute(text("CREATE TABLE user_id (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," "name VARCHAR(64)," "email VARCHAR(120)," @@ -740,7 +754,7 @@ def migrate_Database(_session): # delete old user table and rename new user_id table to user: conn.execute(text("DROP TABLE user")) conn.execute(text("ALTER TABLE user_id RENAME TO user")) - _session.commit() + trans.commit() if _session.query(User).filter(User.role.op('&')(constants.ROLE_ANONYMOUS) == constants.ROLE_ANONYMOUS).first() \ is None: create_anonymous_user(_session) @@ -810,20 +824,20 @@ def create_admin_user(_session): def init_db_thread(): global app_DB_path - engine = create_engine(u'sqlite:///{0}'.format(app_DB_path), echo=False) + engine = create_engine('sqlite:///{0}'.format(app_DB_path), echo=False) Session = scoped_session(sessionmaker()) Session.configure(bind=engine) return Session() -def init_db(app_db_path, user_credentials=None): +def init_db(app_db_path): # Open session for database connection global session global app_DB_path app_DB_path = app_db_path - engine = create_engine(u'sqlite:///{0}'.format(app_db_path), echo=False) + engine = create_engine('sqlite:///{0}'.format(app_db_path), echo=False) Session = scoped_session(sessionmaker()) Session.configure(bind=engine) @@ -838,6 +852,7 @@ def init_db(app_db_path, user_credentials=None): create_admin_user(session) create_anonymous_user(session) +def password_change(user_credentials=None): if user_credentials: username, password = user_credentials.split(':', 1) user = session.query(User).filter(func.lower(User.name) == username.lower()).first() @@ -845,7 +860,12 @@ def init_db(app_db_path, user_credentials=None): if not password: print("Empty password is not allowed") sys.exit(4) - user.password = generate_password_hash(password) + try: + from .helper import valid_password + user.password = generate_password_hash(valid_password(password)) + except Exception: + print("Password doesn't comply with password validation rules") + sys.exit(4) if session_commit() == "": print("Password for user '{}' changed".format(username)) sys.exit(0) @@ -858,7 +878,7 @@ def init_db(app_db_path, user_credentials=None): def get_new_session_instance(): - new_engine = create_engine(u'sqlite:///{0}'.format(app_DB_path), echo=False) + new_engine = create_engine('sqlite:///{0}'.format(app_DB_path), echo=False) new_session = scoped_session(sessionmaker()) new_session.configure(bind=new_engine) diff --git a/cps/updater.py b/cps/updater.py index 13d774bf..6d6e408f 100644 --- a/cps/updater.py +++ b/cps/updater.py @@ -75,29 +75,29 @@ class Updater(threading.Thread): def do_work(self): try: self.status = 1 - log.debug(u'Download update file') + log.debug('Download update file') headers = {'Accept': 'application/vnd.github.v3+json'} r = requests.get(self._get_request_path(), stream=True, headers=headers, timeout=(10, 600)) r.raise_for_status() self.status = 2 - log.debug(u'Opening zipfile') + log.debug('Opening zipfile') z = zipfile.ZipFile(BytesIO(r.content)) self.status = 3 - log.debug(u'Extracting zipfile') + log.debug('Extracting zipfile') tmp_dir = gettempdir() z.extractall(tmp_dir) folder_name = os.path.join(tmp_dir, z.namelist()[0])[:-1] if not os.path.isdir(folder_name): self.status = 11 - log.info(u'Extracted contents of zipfile not found in temp folder') + log.info('Extracted contents of zipfile not found in temp folder') self.pause() return False self.status = 4 - log.debug(u'Replacing files') + log.debug('Replacing files') if self.update_source(folder_name, constants.BASE_DIR): self.status = 6 - log.debug(u'Preparing restart of server') + log.debug('Preparing restart of server') time.sleep(2) self.web_server.stop(True) self.status = 7 @@ -107,20 +107,20 @@ class Updater(threading.Thread): self.status = 13 except requests.exceptions.HTTPError as ex: - log.error(u'HTTP Error %s', ex) + log.error('HTTP Error %s', ex) self.status = 8 except requests.exceptions.ConnectionError: - log.error(u'Connection error') + log.error('Connection error') self.status = 9 except requests.exceptions.Timeout: - log.error(u'Timeout while establishing connection') + log.error('Timeout while establishing connection') self.status = 10 except (requests.exceptions.RequestException, zipfile.BadZipFile): self.status = 11 - log.error(u'General error') + log.error('General error') except (IOError, OSError) as ex: self.status = 12 - log.error(u'Possible Reason for error: update file could not be saved in temp dir') + log.error('Possible Reason for error: update file could not be saved in temp dir') log.error_or_exception(ex) self.pause() return False @@ -327,7 +327,7 @@ class Updater(threading.Thread): @classmethod def _stable_version_info(cls): log.debug("Stable version: {}".format(constants.STABLE_VERSION)) - return constants.STABLE_VERSION # Current version + return constants.STABLE_VERSION # Current Version @classmethod def dry_run(cls): @@ -386,13 +386,13 @@ class Updater(threading.Thread): r.raise_for_status() update_data = r.json() except requests.exceptions.HTTPError as e: - status['message'] = _(u'HTTP Error') + ' ' + str(e) + status['message'] = _('HTTP Error') + ' ' + str(e) except requests.exceptions.ConnectionError: - status['message'] = _(u'Connection error') + status['message'] = _('Connection error') except requests.exceptions.Timeout: - status['message'] = _(u'Timeout while establishing connection') + status['message'] = _('Timeout while establishing connection') except (requests.exceptions.RequestException, ValueError): - status['message'] = _(u'General error') + status['message'] = _('General error') return status, update_data @staticmethod @@ -401,7 +401,7 @@ class Updater(threading.Thread): os.sep + 'app.db', os.sep + 'calibre-web.log1', os.sep + 'calibre-web.log2', os.sep + 'gdrive.db', os.sep + 'vendor', os.sep + 'calibre-web.log', os.sep + '.git', os.sep + 'client_secrets.json', os.sep + 'gdrive_credentials', os.sep + 'settings.yaml', os.sep + 'venv', os.sep + 'virtualenv', - os.sep + 'access.log', os.sep + 'access.log1', os.sep + 'access.log2', + os.sep + 'access.log', os.sep + 'access.log1', os.sep + 'access.log2', os.sep + '.key', os.sep + '.calibre-web.log.swp', os.sep + '_sqlite3.so', os.sep + 'cps' + os.sep + '.HOMEDIR', os.sep + 'gmail.json', os.sep + 'exclude.txt', os.sep + 'cps' + os.sep + 'cache' ] @@ -428,18 +428,18 @@ class Updater(threading.Thread): if status['message'] != '': return json.dumps(status) if 'object' not in commit or 'url' not in commit['object']: - status['message'] = _(u'Unexpected data while reading update information') + status['message'] = _('Unexpected data while reading update information') return json.dumps(status) try: if commit['object']['sha'] == status['current_commit_hash']: status.update({ 'update': False, 'success': True, - 'message': _(u'No update available. You already have the latest version installed') + 'message': _('No update available. You already have the latest version installed') }) return json.dumps(status) except (TypeError, KeyError): - status['message'] = _(u'Unexpected data while reading update information') + status['message'] = _('Unexpected data while reading update information') return json.dumps(status) # a new update is available @@ -454,7 +454,7 @@ class Updater(threading.Thread): log.debug("A new update is available.") status['success'] = True status['message'] = _( - u'A new update is available. Click on the button below to update to the latest version.') + 'A new update is available. Click on the button below to update to the latest version.') new_commit_date = datetime.datetime.strptime( update_data['committer']['date'], '%Y-%m-%dT%H:%M:%SZ') - tz @@ -471,7 +471,7 @@ class Updater(threading.Thread): status['history'] = parents[::-1] except (IndexError, KeyError): status['success'] = False - status['message'] = _(u'Could not fetch update information') + status['message'] = _('Could not fetch update information') log.error("Could not fetch update information") return json.dumps(status) return '' @@ -482,7 +482,7 @@ class Updater(threading.Thread): 'update': True, 'success': True, 'message': _( - u'Click on the button below to update to the latest stable version.'), + 'Click on the button below to update to the latest stable version.'), 'history': parents }) self.updateFile = commit[0]['zipball_url'] @@ -490,8 +490,8 @@ class Updater(threading.Thread): status.update({ 'update': True, 'success': True, - 'message': _(u'A new update is available. Click on the button below to ' - u'update to version: %(version)s', version=commit[0]['tag_name']), + 'message': _('A new update is available. Click on the button below to ' + 'update to version: %(version)s', version=commit[0]['tag_name']), 'history': parents }) self.updateFile = commit[0]['zipball_url'] diff --git a/cps/uploader.py b/cps/uploader.py index ecf4868c..23dfc4a6 100644 --- a/cps/uploader.py +++ b/cps/uploader.py @@ -37,16 +37,22 @@ except (ImportError, RuntimeError) as e: use_generic_pdf_cover = True try: - from PyPDF2 import PdfFileReader + from pypdf import PdfReader use_pdf_meta = True except ImportError as ex: - log.debug('PyPDF2 is recommended for best performance in metadata extracting from pdf files: %s', ex) + log.debug('PyPDF is recommended for best performance in metadata extracting from pdf files: %s', ex) try: - from PyPDF3 import PdfFileReader + from PyPDF2 import PdfReader use_pdf_meta = True - except ImportError as e: - log.debug('Cannot import PyPDF3/PyPDF2, extracting pdf metadata will not work: %s / %s', e) - use_pdf_meta = False + except ImportError as ex: + log.debug('PyPDF is recommended for best performance in metadata extracting from pdf files: %s', ex) + log.debug('PyPdf2 is also possible for metadata extracting from pdf files, but not recommended anymore') + try: + from PyPDF3 import PdfFileReader as PdfReader + use_pdf_meta = True + except ImportError as e: + log.debug('Cannot import PyPDF3/PyPDF2, extracting pdf metadata will not work: %s / %s', e) + use_pdf_meta = False try: from . import epub @@ -63,8 +69,8 @@ except ImportError as e: use_fb2_meta = False -def process(tmp_file_path, original_file_name, original_file_extension, rarExecutable): - meta = None +def process(tmp_file_path, original_file_name, original_file_extension, rar_executable): + meta = default_meta(tmp_file_path, original_file_name, original_file_extension) extension_upper = original_file_extension.upper() try: if ".PDF" == extension_upper: @@ -73,19 +79,19 @@ def process(tmp_file_path, original_file_name, original_file_extension, rarExecu meta = epub.get_epub_info(tmp_file_path, original_file_name, original_file_extension) elif ".FB2" == extension_upper and use_fb2_meta is True: meta = fb2.get_fb2_info(tmp_file_path, original_file_extension) - elif extension_upper in ['.CBZ', '.CBT', '.CBR']: + elif extension_upper in ['.CBZ', '.CBT', '.CBR', ".CB7"]: meta = comic.get_comic_info(tmp_file_path, original_file_name, original_file_extension, - rarExecutable) + rar_executable) except Exception as ex: log.warning('cannot parse metadata, using default: %s', ex) - if meta and meta.title.strip() and meta.author.strip(): - if meta.author.lower() == 'unknown': - meta = meta._replace(author=_(u'Unknown')) - return meta - return default_meta(tmp_file_path, original_file_name, original_file_extension) + if not meta.title.strip(): + meta = meta._replace(title=original_file_name) + if not meta.author.strip() or meta.author.lower() == 'unknown': + meta = meta._replace(author=_('Unknown')) + return meta def default_meta(tmp_file_path, original_file_name, original_file_extension): @@ -93,7 +99,7 @@ def default_meta(tmp_file_path, original_file_name, original_file_extension): file_path=tmp_file_path, extension=original_file_extension, title=original_file_name, - author=_(u'Unknown'), + author=_('Unknown'), cover=None, description="", tags="", @@ -111,7 +117,7 @@ def parse_xmp(pdf_file): Parse XMP Metadata and prepare for BookMeta object """ try: - xmp_info = pdf_file.getXmpMetadata() + xmp_info = pdf_file.xmp_metadata except Exception as ex: log.debug('Can not read PDF XMP metadata {}'.format(ex)) return None @@ -157,10 +163,9 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): if use_pdf_meta: with open(tmp_file_path, 'rb') as f: - pdf_file = PdfFileReader(f) - doc_info = pdf_file.getDocumentInfo() + pdf_file = PdfReader(f) try: - doc_info = pdf_file.getDocumentInfo() + doc_info = pdf_file.metadata except Exception as exc: log.debug('Can not read PDF DocumentInfo {}'.format(exc)) xmp_info = parse_xmp(pdf_file) @@ -173,7 +178,7 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): languages = xmp_info['languages'] publisher = xmp_info['publisher'] else: - author = u'Unknown' + author = 'Unknown' title = '' languages = [""] publisher = "" @@ -182,7 +187,7 @@ def pdf_meta(tmp_file_path, original_file_name, original_file_extension): if doc_info: if author == '': - author = ' & '.join(split_authors([doc_info.author])) if doc_info.author else u'Unknown' + author = ' & '.join(split_authors([doc_info.author])) if doc_info.author else 'Unknown' if title == '': title = doc_info.title if doc_info.title else original_file_name if subject == '': @@ -239,11 +244,11 @@ def get_magick_version(): if not use_generic_pdf_cover: ret['Image Magick'] = ImageVersion.MAGICK_VERSION else: - ret['Image Magick'] = u'not installed' + ret['Image Magick'] = 'not installed' return ret -def upload(uploadfile, rarExcecutable): +def upload(uploadfile, rar_excecutable): tmp_dir = os.path.join(gettempdir(), 'calibre_web') if not os.path.isdir(tmp_dir): @@ -255,4 +260,4 @@ def upload(uploadfile, rarExcecutable): tmp_file_path = os.path.join(tmp_dir, md5) log.debug("Temporary file: %s", tmp_file_path) uploadfile.save(tmp_file_path) - return process(tmp_file_path, filename_root, file_extension, rarExcecutable) + return process(tmp_file_path, filename_root, file_extension, rar_excecutable) diff --git a/cps/usermanagement.py b/cps/usermanagement.py index 62fe6f77..d8f64012 100644 --- a/cps/usermanagement.py +++ b/cps/usermanagement.py @@ -16,16 +16,16 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import base64 -import binascii from functools import wraps from sqlalchemy.sql.expression import func from werkzeug.security import check_password_hash from flask_login import login_required, login_user +from flask import request, Response -from . import lm, ub, config, constants, services +from . import lm, ub, config, constants, services, logger, limiter +log = logger.create() def login_required_if_no_ano(func): @wraps(func) @@ -36,6 +36,54 @@ def login_required_if_no_ano(func): return decorated_view +def requires_basic_auth_if_no_ano(f): + @wraps(f) + def decorated(*args, **kwargs): + auth = request.authorization + if not auth or auth.type != 'basic': + if config.config_anonbrowse != 1: + user = load_user_from_reverse_proxy_header(request) + if user: + return f(*args, **kwargs) + return _authenticate() + else: + return f(*args, **kwargs) + if config.config_login_type == constants.LOGIN_LDAP and services.ldap: + login_result, error = services.ldap.bind_user(auth.username, auth.password) + if login_result: + user = _fetch_user_by_name(auth.username) + [limiter.limiter.storage.clear(k.key) for k in limiter.current_limits] + login_user(user) + return f(*args, **kwargs) + elif login_result is not None: + log.error(error) + return _authenticate() + user = _load_user_from_auth_header(auth.username, auth.password) + if not user: + return _authenticate() + return f(*args, **kwargs) + return decorated + + +def _load_user_from_auth_header(username, password): + limiter.check() + user = _fetch_user_by_name(username) + if bool(user and check_password_hash(str(user.password), password)) and user.name != "Guest": + [limiter.limiter.storage.clear(k.key) for k in limiter.current_limits] + login_user(user) + return user + else: + ip_address = request.headers.get('X-Forwarded-For', request.remote_addr) + log.warning('OPDS Login failed for user "%s" IP-address: %s', username, ip_address) + return None + + +def _authenticate(): + return Response( + 'Could not verify your access level for that URL.\n' + 'You have to login with proper credentials', 401, + {'WWW-Authenticate': 'Basic realm="Login Required"'}) + def _fetch_user_by_name(username): return ub.session.query(ub.User).filter(func.lower(ub.User.name) == username.lower()).first() @@ -43,45 +91,21 @@ def _fetch_user_by_name(username): @lm.user_loader def load_user(user_id): - return ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first() + user = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first() + return user @lm.request_loader -def load_user_from_request(request): +def load_user_from_reverse_proxy_header(req): if config.config_allow_reverse_proxy_header_login: rp_header_name = config.config_reverse_proxy_login_header_name if rp_header_name: - rp_header_username = request.headers.get(rp_header_name) + rp_header_username = req.headers.get(rp_header_name) if rp_header_username: user = _fetch_user_by_name(rp_header_username) if user: + [limiter.limiter.storage.clear(k.key) for k in limiter.current_limits] login_user(user) return user + return None - auth_header = request.headers.get("Authorization") - if auth_header: - user = load_user_from_auth_header(auth_header) - if user: - return user - - return - - -def load_user_from_auth_header(header_val): - if header_val.startswith('Basic '): - header_val = header_val.replace('Basic ', '', 1) - basic_username = basic_password = '' # nosec - try: - header_val = base64.b64decode(header_val).decode('utf-8') - # Users with colon are invalid: rfc7617 page 4 - basic_username = header_val.split(':', 1)[0] - basic_password = header_val.split(':', 1)[1] - except (TypeError, UnicodeDecodeError, binascii.Error): - pass - user = _fetch_user_by_name(basic_username) - if user and config.config_login_type == constants.LOGIN_LDAP and services.ldap: - if services.ldap.bind_user(str(user.password), basic_password): - return user - if user and check_password_hash(str(user.password), basic_password): - return user - return diff --git a/cps/web.py b/cps/web.py index 4f83f98a..4558b8d9 100755 --- a/cps/web.py +++ b/cps/web.py @@ -25,11 +25,13 @@ import chardet # dependency of requests import copy 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, Response from flask import session as flask_session from flask_babel import gettext as _ from flask_babel import get_locale from flask_login import login_user, logout_user, login_required, current_user +from flask_limiter import RateLimitExceeded +from flask_limiter.util import get_remote_address from sqlalchemy.exc import IntegrityError, InvalidRequestError, OperationalError from sqlalchemy.sql.expression import text, func, false, not_, and_, or_ from sqlalchemy.orm.attributes import flag_modified @@ -47,7 +49,7 @@ from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download from .helper import check_valid_domain, check_email, check_username, \ get_book_cover, get_series_cover_thumbnail, get_download_link, send_mail, generate_random_password, \ send_registration_mail, check_send_to_ereader, check_read_formats, tags_filters, reset_password, valid_email, \ - edit_book_read_status + edit_book_read_status, valid_password from .pagination import Pagination from .redirect import redirect_back from .babel import get_available_locale @@ -55,6 +57,10 @@ from .usermanagement import login_required_if_no_ano from .kobo_sync_status import remove_synced_book from .render_template import render_title_template from .kobo_sync_status import change_archived_books +from . import limiter +from .services.worker import WorkerThread +from .tasks_status import render_task_status + feature_support = { 'ldap': bool(services.ldap), @@ -83,15 +89,18 @@ except ImportError: def add_security_headers(resp): csp = "default-src 'self'" csp += ''.join([' ' + host for host in config.config_trustedhosts.strip().split(',')]) - csp += " 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self' " + csp += " 'unsafe-inline' 'unsafe-eval'; font-src 'self' data:; img-src 'self'" if request.path.startswith("/author/") and config.config_use_goodreads: - csp += "images.gr-assets.com i.gr-assets.com s.gr-assets.com" + csp += " images.gr-assets.com i.gr-assets.com s.gr-assets.com" csp += " data:" - resp.headers['Content-Security-Policy'] = csp if request.endpoint == "edit-book.show_edit_book" or config.config_use_google_drive: - resp.headers['Content-Security-Policy'] += " *" + csp += " *;" elif request.endpoint == "web.read_book": - resp.headers['Content-Security-Policy'] += " blob:;style-src-elem 'self' blob: 'unsafe-inline';" + csp += " blob:; style-src-elem 'self' blob: 'unsafe-inline';" + else: + csp += ";" + csp += " object-src 'none';" + resp.headers['Content-Security-Policy'] = csp resp.headers['X-Content-Type-Options'] = 'nosniff' resp.headers['X-Frame-Options'] = 'SAMEORIGIN' resp.headers['X-XSS-Protection'] = '1; mode=block' @@ -388,7 +397,7 @@ def render_books_list(data, sort_param, book_id, page): elif data == "archived": return render_archived_books(page, order) elif data == "search": - term = (request.args.get('query') or '') + term = request.args.get('query', None) offset = int(int(config.config_books_per_page) * (page - 1)) return render_search_results(term, offset, order, config.config_books_per_page) elif data == "advsearch": @@ -403,7 +412,7 @@ def render_books_list(data, sort_param, book_id, page): db.Books.id == db.books_series_link.c.book, db.Series) return render_title_template('index.html', random=random, entries=entries, pagination=pagination, - title=_(u"Books"), page=website, order=order[1]) + title=_("Books"), page=website, order=order[1]) def render_rated_books(page, book_id, order): @@ -418,7 +427,7 @@ def render_rated_books(page, book_id, order): db.Series) return render_title_template('index.html', random=random, entries=entries, pagination=pagination, - id=book_id, title=_(u"Top Rated Books"), page="rated", order=order[1]) + id=book_id, title=_("Top Rated Books"), page="rated", order=order[1]) else: abort(404) @@ -430,7 +439,7 @@ def render_discover_books(book_id): config_read_column=config.config_read_column) pagination = Pagination(1, config.config_books_per_page, config.config_books_per_page) return render_title_template('index.html', random=false(), entries=entries, pagination=pagination, id=book_id, - title=_(u"Discover (Random Books)"), page="discover") + title=_("Discover (Random Books)"), page="discover") else: abort(404) @@ -466,7 +475,7 @@ def render_hot_books(page, order): num_books = entries.__len__() pagination = Pagination(page, config.config_books_per_page, num_books) return render_title_template('index.html', random=random, entries=entries, pagination=pagination, - title=_(u"Hot Books (Most Downloaded)"), page="hot", order=order[1]) + title=_("Hot Books (Most Downloaded)"), page="hot", order=order[1]) else: abort(404) @@ -476,7 +485,8 @@ def render_downloaded_books(page, order, user_id): user_id = int(user_id) else: user_id = current_user.id - if current_user.check_visibility(constants.SIDEBAR_DOWNLOAD): + user = ub.session.query(ub.User).filter(ub.User.id == user_id).first() + if current_user.check_visibility(constants.SIDEBAR_DOWNLOAD) and user: entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, @@ -491,13 +501,12 @@ def render_downloaded_books(page, order, user_id): if not (calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) .filter(db.Books.id == book.Books.id).first()): ub.delete_download(book.Books.id) - user = ub.session.query(ub.User).filter(ub.User.id == user_id).first() return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=user_id, - title=_(u"Downloaded books by %(user)s", user=user.name), + title=_("Downloaded books by %(user)s", user=user.name), page="download", order=order[1]) else: @@ -514,7 +523,7 @@ def render_author_books(page, author_id, order): db.books_series_link.c.book == db.Books.id, db.Series) if entries is None or not len(entries): - flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), + flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), category="error") return redirect(url_for("web.index")) if constants.sqlalchemy_version2: @@ -530,7 +539,7 @@ def render_author_books(page, author_id, order): book_entries = [entry.Books for entry in entries] other_books = services.goodreads_support.get_other_books(author_info, book_entries) return render_title_template('author.html', entries=entries, pagination=pagination, id=author_id, - title=_(u"Author: %(name)s", name=author_name), author=author_info, + title=_("Author: %(name)s", name=author_name), author=author_info, other_books=other_books, page="author", order=order[1]) @@ -566,7 +575,7 @@ def render_publisher_books(page, book_id, order): abort(404) return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id, - title=_(u"Publisher: %(name)s", name=publisher), + title=_("Publisher: %(name)s", name=publisher), page="publisher", order=order[1]) @@ -594,7 +603,7 @@ def render_series_books(page, book_id, order): else: abort(404) return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, - title=_(u"Series: %(serie)s", serie=series_name), page="series", order=order[1]) + title=_("Series: %(serie)s", serie=series_name), page="series", order=order[1]) def render_ratings_books(page, book_id, order): @@ -609,22 +618,20 @@ def render_ratings_books(page, book_id, order): db.Books.id == db.books_series_link.c.book, db.Series, db.books_ratings_link, db.Ratings) - title = _(u"Rating: None") - rating = -1 + title = _("Rating: None") else: name = calibre_db.session.query(db.Ratings).filter(db.Ratings.id == book_id).first() - entries, random, pagination = calibre_db.fill_indexpage(page, 0, - db.Books, - db.Books.ratings.any(db.Ratings.id == book_id), - [order[0][0]], - True, config.config_read_column) - title = _(u"Rating: %(rating)s stars", rating=int(name.rating / 2)) - rating = name.rating - if title and rating <= 10: - return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, - title=title, page="ratings", order=order[1]) - else: - abort(404) + if name: + entries, random, pagination = calibre_db.fill_indexpage(page, 0, + db.Books, + db.Books.ratings.any(db.Ratings.id == book_id), + [order[0][0]], + True, config.config_read_column) + title = _("Rating: %(rating)s stars", rating=int(name.rating / 2)) + else: + abort(404) + return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, + title=title, page="ratings", order=order[1]) def render_formats_books(page, book_id, order): @@ -636,7 +643,7 @@ def render_formats_books(page, book_id, order): [order[0][0]], True, config.config_read_column) return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id, - title=_(u"File format: %(format)s", format=name.format), + title=_("File format: %(format)s", format=name.format), page="formats", order=order[1]) else: @@ -673,13 +680,15 @@ def render_category_books(page, book_id, order): else: abort(404) return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id, - title=_(u"Category: %(name)s", name=tagsname), page="category", order=order[1]) + title=_("Category: %(name)s", name=tagsname), page="category", order=order[1]) def render_language_books(page, name, order): try: if name.lower() != "none": lang_name = isoLanguages.get_language_name(get_locale(), name) + if lang_name == "Unknown": + abort(404) else: lang_name = _("None") except KeyError: @@ -700,7 +709,7 @@ def render_language_books(page, name, order): [order[0][0]], True, config.config_read_column) return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=name, - title=_(u"Language: %(name)s", name=lang_name), page="language", order=order[1]) + title=_("Language: %(name)s", name=lang_name), page="language", order=order[1]) def render_read_books(page, are_read, as_xml=False, order=None): @@ -739,10 +748,10 @@ def render_read_books(page, are_read, as_xml=False, order=None): return entries, pagination else: if are_read: - name = _(u'Read Books') + ' (' + str(pagination.total_count) + ')' + name = _('Read Books') + ' (' + str(pagination.total_count) + ')' page_name = "read" else: - name = _(u'Unread Books') + ' (' + str(pagination.total_count) + ')' + name = _('Unread Books') + ' (' + str(pagination.total_count) + ')' page_name = "unread" return render_title_template('index.html', random=random, entries=entries, pagination=pagination, title=name, page=page_name, order=order[1]) @@ -765,7 +774,7 @@ def render_archived_books(page, sort_param): True, True, config.config_read_column) - name = _(u'Archived Books') + ' (' + str(len(archived_book_ids)) + ')' + name = _('Archived Books') + ' (' + str(len(archived_book_ids)) + ')' page_name = "archived" return render_title_template('index.html', random=random, entries=entries, pagination=pagination, title=name, page=page_name, order=sort_param[1]) @@ -796,7 +805,7 @@ def books_list(data, sort_param, book_id, page): def books_table(): visibility = current_user.view_settings.get('table', {}) cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True) - return render_title_template('book_table.html', title=_(u"Books List"), cc=cc, page="book_table", + return render_title_template('book_table.html', title=_("Books List"), cc=cc, page="book_table", visiblility=visibility) @@ -917,7 +926,7 @@ def author_list(): for entry in author_copy: entry.Authors.name = entry.Authors.name.replace('|', ',') return render_title_template('list.html', entries=author_copy, folder='web.books_list', charlist=char_list, - title=u"Authors", page="authorlist", data='author', order=order_no) + title="Authors", page="authorlist", data='author', order=order_no) else: abort(404) @@ -938,7 +947,7 @@ def download_list(): .filter(ub.User.role.op('&')(constants.ROLE_ANONYMOUS) != constants.ROLE_ANONYMOUS) \ .group_by(func.upper(func.substr(ub.User.name, 1, 1))).all() return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=char_list, - title=_(u"Downloads"), page="downloadlist", data="download", order=order_no) + title=_("Downloads"), page="downloadlist", data="download", order=order_no) else: abort(404) @@ -966,7 +975,7 @@ def publisher_list(): entries = sorted(entries, key=lambda x: x[0].name.lower(), reverse=not order_no) char_list = generate_char_list(entries) 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=_("Publishers"), page="publisherlist", data="publisher", order=order_no) else: abort(404) @@ -994,15 +1003,23 @@ def series_list(): if no_series_count: entries.append([db.Category(_("None"), "-1"), no_series_count]) 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, - title=_(u"Series"), page="serieslist", data="series", order=order_no) + return render_title_template('list.html', + entries=entries, + folder='web.books_list', + charlist=char_list, + title=_("Series"), + page="serieslist", + data="series", order=order_no) else: - entries = calibre_db.session.query(db.Books, func.count('books_series_link').label('count'), - func.max(db.Books.series_index), db.Books.id) \ - .join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters()) \ - .group_by(text('books_series_link.series')).order_by(order).all() + entries = (calibre_db.session.query(db.Books, func.count('books_series_link').label('count'), + func.max(db.Books.series_index), db.Books.id) + .join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters()) + .group_by(text('books_series_link.series')) + .having(or_(func.max(db.Books.series_index), db.Books.series_index=="")) + .order_by(order) + .all()) return render_title_template('grid.html', entries=entries, folder='web.books_list', charlist=char_list, - title=_(u"Series"), page="serieslist", data="series", bodyClass="grid-view", + title=_("Series"), page="serieslist", data="series", bodyClass="grid-view", order=order_no) else: abort(404) @@ -1028,10 +1045,11 @@ def ratings_list(): .filter(or_(db.Ratings.rating == None, db.Ratings.rating == 0)) .filter(calibre_db.common_filters()) .count()) - entries.append([db.Category(_("None"), "-1", -1), no_rating_count]) + if no_rating_count: + entries.append([db.Category(_("None"), "-1", -1), no_rating_count]) entries = sorted(entries, key=lambda x: x[0].rating, reverse=not order_no) return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=list(), - title=_(u"Ratings list"), page="ratingslist", data="ratings", order=order_no) + title=_("Ratings list"), page="ratingslist", data="ratings", order=order_no) else: abort(404) @@ -1058,7 +1076,7 @@ def formats_list(): if no_format_count: entries.append([db.Category(_("None"), "-1"), no_format_count]) return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=list(), - title=_(u"File formats list"), page="formatslist", data="formats", order=order_no) + title=_("File formats list"), page="formatslist", data="formats", order=order_no) else: abort(404) @@ -1066,12 +1084,12 @@ def formats_list(): @web.route("/language") @login_required_if_no_ano def language_overview(): - if current_user.check_visibility(constants.SIDEBAR_LANGUAGE) and current_user.filter_language() == u"all": + if current_user.check_visibility(constants.SIDEBAR_LANGUAGE) and current_user.filter_language() == "all": order_no = 0 if current_user.get_view_property('language', 'dir') == 'desc' else 1 languages = calibre_db.speaking_language(reverse_order=not order_no, with_count=True) char_list = generate_char_list(languages) return render_title_template('list.html', entries=languages, folder='web.books_list', charlist=char_list, - title=_(u"Languages"), page="langlist", data="language", order=order_no) + title=_("Languages"), page="langlist", data="language", order=order_no) else: abort(404) @@ -1099,7 +1117,7 @@ def category_list(): entries = sorted(entries, key=lambda x: x[0].name.lower(), reverse=not order_no) char_list = generate_char_list(entries) 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=_("Categories"), page="catlist", data="category", order=order_no) else: abort(404) @@ -1157,11 +1175,15 @@ def serve_book(book_id, book_format, anyname): data = calibre_db.get_book_format(book_id, book_format.upper()) if not data: return "File not in Database" - log.info('Serving book: %s', data.name) + range_header = request.headers.get('Range', None) + if config.config_use_google_drive: try: headers = Headers() headers["Content-Type"] = mimetypes.types_map.get('.' + book_format, "application/octet-stream") + if not range_header: + log.info('Serving book: %s', data.name) + headers['Accept-Ranges'] = 'bytes' df = getFileFromEbooksFolder(book.path, data.name + "." + book_format) return do_gdrive_download(df, headers, (book_format.upper() == 'TXT')) except AttributeError as ex: @@ -1169,16 +1191,30 @@ def serve_book(book_id, book_format, anyname): return "File Not Found" else: if book_format.upper() == 'TXT': + log.info('Serving book: %s', data.name) try: rawdata = open(os.path.join(config.config_calibre_dir, book.path, data.name + "." + book_format), "rb").read() result = chardet.detect(rawdata) - return make_response( - rawdata.decode(result['encoding'], 'surrogatepass').encode('utf-8', 'surrogatepass')) + try: + text_data = rawdata.decode(result['encoding']).encode('utf-8') + except UnicodeDecodeError as e: + log.error("Encoding error in text file {}: {}".format(book.id, e)) + if "surrogate" in e.reason: + text_data = rawdata.decode(result['encoding'], 'surrogatepass').encode('utf-8', 'surrogatepass') + else: + text_data = rawdata.decode(result['encoding'], 'ignore').encode('utf-8', 'ignore') + return make_response(text_data) except FileNotFoundError: log.error("File Not Found") return "File Not Found" - return send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format) + # enable byte range read of pdf + response = make_response( + send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + book_format)) + if not range_header: + log.info('Serving book: %s', data.name) + response.headers['Accept-Ranges'] = 'bytes' + return response @web.route("/download//", defaults={'anyname': 'None'}) @@ -1191,165 +1227,196 @@ def download_link(book_id, book_format, anyname): @web.route('/send///', methods=["POST"]) -@login_required +@login_required_if_no_ano @download_required def send_to_ereader(book_id, book_format, convert): if not config.get_mail_server_configured(): - flash(_(u"Please configure the SMTP mail settings first..."), category="error") + response = [{'type': "danger", 'message': _("Please configure the SMTP mail settings first...")}] + return Response(json.dumps(response), mimetype='application/json') elif current_user.kindle_mail: result = send_mail(book_id, book_format, convert, current_user.kindle_mail, config.config_calibre_dir, current_user.name) if result is None: - flash(_(u"Book successfully queued for sending to %(kindlemail)s", kindlemail=current_user.kindle_mail), - category="success") ub.update_download(book_id, int(current_user.id)) + response = [{'type': "success", 'message': _("Success! Book queued for sending to %(eReadermail)s", + eReadermail=current_user.kindle_mail)}] else: - flash(_(u"Oops! There was an error sending this book: %(res)s", res=result), category="error") + response = [{'type': "danger", 'message': _("Oops! There was an error sending book: %(res)s", res=result)}] else: - flash(_(u"Please update your profile with a valid Send to Kindle E-mail Address."), category="error") - if "HTTP_REFERER" in request.environ: - return redirect(request.environ["HTTP_REFERER"]) - else: - return redirect(url_for('web.index')) + response = [{'type': "danger", 'message': _("Oops! Please update your profile with a valid eReader Email.")}] + return Response(json.dumps(response), mimetype='application/json') # ################################### Login Logout ################################################################## +@web.route('/register', methods=['POST']) +@limiter.limit("40/day", key_func=get_remote_address) +@limiter.limit("3/minute", key_func=get_remote_address) +def register_post(): + if not config.config_public_reg: + abort(404) + to_save = request.form.to_dict() + try: + limiter.check() + except RateLimitExceeded: + flash(_(u"Please wait one minute to register next user"), category="error") + return render_title_template('register.html', config=config, title=_("Register"), page="register") + if current_user is not None and current_user.is_authenticated: + return redirect(url_for('web.index')) + if not config.get_mail_server_configured(): + flash(_("Oops! Email server is not configured, please contact your administrator."), category="error") + return render_title_template('register.html', title=_("Register"), page="register") + nickname = to_save.get("email", "").strip() if config.config_register_email else to_save.get('name') + if not nickname or not to_save.get("email"): + flash(_("Oops! Please complete all fields."), category="error") + return render_title_template('register.html', title=_("Register"), page="register") + try: + nickname = check_username(nickname) + email = check_email(to_save.get("email", "")) + except Exception as ex: + flash(str(ex), category="error") + return render_title_template('register.html', title=_("Register"), page="register") -@web.route('/register', methods=['GET', 'POST']) + content = ub.User() + if check_valid_domain(email): + content.name = nickname + content.email = email + password = generate_random_password(config.config_password_min_length) + content.password = generate_password_hash(password) + content.role = config.config_default_role + content.locale = config.config_default_locale + content.sidebar_view = config.config_default_show + try: + ub.session.add(content) + ub.session.commit() + if feature_support['oauth']: + register_user_with_oauth(content) + send_registration_mail(to_save.get("email", "").strip(), nickname, password) + except Exception: + ub.session.rollback() + flash(_("Oops! An unknown error occurred. Please try again later."), category="error") + return render_title_template('register.html', title=_("Register"), page="register") + else: + flash(_("Oops! Your Email is not allowed."), category="error") + log.warning('Registering failed for user "{}" Email: {}'.format(nickname, to_save.get("email",""))) + return render_title_template('register.html', title=_("Register"), page="register") + flash(_("Success! Confirmation Email has been sent."), category="success") + return redirect(url_for('web.login')) + + +@web.route('/register', methods=['GET']) def register(): if not config.config_public_reg: abort(404) if current_user is not None and current_user.is_authenticated: return redirect(url_for('web.index')) if not config.get_mail_server_configured(): - flash(_(u"E-Mail server is not configured, please contact your administrator!"), category="error") + flash(_("Oops! Email server is not configured, please contact your administrator."), category="error") return render_title_template('register.html', title=_("Register"), page="register") - - if request.method == "POST": - to_save = request.form.to_dict() - nickname = to_save.get("email", "").strip() if config.config_register_email else to_save.get('name') - if not nickname or not to_save.get("email"): - flash(_(u"Please fill out all fields!"), category="error") - return render_title_template('register.html', title=_("Register"), page="register") - try: - nickname = check_username(nickname) - email = check_email(to_save.get("email", "")) - except Exception as ex: - flash(str(ex), category="error") - return render_title_template('register.html', title=_("Register"), page="register") - - content = ub.User() - if check_valid_domain(email): - content.name = nickname - content.email = email - password = generate_random_password() - content.password = generate_password_hash(password) - content.role = config.config_default_role - content.sidebar_view = config.config_default_show - try: - ub.session.add(content) - ub.session.commit() - if feature_support['oauth']: - register_user_with_oauth(content) - send_registration_mail(to_save.get("email", "").strip(), nickname, password) - except Exception: - ub.session.rollback() - flash(_(u"An unknown error occurred. Please try again later."), category="error") - return render_title_template('register.html', title=_("Register"), page="register") - else: - flash(_(u"Your e-mail is not allowed to register"), category="error") - log.warning('Registering failed for user "{}" e-mail address: {}'.format(nickname, - to_save.get("email",""))) - return render_title_template('register.html', title=_("Register"), page="register") - flash(_(u"Confirmation e-mail was send to your e-mail account."), category="success") - return redirect(url_for('web.login')) - if feature_support['oauth']: register_user_with_oauth() return render_title_template('register.html', config=config, title=_("Register"), page="register") -@web.route('/login', methods=['GET', 'POST']) +def handle_login_user(user, remember, message, category): + login_user(user, remember=remember) + ub.store_user_session() + flash(message, category=category) + [limiter.limiter.storage.clear(k.key) for k in limiter.current_limits] + return redirect_back(url_for("web.index")) + + +def render_login(username="", password=""): + next_url = request.args.get('next', default=url_for("web.index"), type=str) + if url_for("web.logout") == next_url: + next_url = url_for("web.index") + return render_title_template('login.html', + title=_("Login"), + next_url=next_url, + config=config, + username=username, + password=password, + oauth_check=oauth_check, + mail=config.get_mail_server_configured(), page="login") + + +@web.route('/login', methods=['GET']) def login(): if current_user is not None and current_user.is_authenticated: return redirect(url_for('web.index')) if config.config_login_type == constants.LOGIN_LDAP and not services.ldap: log.error(u"Cannot activate LDAP authentication") flash(_(u"Cannot activate LDAP authentication"), category="error") - if request.method == "POST": - form = request.form.to_dict() - user = ub.session.query(ub.User).filter(func.lower(ub.User.name) == form['username'].strip().lower()) \ - .first() - if config.config_login_type == constants.LOGIN_LDAP and services.ldap and (user or config.config_ldap_autocreate_user) and form['password'] != "": - login_result, error = services.ldap.bind_user(form['username'], form['password']) - if login_result: - if config.config_ldap_autocreate_user and not user: - user_data = services.ldap.get_object_details(user=form['username'], query_filter=config.config_ldap_user_object) - user_count, message = ldap_import_create_user(user, user_data) - user = ub.session.query(ub.User).filter(func.lower(ub.User.name) == form['username'].strip().lower()).first() + return render_login() - if user: - login_user(user, remember=bool(form.get('remember_me'))) - ub.store_user_session() - log.debug(u"You are now logged in as: '{}'".format(user.name)) - flash(_(u"you are now logged in as: '%(nickname)s'", nickname=user.name), category="success") - return redirect_back(url_for("web.index")) - else: - log.info("Login failed for user '{}'".format(user.name)) - log.debug("LDAP login succeeded but auto-create user has been disabled") - flash(_(u"Wrong Username or Password"), category="error") - elif login_result is None and user and check_password_hash(str(user.password), form['password']) \ - and user.name != "Guest": - login_user(user, remember=bool(form.get('remember_me'))) - ub.store_user_session() - log.info("Local Fallback Login as: '{}'".format(user.name)) - flash(_(u"Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known", - nickname=user.name), - category="warning") - return redirect_back(url_for("web.index")) - elif login_result is None: - log.info(error) - flash(_(u"Could not login: %(message)s", message=error), category="error") - else: - ip_address = request.headers.get('X-Forwarded-For', request.remote_addr) - log.warning('LDAP Login failed for user "%s" IP-address: %s', form['username'], ip_address) - flash(_(u"Wrong Username or Password"), category="error") + +@web.route('/login', methods=['POST']) +@limiter.limit("40/day", key_func=lambda: request.form.get('username', "").strip().lower()) +@limiter.limit("3/minute", key_func=lambda: request.form.get('username', "").strip().lower()) +def login_post(): + form = request.form.to_dict() + try: + limiter.check() + except RateLimitExceeded: + flash(_(u"Please wait one minute before next login"), category="error") + return render_login(form.get("username", ""), form.get("password", "")) + if current_user is not None and current_user.is_authenticated: + return redirect(url_for('web.index')) + if config.config_login_type == constants.LOGIN_LDAP and not services.ldap: + log.error(u"Cannot activate LDAP authentication") + flash(_(u"Cannot activate LDAP authentication"), category="error") + user = ub.session.query(ub.User).filter(func.lower(ub.User.name) == form.get('username', "").strip().lower()) \ + .first() + remember_me = bool(form.get('remember_me')) + if config.config_login_type == constants.LOGIN_LDAP and services.ldap and user and form['password'] != "": + login_result, error = services.ldap.bind_user(form['username'], form['password']) + if login_result: + log.debug(u"You are now logged in as: '{}'".format(user.name)) + return handle_login_user(user, + remember_me, + _(u"you are now logged in as: '%(nickname)s'", nickname=user.name), + "success") + elif login_result is None and user and check_password_hash(str(user.password), form['password']) \ + and user.name != "Guest": + log.info("Local Fallback Login as: '{}'".format(user.name)) + return handle_login_user(user, + remember_me, + _(u"Fallback Login as: '%(nickname)s', " + u"LDAP Server not reachable, or user not known", nickname=user.name), + "warning") + elif login_result is None: + log.info(error) + flash(_(u"Could not login: %(message)s", message=error), category="error") else: ip_address = request.headers.get('X-Forwarded-For', request.remote_addr) - if form.get('forgot', "") == 'forgot': - if user is not None and user.name != "Guest": - ret, __ = reset_password(user.id) - if ret == 1: - flash(_(u"New Password was send to your email address"), category="info") - log.info('Password reset for user "%s" IP-address: %s', form['username'], ip_address) - else: - log.error(u"An unknown error occurred. Please try again later") - flash(_(u"An unknown error occurred. Please try again later."), category="error") + log.warning('LDAP Login failed for user "%s" IP-address: %s', form['username'], ip_address) + flash(_(u"Wrong Username or Password"), category="error") + else: + ip_address = request.headers.get('X-Forwarded-For', request.remote_addr) + if form.get('forgot', "") == 'forgot': + if user is not None and user.name != "Guest": + ret, __ = reset_password(user.id) + if ret == 1: + flash(_(u"New Password was send to your email address"), category="info") + log.info('Password reset for user "%s" IP-address: %s', form['username'], ip_address) else: - flash(_(u"Please enter valid username to reset password"), category="error") - log.warning('Username missing for password reset IP-address: %s', ip_address) + log.error(u"An unknown error occurred. Please try again later") + flash(_(u"An unknown error occurred. Please try again later."), category="error") else: - if user and check_password_hash(str(user.password), form['password']) and user.name != "Guest": - login_user(user, remember=bool(form.get('remember_me'))) - ub.store_user_session() - log.debug(u"You are now logged in as: '%s'", user.name) - flash(_(u"You are now logged in as: '%(nickname)s'", nickname=user.name), category="success") - config.config_is_initial = False - return redirect_back(url_for("web.index")) - else: - log.warning('Login failed for user "{}" IP-address: {}'.format(form['username'], ip_address)) - flash(_(u"Wrong Username or Password"), category="error") - - next_url = request.args.get('next', default=url_for("web.index"), type=str) - if url_for("web.logout") == next_url: - next_url = url_for("web.index") - return render_title_template('login.html', - title=_(u"Login"), - next_url=next_url, - config=config, - oauth_check=oauth_check, - mail=config.get_mail_server_configured(), page="login") + flash(_(u"Please enter valid username to reset password"), category="error") + log.warning('Username missing for password reset IP-address: %s', ip_address) + else: + if user and check_password_hash(str(user.password), form['password']) and user.name != "Guest": + config.config_is_initial = False + log.debug(u"You are now logged in as: '{}'".format(user.name)) + return handle_login_user(user, + remember_me, + _(u"You are now logged in as: '%(nickname)s'", nickname=user.name), + "success") + else: + log.warning('Login failed for user "{}" IP-address: {}'.format(form['username'], ip_address)) + flash(_(u"Wrong Username or Password"), category="error") + return render_login(form.get("username", ""), form.get("password", "")) @web.route('/logout') @@ -1360,7 +1427,7 @@ def logout(): logout_user() if feature_support['oauth'] and (config.config_login_type == 2 or config.config_login_type == 3): logout_oauth_user() - log.debug(u"User logged out") + log.debug("User logged out") return redirect(url_for('web.login')) @@ -1368,15 +1435,15 @@ def logout(): def change_profile(kobo_support, local_oauth_check, oauth_status, translations, languages): to_save = request.form.to_dict() current_user.random_books = 0 - if current_user.role_passwd() or current_user.role_admin(): - if to_save.get("password"): - current_user.password = generate_password_hash(to_save.get("password")) try: + if current_user.role_passwd() or current_user.role_admin(): + if to_save.get("password", "") != "": + current_user.password = generate_password_hash(valid_password(to_save.get("password"))) if to_save.get("kindle_mail", current_user.kindle_mail) != current_user.kindle_mail: current_user.kindle_mail = valid_email(to_save.get("kindle_mail")) new_email = valid_email(to_save.get("email", current_user.email)) if not new_email: - raise Exception(_(u"E-Mail Address can't be empty and has to be a valid E-Mail")) + raise Exception(_("Email can't be empty and has to be a valid Email")) if new_email != current_user.email: current_user.email = check_email(new_email) if current_user.role_admin(): @@ -1398,10 +1465,11 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations, flash(str(ex), category="error") return render_title_template("user_edit.html", content=current_user, + config=config, translations=translations, profile=1, languages=languages, - title=_(u"%(name)s's profile", name=current_user.name), + title=_("%(name)s's Profile", name=current_user.name), page="me", kobo_support=kobo_support, registered_oauth=local_oauth_check, @@ -1417,16 +1485,16 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations, try: ub.session.commit() - flash(_(u"Profile updated"), category="success") - log.debug(u"Profile updated") + flash(_("Success! Profile Updated"), category="success") + log.debug("Profile updated") except IntegrityError: ub.session.rollback() - flash(_(u"Found an existing account for this e-mail address"), category="error") - log.debug(u"Found an existing account for this e-mail address") + flash(_("Oops! An account already exists for this Email."), category="error") + log.debug("Found an existing account for this Email") except OperationalError as e: ub.session.rollback() log.error("Database error: %s", e) - flash(_(u"Database error: %(error)s.", error=e), category="error") + flash(_("Oops! Database Error: %(error)s.", error=e), category="error") @web.route("/me", methods=["GET", "POST"]) @@ -1449,8 +1517,9 @@ def profile(): profile=1, languages=languages, content=current_user, + config=config, kobo_support=kobo_support, - title=_(u"%(name)s's profile", name=current_user.name), + title=_("%(name)s's Profile", name=current_user.name), page="me", registered_oauth=local_oauth_check, oauth_status=oauth_status) @@ -1464,14 +1533,15 @@ def profile(): @viewer_required def read_book(book_id, book_format): book = calibre_db.get_filtered_book(book_id) - book.ordered_authors = calibre_db.order_authors([book], False) if not book: - flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), + flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), category="error") - log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible") + log.debug("Selected book is unavailable. File does not exist or is not accessible") return redirect(url_for("web.index")) + book.ordered_authors = calibre_db.order_authors([book], False) + # check if book has a bookmark bookmark = None if current_user.is_authenticated: @@ -1479,22 +1549,22 @@ def read_book(book_id, book_format): ub.Bookmark.book_id == book_id, ub.Bookmark.format == book_format.upper())).first() if book_format.lower() == "epub": - log.debug(u"Start epub reader for %d", book_id) + log.debug("Start epub reader for %d", book_id) return render_title_template('read.html', bookid=book_id, title=book.title, bookmark=bookmark) elif book_format.lower() == "pdf": - log.debug(u"Start pdf reader for %d", book_id) + log.debug("Start pdf reader for %d", book_id) return render_title_template('readpdf.html', pdffile=book_id, title=book.title) elif book_format.lower() == "txt": - log.debug(u"Start txt reader for %d", book_id) + log.debug("Start txt reader for %d", book_id) return render_title_template('readtxt.html', txtfile=book_id, title=book.title) - elif book_format.lower() == "djvu": - log.debug(u"Start djvu reader for %d", book_id) - return render_title_template('readdjvu.html', djvufile=book_id, title=book.title) + elif book_format.lower() in ["djvu", "djv"]: + log.debug("Start djvu reader for %d", book_id) + return render_title_template('readdjvu.html', djvufile=book_id, title=book.title, extension=book_format.lower()) else: for fileExt in constants.EXTENSIONS_AUDIO: if book_format.lower() == fileExt: entries = calibre_db.get_filtered_book(book_id) - log.debug(u"Start mp3 listening for %d", book_id) + log.debug("Start mp3 listening for %d", book_id) return render_title_template('listenmp3.html', mp3file=book_id, audioformat=book_format.lower(), entry=entries, bookmark=bookmark) for fileExt in ["cbr", "cbt", "cbz"]: @@ -1505,11 +1575,11 @@ def read_book(book_id, book_format): title = title + " - " + book.series[0].name if book.series_index: title = title + " #" + '{0:.2f}'.format(book.series_index).rstrip('0').rstrip('.') - log.debug(u"Start comic reader for %d", book_id) + log.debug("Start comic reader for %d", book_id) return render_title_template('readcbr.html', comicfile=all_name, title=title, - extension=fileExt) - log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible") - flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), + extension=fileExt, bookmark=bookmark) + log.debug("Selected book is unavailable. File does not exist or is not accessible") + flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), category="error") return redirect(url_for("web.index")) @@ -1553,7 +1623,7 @@ def show_book(book_id): books_shelfs=book_in_shelves, page="book") else: - log.debug(u"Oops! Selected book title is unavailable. File does not exist or is not accessible") - flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), + log.debug("Selected book is unavailable. File does not exist or is not accessible") + flash(_("Oops! Selected book is unavailable. File does not exist or is not accessible"), category="error") return redirect(url_for("web.index")) diff --git a/library/metadata.db b/library/metadata.db new file mode 100644 index 00000000..fc0d5d31 Binary files /dev/null and b/library/metadata.db differ diff --git a/messages.pot b/messages.pot index 9e9dd10b..c683f205 100644 --- a/messages.pot +++ b/messages.pot @@ -1,500 +1,507 @@ # Translations template for PROJECT. -# Copyright (C) 2022 ORGANIZATION +# Copyright (C) 2023 ORGANIZATION # This file is distributed under the same license as the PROJECT project. -# FIRST AUTHOR , 2022. +# FIRST AUTHOR , 2023. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2022-10-02 21:12+0200\n" +"POT-Creation-Date: 2023-12-21 13:31+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.10.3\n" +"Generated-By: Babel 2.13.1\n" #: cps/about.py:84 msgid "Statistics" msgstr "" -#: cps/admin.py:146 -msgid "Server restarted, please reload page" +#: cps/admin.py:149 +msgid "Server restarted, please reload page." msgstr "" -#: cps/admin.py:148 -msgid "Performing shutdown of server, please close window" -msgstr "" - -#: cps/admin.py:156 -msgid "Reconnect successful" +#: cps/admin.py:151 +msgid "Performing Server shutdown, please close window." msgstr "" #: cps/admin.py:159 +msgid "Success! Database Reconnected" +msgstr "" + +#: cps/admin.py:162 msgid "Unknown command" msgstr "" -#: cps/admin.py:169 -msgid "Books successfully queued for Metadata Backup" +#: cps/admin.py:173 +msgid "Success! Books queued for Metadata Backup, please check Tasks for result" msgstr "" -#: cps/admin.py:202 cps/editbooks.py:576 cps/editbooks.py:578 -#: cps/editbooks.py:614 cps/editbooks.py:631 cps/editbooks.py:1238 -#: cps/updater.py:613 cps/uploader.py:86 cps/uploader.py:96 +#: cps/admin.py:206 cps/editbooks.py:587 cps/editbooks.py:589 +#: cps/editbooks.py:627 cps/editbooks.py:644 cps/editbooks.py:1256 +#: cps/updater.py:613 cps/uploader.py:93 cps/uploader.py:102 msgid "Unknown" msgstr "" -#: cps/admin.py:227 +#: cps/admin.py:231 msgid "Admin page" msgstr "" -#: cps/admin.py:247 +#: cps/admin.py:251 msgid "Basic Configuration" msgstr "" -#: cps/admin.py:285 +#: cps/admin.py:289 msgid "UI Configuration" msgstr "" -#: cps/admin.py:319 cps/templates/admin.html:51 +#: cps/admin.py:323 cps/templates/admin.html:51 msgid "Edit Users" msgstr "" -#: cps/admin.py:363 cps/opds.py:532 cps/templates/grid.html:14 +#: cps/admin.py:367 cps/opds.py:506 cps/templates/grid.html:14 #: cps/templates/list.html:13 msgid "All" msgstr "" -#: cps/admin.py:390 cps/admin.py:1380 +#: cps/admin.py:394 cps/admin.py:1405 msgid "User not found" msgstr "" -#: cps/admin.py:404 +#: cps/admin.py:408 msgid "{} users deleted successfully" msgstr "" -#: cps/admin.py:427 cps/templates/config_view_edit.html:133 +#: cps/admin.py:431 cps/templates/config_view_edit.html:133 #: cps/templates/user_edit.html:45 cps/templates/user_table.html:81 msgid "Show All" msgstr "" -#: cps/admin.py:448 cps/admin.py:454 +#: cps/admin.py:452 cps/admin.py:458 msgid "Malformed request" msgstr "" -#: cps/admin.py:466 cps/admin.py:1981 +#: cps/admin.py:470 cps/admin.py:2023 msgid "Guest Name can't be changed" msgstr "" -#: cps/admin.py:478 +#: cps/admin.py:482 msgid "Guest can't have this role" msgstr "" -#: cps/admin.py:490 cps/admin.py:1936 +#: cps/admin.py:494 cps/admin.py:1977 msgid "No admin user remaining, can't remove admin role" msgstr "" -#: cps/admin.py:494 cps/admin.py:508 +#: cps/admin.py:498 cps/admin.py:512 msgid "Value has to be true or false" msgstr "" -#: cps/admin.py:496 +#: cps/admin.py:500 msgid "Invalid role" msgstr "" -#: cps/admin.py:500 +#: cps/admin.py:504 msgid "Guest can't have this view" msgstr "" -#: cps/admin.py:510 +#: cps/admin.py:514 msgid "Invalid view" msgstr "" -#: cps/admin.py:513 +#: cps/admin.py:517 msgid "Guest's Locale is determined automatically and can't be set" msgstr "" -#: cps/admin.py:517 +#: cps/admin.py:521 msgid "No Valid Locale Given" msgstr "" -#: cps/admin.py:528 +#: cps/admin.py:532 msgid "No Valid Book Language Given" msgstr "" -#: cps/admin.py:530 cps/editbooks.py:442 +#: cps/admin.py:534 cps/editbooks.py:453 msgid "Parameter not found" msgstr "" -#: cps/admin.py:567 +#: cps/admin.py:571 msgid "Invalid Read Column" msgstr "" -#: cps/admin.py:573 +#: cps/admin.py:577 msgid "Invalid Restricted Column" msgstr "" -#: cps/admin.py:593 cps/admin.py:1807 +#: cps/admin.py:597 cps/admin.py:1848 msgid "Calibre-Web configuration updated" msgstr "" -#: cps/admin.py:605 +#: cps/admin.py:609 msgid "Do you really want to delete the Kobo Token?" msgstr "" -#: cps/admin.py:607 +#: cps/admin.py:611 msgid "Do you really want to delete this domain?" msgstr "" -#: cps/admin.py:609 +#: cps/admin.py:613 msgid "Do you really want to delete this user?" msgstr "" -#: cps/admin.py:611 +#: cps/admin.py:615 msgid "Are you sure you want to delete this shelf?" msgstr "" -#: cps/admin.py:613 +#: cps/admin.py:617 msgid "Are you sure you want to change locales of selected user(s)?" msgstr "" -#: cps/admin.py:615 +#: cps/admin.py:619 msgid "Are you sure you want to change visible book languages for selected user(s)?" msgstr "" -#: cps/admin.py:617 +#: cps/admin.py:621 msgid "Are you sure you want to change the selected role for the selected user(s)?" msgstr "" -#: cps/admin.py:619 +#: cps/admin.py:623 msgid "Are you sure you want to change the selected restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:621 +#: cps/admin.py:625 msgid "Are you sure you want to change the selected visibility restrictions for the selected user(s)?" msgstr "" -#: cps/admin.py:624 +#: cps/admin.py:628 msgid "Are you sure you want to change shelf sync behavior for the selected user(s)?" msgstr "" -#: cps/admin.py:626 +#: cps/admin.py:630 msgid "Are you sure you want to change Calibre library location?" msgstr "" -#: cps/admin.py:628 +#: cps/admin.py:632 msgid "Calibre-Web will search for updated Covers and update Cover Thumbnails, this may take a while?" msgstr "" -#: cps/admin.py:631 +#: cps/admin.py:635 msgid "Are you sure you want delete Calibre-Web's sync database to force a full sync with your Kobo Reader?" msgstr "" -#: cps/admin.py:874 cps/admin.py:880 cps/admin.py:890 cps/admin.py:900 +#: cps/admin.py:878 cps/admin.py:884 cps/admin.py:894 cps/admin.py:904 #: cps/templates/modal_dialogs.html:29 cps/templates/user_table.html:41 #: cps/templates/user_table.html:58 msgid "Deny" msgstr "" -#: cps/admin.py:876 cps/admin.py:882 cps/admin.py:892 cps/admin.py:902 +#: cps/admin.py:880 cps/admin.py:886 cps/admin.py:896 cps/admin.py:906 #: cps/templates/modal_dialogs.html:28 cps/templates/user_table.html:44 #: cps/templates/user_table.html:61 msgid "Allow" msgstr "" -#: cps/admin.py:917 +#: cps/admin.py:921 msgid "{} sync entries deleted" msgstr "" -#: cps/admin.py:965 +#: cps/admin.py:969 msgid "Tag not found" msgstr "" -#: cps/admin.py:977 +#: cps/admin.py:981 msgid "Invalid Action" msgstr "" -#: cps/admin.py:1092 +#: cps/admin.py:1111 msgid "client_secrets.json Is Not Configured For Web Application" msgstr "" -#: cps/admin.py:1137 +#: cps/admin.py:1156 msgid "Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1143 +#: cps/admin.py:1162 msgid "Access Logfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1173 +#: cps/admin.py:1196 msgid "Please Enter a LDAP Provider, Port, DN and User Object Identifier" msgstr "" -#: cps/admin.py:1179 +#: cps/admin.py:1202 msgid "Please Enter a LDAP Service Account and Password" msgstr "" -#: cps/admin.py:1182 +#: cps/admin.py:1205 msgid "Please Enter a LDAP Service Account" msgstr "" -#: cps/admin.py:1187 +#: cps/admin.py:1210 #, python-format msgid "LDAP Group Object Filter Needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1189 +#: cps/admin.py:1212 msgid "LDAP Group Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1193 +#: cps/admin.py:1216 #, python-format msgid "LDAP User Object Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1195 +#: cps/admin.py:1218 msgid "LDAP User Object Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1202 +#: cps/admin.py:1225 #, python-format msgid "LDAP Member User Filter needs to Have One \"%s\" Format Identifier" msgstr "" -#: cps/admin.py:1204 +#: cps/admin.py:1227 msgid "LDAP Member User Filter Has Unmatched Parenthesis" msgstr "" -#: cps/admin.py:1211 +#: cps/admin.py:1234 msgid "LDAP CACertificate, Certificate or Key Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1242 cps/admin.py:1868 -msgid "Add new user" +#: cps/admin.py:1265 cps/templates/admin.html:53 +msgid "Add New User" msgstr "" -#: cps/admin.py:1251 cps/templates/admin.html:100 -msgid "Edit E-mail Server Settings" +#: cps/admin.py:1274 cps/templates/admin.html:100 +msgid "Edit Email Server Settings" msgstr "" -#: cps/admin.py:1270 -msgid "Gmail Account Verification Successful" +#: cps/admin.py:1293 +msgid "Success! Gmail Account Verified." msgstr "" -#: cps/admin.py:1289 cps/admin.py:1292 cps/admin.py:1673 cps/admin.py:1791 -#: cps/admin.py:1889 cps/admin.py:2009 cps/editbooks.py:229 -#: cps/editbooks.py:305 cps/editbooks.py:1201 cps/shelf.py:82 cps/shelf.py:142 -#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:343 -#: cps/shelf.py:457 cps/tasks/convert.py:136 cps/web.py:1419 +#: cps/admin.py:1313 cps/admin.py:1316 cps/admin.py:1698 cps/admin.py:1832 +#: cps/admin.py:1930 cps/admin.py:2051 cps/editbooks.py:239 +#: cps/editbooks.py:315 cps/editbooks.py:1218 cps/shelf.py:82 cps/shelf.py:142 +#: cps/shelf.py:185 cps/shelf.py:235 cps/shelf.py:272 cps/shelf.py:346 +#: cps/shelf.py:460 cps/tasks/convert.py:136 cps/web.py:1496 #, python-format -msgid "Database error: %(error)s." +msgid "Oops! Database Error: %(error)s." msgstr "" -#: cps/admin.py:1299 +#: cps/admin.py:1323 #, python-format msgid "Test e-mail queued for sending to %(email)s, please check Tasks for result" msgstr "" -#: cps/admin.py:1302 +#: cps/admin.py:1326 #, python-format msgid "There was an error sending the Test e-mail: %(res)s" msgstr "" -#: cps/admin.py:1304 +#: cps/admin.py:1328 msgid "Please configure your e-mail address first..." msgstr "" -#: cps/admin.py:1306 -msgid "E-mail server settings updated" +#: cps/admin.py:1330 +msgid "Email Server Settings updated" msgstr "" -#: cps/admin.py:1329 cps/templates/admin.html:191 +#: cps/admin.py:1353 cps/templates/admin.html:195 msgid "Edit Scheduled Tasks Settings" msgstr "" -#: cps/admin.py:1341 +#: cps/admin.py:1365 msgid "Invalid start time for task specified" msgstr "" -#: cps/admin.py:1346 +#: cps/admin.py:1370 msgid "Invalid duration for task specified" msgstr "" -#: cps/admin.py:1355 +#: cps/admin.py:1380 msgid "Scheduled tasks settings updated" msgstr "" -#: cps/admin.py:1365 cps/admin.py:1414 cps/admin.py:2005 cps/web.py:1257 -#: cps/web.py:1318 -msgid "An unknown error occurred. Please try again later." +#: cps/admin.py:1390 cps/admin.py:1439 cps/admin.py:2047 cps/web.py:1296 +msgid "Oops! An unknown error occurred. Please try again later." msgstr "" -#: cps/admin.py:1369 +#: cps/admin.py:1394 msgid "Settings DB is not Writeable" msgstr "" -#: cps/admin.py:1399 cps/admin.py:1997 +#: cps/admin.py:1424 cps/admin.py:2039 #, python-format msgid "Edit User %(nick)s" msgstr "" -#: cps/admin.py:1411 +#: cps/admin.py:1436 #, python-format -msgid "Password for user %(user)s reset" +msgid "Success! Password for user %(user)s reset" msgstr "" -#: cps/admin.py:1417 cps/web.py:1197 -msgid "Please configure the SMTP mail settings first..." +#: cps/admin.py:1442 +msgid "Oops! Please configure the SMTP mail settings." msgstr "" -#: cps/admin.py:1428 +#: cps/admin.py:1453 msgid "Logfile viewer" msgstr "" -#: cps/admin.py:1494 +#: cps/admin.py:1519 msgid "Requesting update package" msgstr "" -#: cps/admin.py:1495 +#: cps/admin.py:1520 msgid "Downloading update package" msgstr "" -#: cps/admin.py:1496 +#: cps/admin.py:1521 msgid "Unzipping update package" msgstr "" -#: cps/admin.py:1497 +#: cps/admin.py:1522 msgid "Replacing files" msgstr "" -#: cps/admin.py:1498 +#: cps/admin.py:1523 msgid "Database connections are closed" msgstr "" -#: cps/admin.py:1499 +#: cps/admin.py:1524 msgid "Stopping server" msgstr "" -#: cps/admin.py:1500 +#: cps/admin.py:1525 msgid "Update finished, please press okay and reload page" msgstr "" -#: cps/admin.py:1501 cps/admin.py:1502 cps/admin.py:1503 cps/admin.py:1504 -#: cps/admin.py:1505 cps/admin.py:1506 +#: cps/admin.py:1526 cps/admin.py:1527 cps/admin.py:1528 cps/admin.py:1529 +#: cps/admin.py:1530 cps/admin.py:1531 msgid "Update failed:" msgstr "" -#: cps/admin.py:1501 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 +#: cps/admin.py:1526 cps/updater.py:389 cps/updater.py:624 cps/updater.py:626 msgid "HTTP Error" msgstr "" -#: cps/admin.py:1502 cps/updater.py:391 cps/updater.py:628 +#: cps/admin.py:1527 cps/updater.py:391 cps/updater.py:628 msgid "Connection error" msgstr "" -#: cps/admin.py:1503 cps/updater.py:393 cps/updater.py:630 +#: cps/admin.py:1528 cps/updater.py:393 cps/updater.py:630 msgid "Timeout while establishing connection" msgstr "" -#: cps/admin.py:1504 cps/updater.py:395 cps/updater.py:632 +#: cps/admin.py:1529 cps/updater.py:395 cps/updater.py:632 msgid "General error" msgstr "" -#: cps/admin.py:1505 +#: cps/admin.py:1530 msgid "Update file could not be saved in temp dir" msgstr "" -#: cps/admin.py:1506 +#: cps/admin.py:1531 msgid "Files could not be replaced during update" msgstr "" -#: cps/admin.py:1530 +#: cps/admin.py:1555 msgid "Failed to extract at least One LDAP User" msgstr "" -#: cps/admin.py:1575 +#: cps/admin.py:1600 msgid "Failed to Create at Least One LDAP User" msgstr "" -#: cps/admin.py:1588 +#: cps/admin.py:1613 #, python-format msgid "Error: %(ldaperror)s" msgstr "" -#: cps/admin.py:1592 +#: cps/admin.py:1617 msgid "Error: No user returned in response of LDAP server" msgstr "" -#: cps/admin.py:1625 +#: cps/admin.py:1650 msgid "At Least One LDAP User Not Found in Database" msgstr "" -#: cps/admin.py:1627 +#: cps/admin.py:1652 msgid "{} User Successfully Imported" msgstr "" -#: cps/admin.py:1685 +#: cps/admin.py:1710 msgid "DB Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1705 +#: cps/admin.py:1730 msgid "DB is not Writeable" msgstr "" -#: cps/admin.py:1718 +#: cps/admin.py:1743 msgid "Keyfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1722 +#: cps/admin.py:1747 msgid "Certfile Location is not Valid, Please Enter Correct Path" msgstr "" -#: cps/admin.py:1830 +#: cps/admin.py:1819 +msgid "Password length has to be between 1 and 40" +msgstr "" + +#: cps/admin.py:1871 msgid "Database Settings updated" msgstr "" -#: cps/admin.py:1838 +#: cps/admin.py:1879 msgid "Database Configuration" msgstr "" -#: cps/admin.py:1854 cps/web.py:1232 -msgid "Please fill out all fields!" +#: cps/admin.py:1894 cps/web.py:1270 +msgid "Oops! Please complete all fields." msgstr "" -#: cps/admin.py:1862 +#: cps/admin.py:1903 msgid "E-mail is not from valid domain" msgstr "" -#: cps/admin.py:1879 +#: cps/admin.py:1909 +msgid "Add new user" +msgstr "" + +#: cps/admin.py:1920 #, python-format msgid "User '%(user)s' created" msgstr "" -#: cps/admin.py:1885 -msgid "Found an existing account for this e-mail address or name." +#: cps/admin.py:1926 +msgid "Oops! An account already exists for this Email. or name." msgstr "" -#: cps/admin.py:1915 +#: cps/admin.py:1956 #, python-format msgid "User '%(nick)s' deleted" msgstr "" -#: cps/admin.py:1917 cps/admin.py:1918 +#: cps/admin.py:1959 msgid "Can't delete Guest User" msgstr "" -#: cps/admin.py:1921 +#: cps/admin.py:1962 msgid "No admin user remaining, can't delete user" msgstr "" -#: cps/admin.py:1975 cps/web.py:1369 -msgid "E-Mail Address can't be empty and has to be a valid E-Mail" +#: cps/admin.py:2017 cps/web.py:1445 +msgid "Email can't be empty and has to be a valid Email" msgstr "" -#: cps/admin.py:2001 +#: cps/admin.py:2043 #, python-format msgid "User '%(nick)s' updated" msgstr "" @@ -507,122 +514,122 @@ msgstr "" msgid "Execution permissions missing" msgstr "" -#: cps/db.py:724 cps/search.py:137 cps/web.py:722 +#: cps/db.py:752 cps/search.py:137 cps/web.py:731 #, python-format msgid "Custom Column No.%(column)d does not exist in calibre database" msgstr "" -#: cps/db.py:967 cps/templates/config_edit.html:204 +#: cps/db.py:993 cps/templates/config_edit.html:204 #: cps/templates/config_view_edit.html:62 cps/templates/email_edit.html:41 -#: cps/web.py:549 cps/web.py:583 cps/web.py:658 cps/web.py:683 cps/web.py:964 -#: cps/web.py:994 cps/web.py:1030 cps/web.py:1058 cps/web.py:1097 +#: cps/web.py:558 cps/web.py:592 cps/web.py:665 cps/web.py:692 cps/web.py:973 +#: cps/web.py:1003 cps/web.py:1048 cps/web.py:1076 cps/web.py:1115 msgid "None" msgstr "" -#: cps/editbooks.py:110 cps/editbooks.py:895 cps/web.py:516 cps/web.py:1460 -#: cps/web.py:1502 cps/web.py:1547 -msgid "Oops! Selected book title is unavailable. File does not exist or is not accessible" +#: cps/editbooks.py:120 cps/editbooks.py:908 cps/web.py:525 cps/web.py:1537 +#: cps/web.py:1581 cps/web.py:1626 +msgid "Oops! Selected book is unavailable. File does not exist or is not accessible" msgstr "" -#: cps/editbooks.py:154 cps/editbooks.py:1221 +#: cps/editbooks.py:164 cps/editbooks.py:1239 msgid "User has no rights to upload cover" msgstr "" -#: cps/editbooks.py:174 cps/editbooks.py:716 +#: cps/editbooks.py:184 cps/editbooks.py:729 msgid "Identifiers are not Case Sensitive, Overwriting Old Identifier" msgstr "" -#: cps/editbooks.py:216 +#: cps/editbooks.py:226 msgid "Metadata successfully updated" msgstr "" -#: cps/editbooks.py:234 +#: cps/editbooks.py:244 msgid "Error editing book: {}" msgstr "" -#: cps/editbooks.py:291 +#: cps/editbooks.py:301 #, python-format msgid "File %(file)s uploaded" msgstr "" -#: cps/editbooks.py:318 +#: cps/editbooks.py:329 msgid "Source or destination format for conversion missing" msgstr "" -#: cps/editbooks.py:326 +#: cps/editbooks.py:337 #, python-format msgid "Book successfully queued for converting to %(book_format)s" msgstr "" -#: cps/editbooks.py:330 +#: cps/editbooks.py:341 #, python-format msgid "There was an error converting this book: %(res)s" msgstr "" -#: cps/editbooks.py:635 +#: cps/editbooks.py:648 msgid "Uploaded book probably exists in the library, consider to change before upload new: " msgstr "" -#: cps/editbooks.py:690 cps/editbooks.py:1015 +#: cps/editbooks.py:703 cps/editbooks.py:1031 #, python-format msgid "'%(langname)s' is not a valid language" msgstr "" -#: cps/editbooks.py:728 cps/editbooks.py:1162 +#: cps/editbooks.py:741 cps/editbooks.py:1179 #, python-format msgid "File extension '%(ext)s' is not allowed to be uploaded to this server" msgstr "" -#: cps/editbooks.py:732 cps/editbooks.py:1166 +#: cps/editbooks.py:745 cps/editbooks.py:1183 msgid "File to be uploaded must have an extension" msgstr "" -#: cps/editbooks.py:740 +#: cps/editbooks.py:753 #, python-format msgid "File %(filename)s could not saved to temp dir" msgstr "" -#: cps/editbooks.py:760 +#: cps/editbooks.py:773 #, python-format msgid "Failed to Move Cover File %(file)s: %(error)s" msgstr "" -#: cps/editbooks.py:817 cps/editbooks.py:819 +#: cps/editbooks.py:830 cps/editbooks.py:832 msgid "Book Format Successfully Deleted" msgstr "" -#: cps/editbooks.py:826 cps/editbooks.py:828 +#: cps/editbooks.py:839 cps/editbooks.py:841 msgid "Book Successfully Deleted" msgstr "" -#: cps/editbooks.py:880 +#: cps/editbooks.py:893 msgid "You are missing permissions to delete books" msgstr "" -#: cps/editbooks.py:930 +#: cps/editbooks.py:943 msgid "edit metadata" msgstr "" -#: cps/editbooks.py:979 +#: cps/editbooks.py:992 #, python-format msgid "%(seriesindex)s is not a valid number, skipping" msgstr "" -#: cps/editbooks.py:1157 +#: cps/editbooks.py:1174 msgid "User has no rights to upload additional file formats" msgstr "" -#: cps/editbooks.py:1178 +#: cps/editbooks.py:1195 #, python-format msgid "Failed to create path %(path)s (Permission denied)." msgstr "" -#: cps/editbooks.py:1183 +#: cps/editbooks.py:1200 #, python-format msgid "Failed to store file %(file)s." msgstr "" -#: cps/editbooks.py:1206 +#: cps/editbooks.py:1224 #, python-format msgid "File format %(ext)s added to %(book)s" msgstr "" @@ -635,178 +642,181 @@ msgstr "" msgid "Callback domain is not verified, please follow steps to verify domain in google developer console" msgstr "" -#: cps/helper.py:80 +#: cps/helper.py:81 #, python-format msgid "%(format)s format not found for book id: %(book)d" msgstr "" -#: cps/helper.py:87 cps/tasks/convert.py:75 +#: cps/helper.py:88 cps/tasks/convert.py:75 #, python-format msgid "%(format)s not found on Google Drive: %(fn)s" msgstr "" -#: cps/helper.py:92 +#: cps/helper.py:93 #, python-format msgid "%(format)s not found: %(fn)s" msgstr "" -#: cps/helper.py:97 cps/helper.py:226 cps/templates/detail.html:42 -#: cps/templates/detail.html:46 -msgid "Send to E-Reader" +#: cps/helper.py:98 cps/helper.py:223 cps/templates/detail.html:58 +msgid "Send to eReader" msgstr "" -#: cps/helper.py:98 cps/helper.py:116 cps/helper.py:228 -msgid "This e-mail has been sent via Calibre-Web." -msgstr "" - -#: cps/helper.py:114 -msgid "Calibre-Web test e-mail" +#: cps/helper.py:99 cps/helper.py:117 cps/helper.py:225 +msgid "This Email has been sent via Calibre-Web." msgstr "" #: cps/helper.py:115 -msgid "Test e-mail" +msgid "Calibre-Web Test Email" msgstr "" -#: cps/helper.py:132 +#: cps/helper.py:116 +msgid "Test Email" +msgstr "" + +#: cps/helper.py:133 msgid "Get Started with Calibre-Web" msgstr "" -#: cps/helper.py:137 +#: cps/helper.py:138 #, python-format -msgid "Registration e-mail for user: %(name)s" +msgid "Registration Email for user: %(name)s" msgstr "" -#: cps/helper.py:148 cps/helper.py:154 +#: cps/helper.py:149 cps/helper.py:155 #, python-format -msgid "Convert %(orig)s to %(format)s and send to E-Reader" +msgid "Convert %(orig)s to %(format)s and send to eReader" msgstr "" -#: cps/helper.py:173 cps/helper.py:177 cps/helper.py:181 cps/helper.py:185 +#: cps/helper.py:174 cps/helper.py:178 cps/helper.py:182 #, python-format -msgid "Send %(format)s to E-Reader" +msgid "Send %(format)s to eReader" msgstr "" -#: cps/helper.py:225 cps/tasks/convert.py:92 +#: cps/helper.py:222 #, python-format -msgid "%(book)s send to E-Reader" +msgid "%(book)s send to eReader" msgstr "" -#: cps/helper.py:230 +#: cps/helper.py:227 msgid "The requested file could not be read. Maybe wrong permissions?" msgstr "" -#: cps/helper.py:345 +#: cps/helper.py:342 msgid "Read status could not set: {}" msgstr "" -#: cps/helper.py:368 +#: cps/helper.py:365 #, python-format msgid "Deleting bookfolder for book %(id)s failed, path has subfolders: %(path)s" msgstr "" -#: cps/helper.py:374 +#: cps/helper.py:371 #, python-format msgid "Deleting book %(id)s failed: %(message)s" msgstr "" -#: cps/helper.py:385 +#: cps/helper.py:382 #, python-format msgid "Deleting book %(id)s from database only, book path in database not valid: %(path)s" msgstr "" -#: cps/helper.py:450 +#: cps/helper.py:447 #, python-format msgid "Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:522 cps/helper.py:531 +#: cps/helper.py:519 cps/helper.py:528 #, python-format msgid "File %(file)s not found on Google Drive" msgstr "" -#: cps/helper.py:565 +#: cps/helper.py:562 #, python-format msgid "Rename title from: '%(src)s' to '%(dest)s' failed with error: %(error)s" msgstr "" -#: cps/helper.py:585 +#: cps/helper.py:582 msgid "Error in rename file in path: {}" msgstr "" -#: cps/helper.py:603 +#: cps/helper.py:600 #, python-format msgid "Book path %(path)s not found on Google Drive" msgstr "" -#: cps/helper.py:644 cps/web.py:1414 -msgid "Found an existing account for this e-mail address" +#: cps/helper.py:665 +msgid "Found an existing account for this Email address" msgstr "" -#: cps/helper.py:652 +#: cps/helper.py:673 msgid "This username is already taken" msgstr "" -#: cps/helper.py:664 -msgid "Invalid e-mail address format" +#: cps/helper.py:685 +msgid "Invalid Email address format" msgstr "" -#: cps/helper.py:815 +#: cps/helper.py:703 +msgid "Password doesn't comply with password validation rules" +msgstr "" + +#: cps/helper.py:852 msgid "Python module 'advocate' is not installed but is needed for cover uploads" msgstr "" -#: cps/helper.py:825 +#: cps/helper.py:862 msgid "Error Downloading Cover" msgstr "" -#: cps/helper.py:828 +#: cps/helper.py:865 msgid "Cover Format Error" msgstr "" -#: cps/helper.py:831 +#: cps/helper.py:868 msgid "You are not allowed to access localhost or the local network for cover uploads" msgstr "" -#: cps/helper.py:841 +#: cps/helper.py:878 msgid "Failed to create path for cover" msgstr "" -#: cps/helper.py:857 +#: cps/helper.py:894 msgid "Cover-file is not a valid image file, or could not be stored" msgstr "" -#: cps/helper.py:868 +#: cps/helper.py:905 msgid "Only jpg/jpeg/png/webp/bmp files are supported as coverfile" msgstr "" -#: cps/helper.py:880 +#: cps/helper.py:917 msgid "Invalid cover file content" msgstr "" -#: cps/helper.py:884 +#: cps/helper.py:921 msgid "Only jpg/jpeg files are supported as coverfile" msgstr "" -#: cps/helper.py:936 +#: cps/helper.py:973 msgid "Unrar binary file not found" msgstr "" -#: cps/helper.py:947 +#: cps/helper.py:984 msgid "Error executing UnRar" msgstr "" -#: cps/helper.py:1040 +#: cps/helper.py:1077 msgid "Cover" msgstr "" -#: cps/helper.py:1042 cps/templates/admin.html:211 +#: cps/helper.py:1079 cps/templates/admin.html:216 msgid "Queue all books for metadata backup" msgstr "" -#: cps/kobo_auth.py:89 +#: cps/kobo_auth.py:90 msgid "Please access Calibre-Web from non localhost to get valid api_endpoint for kobo device" msgstr "" -#: cps/kobo_auth.py:115 +#: cps/kobo_auth.py:116 msgid "Kobo Setup" msgstr "" @@ -815,9 +825,9 @@ msgstr "" msgid "Register with %(provider)s" msgstr "" -#: cps/oauth_bb.py:138 cps/remotelogin.py:130 cps/web.py:1289 +#: cps/oauth_bb.py:138 cps/remotelogin.py:130 #, python-format -msgid "you are now logged in as: '%(nickname)s'" +msgid "Success! You are now logged in as: %(nickname)s" msgstr "" #: cps/oauth_bb.py:148 @@ -876,12 +886,13 @@ msgstr "" msgid "Google Oauth error: {}" msgstr "" -#: cps/opds.py:287 +#: cps/opds.py:274 msgid "{} Stars" msgstr "" -#: cps/remotelogin.py:62 cps/templates/layout.html:85 -#: cps/templates/login.html:4 cps/templates/login.html:21 cps/web.py:1338 +#: cps/remotelogin.py:62 cps/templates/layout.html:67 +#: cps/templates/layout.html:101 cps/templates/login.html:4 +#: cps/templates/login.html:21 cps/web.py:1333 msgid "Login" msgstr "" @@ -897,149 +908,149 @@ msgstr "" msgid "Success! Please return to your device" msgstr "" -#: cps/render_template.py:40 cps/web.py:405 +#: cps/render_template.py:42 cps/web.py:414 msgid "Books" msgstr "" -#: cps/render_template.py:42 +#: cps/render_template.py:44 msgid "Show recent books" msgstr "" -#: cps/render_template.py:43 cps/templates/index.xml:25 +#: cps/render_template.py:45 cps/templates/index.xml:26 msgid "Hot Books" msgstr "" -#: cps/render_template.py:45 +#: cps/render_template.py:47 msgid "Show Hot Books" msgstr "" -#: cps/render_template.py:47 cps/render_template.py:52 +#: cps/render_template.py:49 cps/render_template.py:54 msgid "Downloaded Books" msgstr "" -#: cps/render_template.py:49 cps/render_template.py:54 +#: cps/render_template.py:51 cps/render_template.py:56 #: cps/templates/user_table.html:167 msgid "Show Downloaded Books" msgstr "" -#: cps/render_template.py:57 cps/templates/index.xml:32 cps/web.py:420 +#: cps/render_template.py:59 cps/templates/index.xml:33 cps/web.py:429 msgid "Top Rated Books" msgstr "" -#: cps/render_template.py:59 cps/templates/user_table.html:161 +#: cps/render_template.py:61 cps/templates/user_table.html:161 msgid "Show Top Rated Books" msgstr "" -#: cps/render_template.py:60 cps/templates/index.xml:54 -#: cps/templates/index.xml:58 cps/web.py:741 +#: cps/render_template.py:62 cps/templates/index.xml:55 +#: cps/templates/index.xml:59 cps/web.py:750 msgid "Read Books" msgstr "" -#: cps/render_template.py:62 -msgid "Show read and unread" +#: cps/render_template.py:64 +msgid "Show Read and Unread" msgstr "" -#: cps/render_template.py:64 cps/templates/index.xml:61 -#: cps/templates/index.xml:65 cps/web.py:744 +#: cps/render_template.py:66 cps/templates/index.xml:62 +#: cps/templates/index.xml:66 cps/web.py:753 msgid "Unread Books" msgstr "" -#: cps/render_template.py:66 +#: cps/render_template.py:68 msgid "Show unread" msgstr "" -#: cps/render_template.py:67 +#: cps/render_template.py:69 msgid "Discover" msgstr "" -#: cps/render_template.py:69 cps/templates/index.xml:50 -#: cps/templates/user_table.html:162 +#: cps/render_template.py:71 cps/templates/index.xml:51 +#: cps/templates/user_table.html:159 cps/templates/user_table.html:162 msgid "Show Random Books" msgstr "" -#: cps/render_template.py:70 cps/templates/book_table.html:67 -#: cps/templates/index.xml:83 cps/web.py:1101 +#: cps/render_template.py:72 cps/templates/book_table.html:67 +#: cps/templates/index.xml:84 cps/web.py:1119 msgid "Categories" msgstr "" -#: cps/render_template.py:72 cps/templates/user_table.html:158 -msgid "Show category selection" +#: cps/render_template.py:74 cps/templates/user_table.html:158 +msgid "Show Category Section" msgstr "" -#: cps/render_template.py:73 cps/templates/book_edit.html:91 -#: cps/templates/book_table.html:68 cps/templates/index.xml:90 -#: cps/templates/search_form.html:69 cps/web.py:997 cps/web.py:1004 +#: cps/render_template.py:75 cps/templates/book_edit.html:91 +#: cps/templates/book_table.html:68 cps/templates/index.xml:91 +#: cps/templates/search_form.html:70 cps/web.py:1009 cps/web.py:1021 msgid "Series" msgstr "" -#: cps/render_template.py:75 cps/templates/user_table.html:157 -msgid "Show series selection" +#: cps/render_template.py:77 cps/templates/user_table.html:157 +msgid "Show Series Section" msgstr "" -#: cps/render_template.py:76 cps/templates/book_table.html:66 -#: cps/templates/index.xml:69 +#: cps/render_template.py:78 cps/templates/book_table.html:66 +#: cps/templates/index.xml:70 msgid "Authors" msgstr "" -#: cps/render_template.py:78 cps/templates/user_table.html:160 -msgid "Show author selection" +#: cps/render_template.py:80 cps/templates/user_table.html:160 +msgid "Show Author Section" msgstr "" -#: cps/render_template.py:80 cps/templates/book_table.html:72 -#: cps/templates/index.xml:76 cps/web.py:968 +#: cps/render_template.py:82 cps/templates/book_table.html:72 +#: cps/templates/index.xml:77 cps/web.py:977 msgid "Publishers" msgstr "" -#: cps/render_template.py:82 cps/templates/user_table.html:163 -msgid "Show publisher selection" +#: cps/render_template.py:84 cps/templates/user_table.html:163 +msgid "Show Publisher Section" msgstr "" -#: cps/render_template.py:83 cps/templates/book_table.html:70 -#: cps/templates/index.xml:97 cps/templates/search_form.html:107 -#: cps/web.py:1073 +#: cps/render_template.py:85 cps/templates/book_table.html:70 +#: cps/templates/index.xml:98 cps/templates/search_form.html:108 +#: cps/web.py:1091 msgid "Languages" msgstr "" -#: cps/render_template.py:86 cps/templates/user_table.html:155 -msgid "Show language selection" +#: cps/render_template.py:88 cps/templates/user_table.html:155 +msgid "Show Language Section" msgstr "" -#: cps/render_template.py:87 cps/templates/index.xml:104 +#: cps/render_template.py:89 cps/templates/index.xml:105 msgid "Ratings" msgstr "" -#: cps/render_template.py:89 cps/templates/user_table.html:164 -msgid "Show ratings selection" +#: cps/render_template.py:91 cps/templates/user_table.html:164 +msgid "Show Ratings Section" msgstr "" -#: cps/render_template.py:90 cps/templates/index.xml:112 +#: cps/render_template.py:92 cps/templates/index.xml:113 msgid "File formats" msgstr "" -#: cps/render_template.py:92 cps/templates/user_table.html:165 -msgid "Show file formats selection" +#: cps/render_template.py:94 cps/templates/user_table.html:165 +msgid "Show File Formats Section" msgstr "" -#: cps/render_template.py:94 cps/web.py:767 +#: cps/render_template.py:96 cps/web.py:776 msgid "Archived Books" msgstr "" -#: cps/render_template.py:96 cps/templates/user_table.html:166 -msgid "Show archived books" +#: cps/render_template.py:98 cps/templates/user_table.html:166 +msgid "Show Archived Books" msgstr "" -#: cps/render_template.py:99 cps/web.py:798 +#: cps/render_template.py:101 cps/web.py:807 msgid "Books List" msgstr "" -#: cps/render_template.py:101 cps/templates/user_table.html:168 +#: cps/render_template.py:103 cps/templates/user_table.html:168 msgid "Show Books List" msgstr "" -#: cps/search.py:48 cps/search.py:392 cps/templates/book_edit.html:236 -#: cps/templates/feed.xml:33 cps/templates/index.xml:11 +#: cps/search.py:48 cps/search.py:399 cps/templates/book_edit.html:236 +#: cps/templates/feed.xml:34 cps/templates/index.xml:12 #: cps/templates/layout.html:46 cps/templates/layout.html:49 -#: cps/templates/search_form.html:226 +#: cps/templates/search_form.html:227 msgid "Search" msgstr "" @@ -1063,14 +1074,14 @@ msgstr "" #: cps/search.py:221 #, python-format -msgid "Read Status = %(status)s" +msgid "Read Status = '%(status)s'" msgstr "" -#: cps/search.py:323 +#: cps/search.py:324 msgid "Error on search for custom columns, please restart Calibre-Web" msgstr "" -#: cps/search.py:342 cps/search.py:374 cps/templates/layout.html:57 +#: cps/search.py:343 cps/search.py:375 cps/templates/layout.html:57 msgid "Advanced Search" msgstr "" @@ -1120,7 +1131,7 @@ msgstr "" msgid "Sorry you are not allowed to remove a book from this shelf" msgstr "" -#: cps/shelf.py:210 cps/templates/layout.html:141 +#: cps/shelf.py:210 cps/templates/layout.html:157 msgid "Create a Shelf" msgstr "" @@ -1145,73 +1156,73 @@ msgstr "" msgid "Change order of Shelf: '%(name)s'" msgstr "" -#: cps/shelf.py:313 +#: cps/shelf.py:316 msgid "Sorry you are not allowed to create a public shelf" msgstr "" -#: cps/shelf.py:330 -#, python-format -msgid "Shelf %(title)s created" -msgstr "" - #: cps/shelf.py:333 #, python-format +msgid "Shelf %(title)s created" +msgstr "" + +#: cps/shelf.py:336 +#, python-format msgid "Shelf %(title)s changed" msgstr "" -#: cps/shelf.py:347 +#: cps/shelf.py:350 msgid "There was an error" msgstr "" -#: cps/shelf.py:369 +#: cps/shelf.py:372 #, python-format msgid "A public shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:380 +#: cps/shelf.py:383 #, python-format msgid "A private shelf with the name '%(title)s' already exists." msgstr "" -#: cps/shelf.py:462 +#: cps/shelf.py:465 #, python-format msgid "Shelf: '%(name)s'" msgstr "" -#: cps/shelf.py:466 +#: cps/shelf.py:469 msgid "Error opening shelf. Shelf does not exist or is not accessible" msgstr "" -#: cps/tasks_status.py:48 cps/templates/layout.html:74 +#: cps/tasks_status.py:46 cps/templates/layout.html:88 #: cps/templates/tasks.html:7 msgid "Tasks" msgstr "" -#: cps/tasks_status.py:64 +#: cps/tasks_status.py:62 msgid "Waiting" msgstr "" -#: cps/tasks_status.py:66 +#: cps/tasks_status.py:64 msgid "Failed" msgstr "" -#: cps/tasks_status.py:68 +#: cps/tasks_status.py:66 msgid "Started" msgstr "" -#: cps/tasks_status.py:70 +#: cps/tasks_status.py:68 msgid "Finished" msgstr "" -#: cps/tasks_status.py:72 +#: cps/tasks_status.py:70 msgid "Ended" msgstr "" -#: cps/tasks_status.py:74 +#: cps/tasks_status.py:72 msgid "Cancelled" msgstr "" -#: cps/tasks_status.py:76 +#: cps/tasks_status.py:74 msgid "Unknown Status" msgstr "" @@ -1244,146 +1255,177 @@ msgstr "" msgid "No release information available" msgstr "" -#: cps/templates/index.html:6 cps/web.py:432 +#: cps/templates/index.html:6 cps/web.py:441 msgid "Discover (Random Books)" msgstr "" -#: cps/web.py:468 +#: cps/web.py:477 msgid "Hot Books (Most Downloaded)" msgstr "" -#: cps/web.py:499 +#: cps/web.py:508 #, python-format msgid "Downloaded books by %(user)s" msgstr "" -#: cps/web.py:532 +#: cps/web.py:541 #, python-format msgid "Author: %(name)s" msgstr "" -#: cps/web.py:568 +#: cps/web.py:577 #, python-format msgid "Publisher: %(name)s" msgstr "" -#: cps/web.py:596 +#: cps/web.py:605 #, python-format msgid "Series: %(serie)s" msgstr "" -#: cps/web.py:611 +#: cps/web.py:620 msgid "Rating: None" msgstr "" -#: cps/web.py:620 +#: cps/web.py:629 #, python-format msgid "Rating: %(rating)s stars" msgstr "" -#: cps/web.py:638 +#: cps/web.py:645 #, python-format msgid "File format: %(format)s" msgstr "" -#: cps/web.py:675 +#: cps/web.py:682 #, python-format msgid "Category: %(name)s" msgstr "" -#: cps/web.py:702 +#: cps/web.py:711 #, python-format msgid "Language: %(name)s" msgstr "" -#: cps/templates/admin.html:16 cps/web.py:940 +#: cps/templates/admin.html:16 cps/web.py:949 msgid "Downloads" msgstr "" -#: cps/web.py:1033 +#: cps/web.py:1051 msgid "Ratings list" msgstr "" -#: cps/web.py:1060 +#: cps/web.py:1078 msgid "File formats list" msgstr "" -#: cps/web.py:1202 +#: cps/web.py:1233 +msgid "Please configure the SMTP mail settings first..." +msgstr "" + +#: cps/web.py:1240 #, python-format -msgid "Book successfully queued for sending to %(kindlemail)s" +msgid "Success! Book queued for sending to %(eReadermail)s" msgstr "" -#: cps/web.py:1206 +#: cps/web.py:1243 #, python-format -msgid "Oops! There was an error sending this book: %(res)s" +msgid "Oops! There was an error sending book: %(res)s" msgstr "" -#: cps/web.py:1208 -msgid "Please update your profile with a valid Send to Kindle E-mail Address." +#: cps/web.py:1245 +msgid "Oops! Please update your profile with a valid eReader Email." msgstr "" -#: cps/web.py:1225 -msgid "E-Mail server is not configured, please contact your administrator!" +#: cps/web.py:1261 +msgid "Please wait one minute to register next user" msgstr "" -#: cps/templates/layout.html:86 cps/templates/register.html:17 cps/web.py:1226 -#: cps/web.py:1233 cps/web.py:1239 cps/web.py:1258 cps/web.py:1263 -#: cps/web.py:1269 +#: cps/templates/layout.html:68 cps/templates/layout.html:102 +#: cps/templates/login.html:27 cps/templates/register.html:17 cps/web.py:1262 +#: cps/web.py:1267 cps/web.py:1271 cps/web.py:1277 cps/web.py:1297 +#: cps/web.py:1301 cps/web.py:1314 cps/web.py:1317 msgid "Register" msgstr "" -#: cps/web.py:1260 -msgid "Your e-mail is not allowed to register" +#: cps/web.py:1266 cps/web.py:1313 +msgid "Oops! Email server is not configured, please contact your administrator." msgstr "" -#: cps/web.py:1264 -msgid "Confirmation e-mail was send to your e-mail account." +#: cps/web.py:1299 +msgid "Oops! Your Email is not allowed." msgstr "" -#: cps/web.py:1278 +#: cps/web.py:1302 +msgid "Success! Confirmation Email has been sent." +msgstr "" + +#: cps/web.py:1348 cps/web.py:1366 msgid "Cannot activate LDAP authentication" msgstr "" -#: cps/web.py:1297 +#: cps/web.py:1360 +msgid "Please wait one minute before next login" +msgstr "" + +#: cps/web.py:1376 +#, python-format +msgid "you are now logged in as: '%(nickname)s'" +msgstr "" + +#: cps/web.py:1383 #, python-format msgid "Fallback Login as: '%(nickname)s', LDAP Server not reachable, or user not known" msgstr "" -#: cps/web.py:1303 +#: cps/web.py:1388 #, python-format msgid "Could not login: %(message)s" msgstr "" -#: cps/web.py:1307 cps/web.py:1332 +#: cps/web.py:1392 cps/web.py:1417 msgid "Wrong Username or Password" msgstr "" -#: cps/web.py:1314 +#: cps/web.py:1399 msgid "New Password was send to your email address" msgstr "" -#: cps/web.py:1320 +#: cps/web.py:1403 +msgid "An unknown error occurred. Please try again later." +msgstr "" + +#: cps/web.py:1405 msgid "Please enter valid username to reset password" msgstr "" -#: cps/web.py:1327 +#: cps/web.py:1413 #, python-format msgid "You are now logged in as: '%(nickname)s'" msgstr "" -#: cps/web.py:1394 cps/web.py:1443 +#: cps/web.py:1471 cps/web.py:1521 #, python-format -msgid "%(name)s's profile" +msgid "%(name)s's Profile" msgstr "" -#: cps/web.py:1410 -msgid "Profile updated" +#: cps/web.py:1487 +msgid "Success! Profile Updated" +msgstr "" + +#: cps/web.py:1491 +msgid "Oops! An account already exists for this Email." msgstr "" #: cps/services/gmail.py:58 msgid "Found no valid gmail.json file with OAuth information" msgstr "" +#: cps/tasks/convert.py:92 +#, python-format +msgid "%(book)s send to E-Reader" +msgstr "" + #: cps/tasks/convert.py:153 #, python-format msgid "Calibre ebook-convert %(tool)s not found" @@ -1426,34 +1468,34 @@ msgstr "" msgid "Reconnecting Calibre database" msgstr "" -#: cps/tasks/mail.py:265 +#: cps/tasks/mail.py:269 msgid "E-mail" msgstr "" -#: cps/tasks/metadata_backup.py:47 +#: cps/tasks/metadata_backup.py:46 msgid "Backing up Metadata" msgstr "" -#: cps/tasks/thumbnail.py:95 +#: cps/tasks/thumbnail.py:96 #, python-format msgid "Generated %(count)s cover thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:222 cps/tasks/thumbnail.py:435 -#: cps/tasks/thumbnail.py:503 +#: cps/tasks/thumbnail.py:230 cps/tasks/thumbnail.py:443 +#: cps/tasks/thumbnail.py:511 msgid "Cover Thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:281 +#: cps/tasks/thumbnail.py:289 msgid "Generated {0} series thumbnails" msgstr "" -#: cps/tasks/thumbnail.py:446 +#: cps/tasks/thumbnail.py:454 msgid "Clearing cover thumbnail cache" msgstr "" #: cps/tasks/upload.py:38 cps/templates/admin.html:20 -#: cps/templates/layout.html:67 cps/templates/user_table.html:145 +#: cps/templates/layout.html:81 cps/templates/user_table.html:145 msgid "Upload" msgstr "" @@ -1469,14 +1511,14 @@ msgstr "" #: cps/templates/admin.html:14 cps/templates/register.html:14 #: cps/templates/user_edit.html:15 cps/templates/user_table.html:135 -msgid "E-mail Address" +msgid "Email" msgstr "" #: cps/templates/admin.html:15 cps/templates/user_edit.html:28 -msgid "Send to E-Reader E-mail Address" +msgid "Send to eReader Email" msgstr "" -#: cps/templates/admin.html:17 cps/templates/layout.html:77 +#: cps/templates/admin.html:17 cps/templates/layout.html:91 #: cps/templates/user_table.html:143 msgid "Admin" msgstr "" @@ -1486,8 +1528,8 @@ msgstr "" msgid "Password" msgstr "" -#: cps/templates/admin.html:22 cps/templates/detail.html:19 -#: cps/templates/detail.html:28 cps/templates/shelf.html:8 +#: cps/templates/admin.html:22 cps/templates/detail.html:20 +#: cps/templates/detail.html:33 cps/templates/shelf.html:8 #: cps/templates/user_table.html:146 msgid "Download" msgstr "" @@ -1512,16 +1554,12 @@ msgstr "" msgid "Public Shelf" msgstr "" -#: cps/templates/admin.html:53 -msgid "Add New User" -msgstr "" - #: cps/templates/admin.html:55 msgid "Import LDAP Users" msgstr "" #: cps/templates/admin.html:62 -msgid "E-mail Server Settings" +msgid "Email Server Settings" msgstr "" #: cps/templates/admin.html:67 cps/templates/email_edit.html:31 @@ -1542,11 +1580,11 @@ msgstr "" #: cps/templates/admin.html:83 cps/templates/admin.html:94 #: cps/templates/email_edit.html:55 -msgid "From E-mail" +msgid "From Email" msgstr "" #: cps/templates/admin.html:90 -msgid "E-Mail Service" +msgid "Email Service" msgstr "" #: cps/templates/admin.html:91 @@ -1618,102 +1656,104 @@ msgid "Scheduled Tasks" msgstr "" #: cps/templates/admin.html:170 cps/templates/schedule_edit.html:12 -msgid "Time at which tasks start to run" +#: cps/templates/tasks.html:18 +msgid "Start Time" msgstr "" #: cps/templates/admin.html:174 cps/templates/schedule_edit.html:20 -msgid "Maximum tasks duration" +msgid "Maximum Duration" msgstr "" -#: cps/templates/admin.html:178 -msgid "Generate book cover thumbnails" +#: cps/templates/admin.html:178 cps/templates/schedule_edit.html:29 +msgid "Generate Thumbnails" msgstr "" #: cps/templates/admin.html:182 msgid "Generate series cover thumbnails" msgstr "" -#: cps/templates/admin.html:186 cps/templates/schedule_edit.html:37 -msgid "Reconnect to Calibre Library" -msgstr "" - -#: cps/templates/admin.html:193 -msgid "Refresh Thumbnail Cover Cache" -msgstr "" - -#: cps/templates/admin.html:199 -msgid "Administration" -msgstr "" - -#: cps/templates/admin.html:200 -msgid "Download Debug Package" -msgstr "" - -#: cps/templates/admin.html:201 -msgid "View Logs" -msgstr "" - -#: cps/templates/admin.html:204 +#: cps/templates/admin.html:186 cps/templates/admin.html:208 +#: cps/templates/schedule_edit.html:37 msgid "Reconnect Calibre Database" msgstr "" -#: cps/templates/admin.html:207 +#: cps/templates/admin.html:190 cps/templates/schedule_edit.html:41 +msgid "Generate Metadata Backup Files" +msgstr "" + +#: cps/templates/admin.html:197 +msgid "Refresh Thumbnail Cache" +msgstr "" + +#: cps/templates/admin.html:203 +msgid "Administration" +msgstr "" + +#: cps/templates/admin.html:204 +msgid "Download Debug Package" +msgstr "" + +#: cps/templates/admin.html:205 +msgid "View Logs" +msgstr "" + +#: cps/templates/admin.html:211 msgid "Restart" msgstr "" -#: cps/templates/admin.html:208 +#: cps/templates/admin.html:212 msgid "Shutdown" msgstr "" -#: cps/templates/admin.html:216 +#: cps/templates/admin.html:221 msgid "Version Information" msgstr "" -#: cps/templates/admin.html:220 +#: cps/templates/admin.html:225 msgid "Version" msgstr "" -#: cps/templates/admin.html:221 +#: cps/templates/admin.html:226 msgid "Details" msgstr "" -#: cps/templates/admin.html:227 -msgid "Current version" +#: cps/templates/admin.html:232 +msgid "Current Version" msgstr "" -#: cps/templates/admin.html:234 +#: cps/templates/admin.html:239 msgid "Check for Update" msgstr "" -#: cps/templates/admin.html:235 +#: cps/templates/admin.html:240 msgid "Perform Update" msgstr "" -#: cps/templates/admin.html:248 +#: cps/templates/admin.html:253 msgid "Are you sure you want to restart?" msgstr "" -#: cps/templates/admin.html:253 cps/templates/admin.html:267 -#: cps/templates/admin.html:287 cps/templates/config_db.html:70 +#: cps/templates/admin.html:258 cps/templates/admin.html:272 +#: cps/templates/admin.html:292 cps/templates/config_db.html:70 msgid "OK" msgstr "" -#: cps/templates/admin.html:254 cps/templates/admin.html:268 +#: cps/templates/admin.html:259 cps/templates/admin.html:273 #: cps/templates/book_edit.html:214 cps/templates/book_table.html:127 -#: cps/templates/config_db.html:54 cps/templates/config_edit.html:359 +#: cps/templates/config_db.html:54 cps/templates/config_edit.html:410 #: cps/templates/config_view_edit.html:175 cps/templates/modal_dialogs.html:64 #: cps/templates/modal_dialogs.html:99 cps/templates/modal_dialogs.html:117 -#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:41 +#: cps/templates/modal_dialogs.html:135 cps/templates/schedule_edit.html:45 #: cps/templates/shelf_edit.html:27 cps/templates/tasks.html:46 #: cps/templates/user_edit.html:144 msgid "Cancel" msgstr "" -#: cps/templates/admin.html:266 +#: cps/templates/admin.html:271 msgid "Are you sure you want to shutdown?" msgstr "" -#: cps/templates/admin.html:278 +#: cps/templates/admin.html:283 msgid "Updating, please do not reload this page" msgstr "" @@ -1803,7 +1843,7 @@ msgid "Author" msgstr "" #: cps/templates/book_edit.html:68 cps/templates/book_edit.html:276 -#: cps/templates/book_edit.html:291 cps/templates/search_form.html:153 +#: cps/templates/book_edit.html:291 cps/templates/search_form.html:154 msgid "Description" msgstr "" @@ -1828,7 +1868,7 @@ msgstr "" msgid "Add Identifier" msgstr "" -#: cps/templates/book_edit.html:87 cps/templates/search_form.html:51 +#: cps/templates/book_edit.html:87 cps/templates/search_form.html:52 msgid "Tags" msgstr "" @@ -1853,23 +1893,23 @@ msgid "Published Date" msgstr "" #: cps/templates/book_edit.html:122 cps/templates/book_edit.html:273 -#: cps/templates/book_edit.html:290 cps/templates/detail.html:165 -#: cps/templates/search_form.html:16 +#: cps/templates/book_edit.html:290 cps/templates/detail.html:192 +#: cps/templates/listenmp3.html:102 cps/templates/search_form.html:16 msgid "Publisher" msgstr "" -#: cps/templates/book_edit.html:126 cps/templates/detail.html:132 -#: cps/templates/user_edit.html:33 +#: cps/templates/book_edit.html:126 cps/templates/detail.html:157 +#: cps/templates/listenmp3.html:69 cps/templates/user_edit.html:33 msgid "Language" msgstr "" -#: cps/templates/book_edit.html:136 cps/templates/search_form.html:45 -#: cps/templates/search_form.html:164 +#: cps/templates/book_edit.html:136 cps/templates/search_form.html:46 +#: cps/templates/search_form.html:165 msgid "Yes" msgstr "" -#: cps/templates/book_edit.html:137 cps/templates/search_form.html:46 -#: cps/templates/search_form.html:165 +#: cps/templates/book_edit.html:137 cps/templates/search_form.html:47 +#: cps/templates/search_form.html:166 msgid "No" msgstr "" @@ -1886,8 +1926,8 @@ msgid "Fetch Metadata" msgstr "" #: cps/templates/book_edit.html:213 cps/templates/config_db.html:53 -#: cps/templates/config_edit.html:358 cps/templates/config_view_edit.html:174 -#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:40 +#: cps/templates/config_edit.html:409 cps/templates/config_view_edit.html:174 +#: cps/templates/email_edit.html:65 cps/templates/schedule_edit.html:44 #: cps/templates/shelf_edit.html:25 cps/templates/shelf_order.html:41 #: cps/templates/user_edit.html:142 msgid "Save" @@ -1909,8 +1949,8 @@ msgstr "" msgid "Loading..." msgstr "" -#: cps/templates/book_edit.html:251 cps/templates/layout.html:64 -#: cps/templates/layout.html:187 cps/templates/modal_dialogs.html:34 +#: cps/templates/book_edit.html:251 cps/templates/layout.html:78 +#: cps/templates/layout.html:203 cps/templates/modal_dialogs.html:34 #: cps/templates/user_edit.html:163 msgid "Close" msgstr "" @@ -2135,7 +2175,7 @@ msgid "Enable Uploads" msgstr "" #: cps/templates/config_edit.html:108 -msgid "(Please ensure users having also upload rights)" +msgid "(Please ensure that users also have upload permissions)" msgstr "" #: cps/templates/config_edit.html:112 @@ -2151,7 +2191,7 @@ msgid "Enable Public Registration" msgstr "" #: cps/templates/config_edit.html:127 -msgid "Use E-Mail as Username" +msgid "Use Email as Username" msgstr "" #: cps/templates/config_edit.html:132 @@ -2341,6 +2381,50 @@ msgstr "" msgid "Location of Unrar binary" msgstr "" +#: cps/templates/config_edit.html:361 +msgid "Security Settings" +msgstr "" + +#: cps/templates/config_edit.html:369 +msgid "Limit failed login attempts" +msgstr "" + +#: cps/templates/config_edit.html:372 +msgid "Session protection" +msgstr "" + +#: cps/templates/config_edit.html:374 +msgid "Basic" +msgstr "" + +#: cps/templates/config_edit.html:375 +msgid "Strong" +msgstr "" + +#: cps/templates/config_edit.html:380 +msgid "User Password policy" +msgstr "" + +#: cps/templates/config_edit.html:384 +msgid "Minimum password length" +msgstr "" + +#: cps/templates/config_edit.html:389 +msgid "Enforce number" +msgstr "" + +#: cps/templates/config_edit.html:393 +msgid "Enforce lowercase characters" +msgstr "" + +#: cps/templates/config_edit.html:397 +msgid "Enforce uppercase characters" +msgstr "" + +#: cps/templates/config_edit.html:401 +msgid "Enforce special characters" +msgstr "" + #: cps/templates/config_view_edit.html:17 msgid "View Configuration" msgstr "" @@ -2353,7 +2437,7 @@ msgstr "" msgid "No. of Authors to Display Before Hiding (0=Disable Hiding)" msgstr "" -#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:113 +#: cps/templates/config_view_edit.html:40 cps/templates/readcbr.html:101 msgid "Theme" msgstr "" @@ -2442,79 +2526,81 @@ msgstr "" msgid "Add Allowed/Denied custom column values" msgstr "" -#: cps/templates/detail.html:61 cps/templates/detail.html:70 +#: cps/templates/detail.html:77 cps/templates/detail.html:91 msgid "Read in Browser" msgstr "" -#: cps/templates/detail.html:78 cps/templates/detail.html:95 +#: cps/templates/detail.html:100 cps/templates/detail.html:120 msgid "Listen in Browser" msgstr "" -#: cps/templates/detail.html:125 +#: cps/templates/detail.html:150 cps/templates/listenmp3.html:62 #, python-format msgid "Book %(index)s of %(range)s" msgstr "" -#: cps/templates/detail.html:174 +#: cps/templates/detail.html:201 cps/templates/listenmp3.html:111 msgid "Published" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:250 cps/templates/listenmp3.html:158 msgid "Mark As Unread" msgstr "" -#: cps/templates/detail.html:222 +#: cps/templates/detail.html:251 cps/templates/listenmp3.html:158 msgid "Mark As Read" msgstr "" -#: cps/templates/detail.html:223 +#: cps/templates/detail.html:253 cps/templates/listenmp3.html:159 msgid "Read" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:263 cps/templates/listenmp3.html:166 msgid "Restore from archive" msgstr "" -#: cps/templates/detail.html:232 +#: cps/templates/detail.html:264 cps/templates/listenmp3.html:166 msgid "Add to archive" msgstr "" -#: cps/templates/detail.html:233 +#: cps/templates/detail.html:266 cps/templates/listenmp3.html:167 msgid "Archived" msgstr "" -#: cps/templates/detail.html:244 +#: cps/templates/detail.html:277 cps/templates/listenmp3.html:177 msgid "Description:" msgstr "" -#: cps/templates/detail.html:257 cps/templates/search.html:16 +#: cps/templates/detail.html:292 cps/templates/listenmp3.html:190 +#: cps/templates/search.html:16 msgid "Add to shelf" msgstr "" -#: cps/templates/detail.html:268 cps/templates/detail.html:285 -#: cps/templates/feed.xml:79 cps/templates/layout.html:138 +#: cps/templates/detail.html:304 cps/templates/detail.html:323 +#: cps/templates/feed.xml:81 cps/templates/layout.html:154 +#: cps/templates/listenmp3.html:201 cps/templates/listenmp3.html:218 #: cps/templates/search.html:22 msgid "(Public)" msgstr "" -#: cps/templates/detail.html:299 +#: cps/templates/detail.html:339 msgid "Edit Metadata" msgstr "" #: cps/templates/email_edit.html:13 -msgid "Choose Server Type" +msgid "Email Account Type" msgstr "" #: cps/templates/email_edit.html:15 -msgid "Use Standard E-Mail Account" +msgid "Standard Email Account" msgstr "" #: cps/templates/email_edit.html:16 -msgid "Gmail Account with OAuth2 Verification" +msgid "Gmail Account" msgstr "" #: cps/templates/email_edit.html:22 -msgid "Setup Gmail Account as E-Mail Server" +msgid "Setup Gmail Account" msgstr "" #: cps/templates/email_edit.html:24 @@ -2538,10 +2624,10 @@ msgid "Attachment Size Limit" msgstr "" #: cps/templates/email_edit.html:66 -msgid "Save and Send Test E-mail" +msgid "Save and Send Test Email" msgstr "" -#: cps/templates/email_edit.html:70 cps/templates/layout.html:30 +#: cps/templates/email_edit.html:70 cps/templates/layout.html:26 #: cps/templates/shelf_order.html:42 cps/templates/user_table.html:174 msgid "Back" msgstr "" @@ -2567,12 +2653,12 @@ msgstr "" msgid "Denied Domains (Blacklist)" msgstr "" -#: cps/templates/feed.xml:21 cps/templates/layout.html:171 +#: cps/templates/feed.xml:22 cps/templates/layout.html:187 msgid "Next" msgstr "" #: cps/templates/generate_kobo_auth_url.html:6 -msgid "Open the .kobo/Kobo eReader.conf file in a text editor and add (or edit):" +msgid "Open the .kobo/Kobo/Kobo eReader.conf file in a text editor and add (or edit):" msgstr "" #: cps/templates/generate_kobo_auth_url.html:11 @@ -2583,19 +2669,19 @@ msgstr "" msgid "List" msgstr "" -#: cps/templates/http_error.html:31 +#: cps/templates/http_error.html:34 msgid "Calibre-Web Instance is unconfigured, please contact your administrator" msgstr "" -#: cps/templates/http_error.html:41 +#: cps/templates/http_error.html:44 msgid "Create Issue" msgstr "" -#: cps/templates/http_error.html:48 +#: cps/templates/http_error.html:51 msgid "Return to Home" msgstr "" -#: cps/templates/http_error.html:50 +#: cps/templates/http_error.html:53 msgid "Logout User" msgstr "" @@ -2625,80 +2711,80 @@ msgstr "" msgid "Sort descending according to series index" msgstr "" -#: cps/templates/index.xml:6 +#: cps/templates/index.xml:7 msgid "Start" msgstr "" -#: cps/templates/index.xml:18 +#: cps/templates/index.xml:19 msgid "Alphabetical Books" msgstr "" -#: cps/templates/index.xml:22 +#: cps/templates/index.xml:23 msgid "Books sorted alphabetically" msgstr "" -#: cps/templates/index.xml:29 +#: cps/templates/index.xml:30 msgid "Popular publications from this catalog based on Downloads." msgstr "" -#: cps/templates/index.xml:36 +#: cps/templates/index.xml:37 msgid "Popular publications from this catalog based on Rating." msgstr "" -#: cps/templates/index.xml:39 +#: cps/templates/index.xml:40 msgid "Recently added Books" msgstr "" -#: cps/templates/index.xml:43 +#: cps/templates/index.xml:44 msgid "The latest Books" msgstr "" -#: cps/templates/index.xml:46 +#: cps/templates/index.xml:47 msgid "Random Books" msgstr "" -#: cps/templates/index.xml:73 +#: cps/templates/index.xml:74 msgid "Books ordered by Author" msgstr "" -#: cps/templates/index.xml:80 +#: cps/templates/index.xml:81 msgid "Books ordered by publisher" msgstr "" -#: cps/templates/index.xml:87 +#: cps/templates/index.xml:88 msgid "Books ordered by category" msgstr "" -#: cps/templates/index.xml:94 +#: cps/templates/index.xml:95 msgid "Books ordered by series" msgstr "" -#: cps/templates/index.xml:101 +#: cps/templates/index.xml:102 msgid "Books ordered by Languages" msgstr "" -#: cps/templates/index.xml:108 +#: cps/templates/index.xml:109 msgid "Books ordered by Rating" msgstr "" -#: cps/templates/index.xml:116 +#: cps/templates/index.xml:117 msgid "Books ordered by file formats" msgstr "" -#: cps/templates/index.xml:119 cps/templates/layout.html:136 -#: cps/templates/search_form.html:87 +#: cps/templates/index.xml:120 cps/templates/layout.html:152 +#: cps/templates/search_form.html:88 msgid "Shelves" msgstr "" -#: cps/templates/index.xml:123 +#: cps/templates/index.xml:124 msgid "Books organized in shelves" msgstr "" -#: cps/templates/layout.html:30 +#: cps/templates/layout.html:26 cps/templates/login.html:30 msgid "Home" msgstr "" -#: cps/templates/layout.html:36 +#: cps/templates/layout.html:32 msgid "Toggle Navigation" msgstr "" @@ -2706,48 +2792,48 @@ msgstr "" msgid "Search Library" msgstr "" -#: cps/templates/layout.html:64 cps/templates/layout.html:118 -msgid "Uploading..." -msgstr "" - -#: cps/templates/layout.html:64 -msgid "Error" -msgstr "" - -#: cps/templates/layout.html:64 -msgid "Upload done, processing, please wait..." -msgstr "" - -#: cps/templates/layout.html:77 cps/templates/read.html:72 -#: cps/templates/readcbr.html:84 cps/templates/readcbr.html:108 -msgid "Settings" -msgstr "" - -#: cps/templates/layout.html:79 +#: cps/templates/layout.html:65 cps/templates/layout.html:94 msgid "Account" msgstr "" -#: cps/templates/layout.html:81 +#: cps/templates/layout.html:71 cps/templates/layout.html:96 msgid "Logout" msgstr "" -#: cps/templates/layout.html:119 +#: cps/templates/layout.html:78 cps/templates/layout.html:134 +msgid "Uploading..." +msgstr "" + +#: cps/templates/layout.html:78 +msgid "Error" +msgstr "" + +#: cps/templates/layout.html:78 +msgid "Upload done, processing, please wait..." +msgstr "" + +#: cps/templates/layout.html:91 cps/templates/read.html:76 +#: cps/templates/readcbr.html:70 cps/templates/readcbr.html:96 +msgid "Settings" +msgstr "" + +#: cps/templates/layout.html:135 msgid "Please do not refresh the page" msgstr "" -#: cps/templates/layout.html:129 +#: cps/templates/layout.html:145 msgid "Browse" msgstr "" -#: cps/templates/layout.html:142 cps/templates/stats.html:3 +#: cps/templates/layout.html:158 cps/templates/stats.html:3 msgid "About" msgstr "" -#: cps/templates/layout.html:156 +#: cps/templates/layout.html:172 msgid "Previous" msgstr "" -#: cps/templates/layout.html:183 +#: cps/templates/layout.html:199 msgid "Book Details" msgstr "" @@ -2763,7 +2849,7 @@ msgstr "" msgid "Forgot Password?" msgstr "" -#: cps/templates/login.html:26 +#: cps/templates/login.html:34 msgid "Log in with Magic Link" msgstr "" @@ -2871,135 +2957,159 @@ msgstr "" msgid "epub Reader" msgstr "" -#: cps/templates/read.html:77 cps/templates/readcbr.html:116 +#: cps/templates/read.html:81 cps/templates/readcbr.html:104 msgid "Light" msgstr "" -#: cps/templates/read.html:78 cps/templates/readcbr.html:117 +#: cps/templates/read.html:82 cps/templates/readcbr.html:105 msgid "Dark" msgstr "" -#: cps/templates/read.html:79 +#: cps/templates/read.html:83 msgid "Sepia" msgstr "" -#: cps/templates/read.html:80 +#: cps/templates/read.html:84 msgid "Black" msgstr "" -#: cps/templates/read.html:84 +#: cps/templates/read.html:88 msgid "Reflow text when sidebars are open." msgstr "" -#: cps/templates/readcbr.html:7 +#: cps/templates/read.html:93 +msgid "Font Sizes" +msgstr "" + +#: cps/templates/readcbr.html:8 msgid "Comic Reader" msgstr "" -#: cps/templates/readcbr.html:89 +#: cps/templates/readcbr.html:75 msgid "Keyboard Shortcuts" msgstr "" -#: cps/templates/readcbr.html:92 +#: cps/templates/readcbr.html:78 msgid "Previous Page" msgstr "" -#: cps/templates/readcbr.html:93 cps/templates/readcbr.html:162 +#: cps/templates/readcbr.html:79 cps/templates/readcbr.html:159 msgid "Next Page" msgstr "" -#: cps/templates/readcbr.html:94 +#: cps/templates/readcbr.html:80 +msgid "Single Page Display" +msgstr "" + +#: cps/templates/readcbr.html:81 +msgid "Long Strip Display" +msgstr "" + +#: cps/templates/readcbr.html:82 msgid "Scale to Best" msgstr "" -#: cps/templates/readcbr.html:95 +#: cps/templates/readcbr.html:83 msgid "Scale to Width" msgstr "" -#: cps/templates/readcbr.html:96 +#: cps/templates/readcbr.html:84 msgid "Scale to Height" msgstr "" -#: cps/templates/readcbr.html:97 +#: cps/templates/readcbr.html:85 msgid "Scale to Native" msgstr "" -#: cps/templates/readcbr.html:98 +#: cps/templates/readcbr.html:86 msgid "Rotate Right" msgstr "" -#: cps/templates/readcbr.html:99 +#: cps/templates/readcbr.html:87 msgid "Rotate Left" msgstr "" -#: cps/templates/readcbr.html:100 +#: cps/templates/readcbr.html:88 msgid "Flip Image" msgstr "" -#: cps/templates/readcbr.html:122 +#: cps/templates/readcbr.html:110 +msgid "Display" +msgstr "" + +#: cps/templates/readcbr.html:113 +msgid "Single Page" +msgstr "" + +#: cps/templates/readcbr.html:114 +msgid "Long Strip" +msgstr "" + +#: cps/templates/readcbr.html:119 msgid "Scale" msgstr "" -#: cps/templates/readcbr.html:125 +#: cps/templates/readcbr.html:122 msgid "Best" msgstr "" -#: cps/templates/readcbr.html:126 +#: cps/templates/readcbr.html:123 msgid "Width" msgstr "" -#: cps/templates/readcbr.html:127 +#: cps/templates/readcbr.html:124 msgid "Height" msgstr "" -#: cps/templates/readcbr.html:128 +#: cps/templates/readcbr.html:125 msgid "Native" msgstr "" -#: cps/templates/readcbr.html:133 +#: cps/templates/readcbr.html:130 msgid "Rotate" msgstr "" -#: cps/templates/readcbr.html:144 +#: cps/templates/readcbr.html:141 msgid "Flip" msgstr "" -#: cps/templates/readcbr.html:147 +#: cps/templates/readcbr.html:144 msgid "Horizontal" msgstr "" -#: cps/templates/readcbr.html:148 +#: cps/templates/readcbr.html:145 msgid "Vertical" msgstr "" -#: cps/templates/readcbr.html:153 +#: cps/templates/readcbr.html:150 msgid "Direction" msgstr "" -#: cps/templates/readcbr.html:156 +#: cps/templates/readcbr.html:153 msgid "Left to Right" msgstr "" -#: cps/templates/readcbr.html:157 +#: cps/templates/readcbr.html:154 msgid "Right to Left" msgstr "" -#: cps/templates/readcbr.html:165 +#: cps/templates/readcbr.html:162 msgid "Reset to Top" msgstr "" -#: cps/templates/readcbr.html:166 +#: cps/templates/readcbr.html:163 msgid "Remember Position" msgstr "" -#: cps/templates/readcbr.html:171 +#: cps/templates/readcbr.html:168 msgid "Scrollbar" msgstr "" -#: cps/templates/readcbr.html:174 +#: cps/templates/readcbr.html:171 msgid "Show" msgstr "" -#: cps/templates/readcbr.html:175 +#: cps/templates/readcbr.html:172 msgid "Hide" msgstr "" @@ -3007,7 +3117,7 @@ msgstr "" msgid "DJVU Reader" msgstr "" -#: cps/templates/readpdf.html:29 +#: cps/templates/readpdf.html:32 msgid "PDF Reader" msgstr "" @@ -3024,7 +3134,7 @@ msgid "Choose a username" msgstr "" #: cps/templates/register.html:15 -msgid "Your email address" +msgid "Your Email" msgstr "" #: cps/templates/remote_login.html:5 @@ -3043,10 +3153,6 @@ msgstr "" msgid "This verification link will expire in 10 minutes." msgstr "" -#: cps/templates/schedule_edit.html:29 -msgid "Generate Book Cover Thumbnails" -msgstr "" - #: cps/templates/schedule_edit.html:33 msgid "Generate Series Cover Thumbnails" msgstr "" @@ -3071,43 +3177,51 @@ msgstr "" msgid "Published Date To" msgstr "" -#: cps/templates/search_form.html:59 +#: cps/templates/search_form.html:44 +msgid "Any" +msgstr "" + +#: cps/templates/search_form.html:45 +msgid "Empty" +msgstr "" + +#: cps/templates/search_form.html:60 msgid "Exclude Tags" msgstr "" -#: cps/templates/search_form.html:77 +#: cps/templates/search_form.html:78 msgid "Exclude Series" msgstr "" -#: cps/templates/search_form.html:95 +#: cps/templates/search_form.html:96 msgid "Exclude Shelves" msgstr "" -#: cps/templates/search_form.html:115 +#: cps/templates/search_form.html:116 msgid "Exclude Languages" msgstr "" -#: cps/templates/search_form.html:126 +#: cps/templates/search_form.html:127 msgid "Extensions" msgstr "" -#: cps/templates/search_form.html:134 +#: cps/templates/search_form.html:135 msgid "Exclude Extensions" msgstr "" -#: cps/templates/search_form.html:144 +#: cps/templates/search_form.html:145 msgid "Rating Above" msgstr "" -#: cps/templates/search_form.html:148 +#: cps/templates/search_form.html:149 msgid "Rating Below" msgstr "" -#: cps/templates/search_form.html:180 +#: cps/templates/search_form.html:181 msgid "From:" msgstr "" -#: cps/templates/search_form.html:190 +#: cps/templates/search_form.html:191 msgid "To:" msgstr "" @@ -3199,10 +3313,6 @@ msgstr "" msgid "Run Time" msgstr "" -#: cps/templates/tasks.html:18 -msgid "Start Time" -msgstr "" - #: cps/templates/tasks.html:20 msgid "Actions" msgstr "" @@ -3276,15 +3386,15 @@ msgid "Enter Username" msgstr "" #: cps/templates/user_table.html:135 -msgid "Enter E-mail Address" +msgid "Enter Email" msgstr "" #: cps/templates/user_table.html:136 -msgid "Enter E-Reader E-mail Address" +msgid "Enter eReader Email" msgstr "" #: cps/templates/user_table.html:136 -msgid "E-Reader E-mail" +msgid "eReader Email" msgstr "" #: cps/templates/user_table.html:137 @@ -3344,10 +3454,6 @@ msgid "Sync selected Shelves with Kobo" msgstr "" #: cps/templates/user_table.html:156 -msgid "Show read/unread selection" -msgstr "" - -#: cps/templates/user_table.html:159 -msgid "Show random books" +msgid "Show Read/Unread Section" msgstr "" diff --git a/optional-requirements.txt b/optional-requirements.txt index 57a4038f..6763eaff 100644 --- a/optional-requirements.txt +++ b/optional-requirements.txt @@ -1,31 +1,31 @@ # GDrive Integration -google-api-python-client>=1.7.11,<2.50.0 -gevent>20.6.0,<22.0.0 -greenlet>=0.4.17,<1.2.0 -httplib2>=0.9.2,<0.21.0 +google-api-python-client>=1.7.11,<2.108.0 +gevent>20.6.0,<24.0.0 +greenlet>=0.4.17,<2.1.0 +httplib2>=0.9.2,<0.23.0 oauth2client>=4.0.0,<4.1.4 uritemplate>=3.0.0,<4.2.0 -pyasn1-modules>=0.0.8,<0.3.0 -pyasn1>=0.1.9,<0.5.0 -PyDrive2>=1.3.1,<1.11.0 -PyYAML>=3.12 -rsa>=3.4.2,<4.9.0 +pyasn1-modules>=0.0.8,<0.4.0 +pyasn1>=0.1.9,<0.6.0 +PyDrive2>=1.3.1,<1.18.0 +PyYAML>=3.12,<6.1 +rsa>=3.4.2,<4.10.0 # Gmail -google-auth-oauthlib>=0.4.3,<0.6.0 -google-api-python-client>=1.7.11,<2.50.0 +google-auth-oauthlib>=0.4.3,<1.1.0 +google-api-python-client>=1.7.11,<2.108.0 # goodreads goodreads>=0.3.2,<0.4.0 -python-Levenshtein>=0.12.0,<0.13.0 +python-Levenshtein>=0.12.0,<0.22.0 # ldap login python-ldap>=3.0.0,<3.5.0 Flask-SimpleLDAP>=1.4.0,<1.5.0 # oauth -Flask-Dance>=2.0.0,<5.2.0 -SQLAlchemy-Utils>=0.33.5,<0.39.0 +Flask-Dance>=2.0.0,<7.1.0 +SQLAlchemy-Utils>=0.33.5,<0.42.0 # metadata extraction rarfile>=3.2 @@ -33,12 +33,13 @@ scholarly>=1.2.0,<1.8 markdown2>=2.0.0,<2.5.0 html2text>=2020.1.16,<2022.1.1 python-dateutil>=2.1,<2.9.0 -beautifulsoup4>=4.0.1,<4.12.0 -cchardet>=2.0.0,<2.2.0 +beautifulsoup4>=4.0.1,<4.13.0 +faust-cchardet>=2.1.18,<2.1.20 +py7zr>=0.15.0,<0.21.0 # Comics -natsort>=2.2.0,<8.2.0 -comicapi>=2.2.0,<2.3.0 +natsort>=2.2.0,<8.4.0 +comicapi>=2.2.0,<3.3.0 # Kobo integration -jsonschema>=3.2.0,<4.9.0 +jsonschema>=3.2.0,<4.20.0 diff --git a/requirements.txt b/requirements.txt index 0c20c71d..f1e5b712 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,20 @@ -APScheduler>=3.6.3,<3.10.0 -werkzeug<2.1.0 +Werkzeug<3.0.0 +APScheduler>=3.6.3,<3.11.0 Babel>=1.3,<3.0 -Flask-Babel>=0.11.1,<2.1.0 -Flask-Login>=0.3.2,<0.6.2 +Flask-Babel>=0.11.1,<4.1.0 +Flask-Login>=0.3.2,<0.6.3 Flask-Principal>=0.3.2,<0.5.1 -backports_abc>=0.4 -Flask>=1.0.2,<2.1.0 +Flask>=1.0.2,<2.4.0 iso-639>=0.4.5,<0.5.0 -PyPDF2>=1.20,<2.11.0 +PyPDF>=3.0.0,<3.16.0 pytz>=2016.10 -requests>=2.11.1,<2.28.0 -SQLAlchemy>=1.3.0,<1.5.0 -tornado>=4.1,<6.2 +requests>=2.28.0,<2.32.0 +SQLAlchemy>=1.3.0,<2.0.0 +tornado>=6.3,<6.4 Wand>=0.4.4,<0.7.0 unidecode>=0.04.19,<1.4.0 -lxml>=3.8.0,<4.9.0 -flask-wtf>=0.14.2,<1.1.0 +lxml>=3.8.0,<5.0.0 +flask-wtf>=0.14.2,<1.3.0 chardet>=3.0.0,<4.1.0 advocate>=1.0.0,<1.1.0 +Flask-Limiter>=2.3.0,<3.6.0 diff --git a/setup.cfg b/setup.cfg index 1c531d48..4bcd1a11 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,17 +13,17 @@ author = @OzzieIsaacs author_email = Ozzie.Fernandez.Isaacs@googlemail.com maintainer = @OzzieIsaacs license = GPLv3+ -license_file = LICENSE +license_files = LICENSE classifiers = Development Status :: 5 - Production/Stable License :: OSI Approved :: GNU Affero General Public License v3 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 Operating System :: OS Independent keywords = calibre @@ -38,64 +38,69 @@ console_scripts = [options] include_package_data = True install_requires = - APScheduler>=3.6.3,<3.10.0 - werkzeug<2.1.0 + Werkzeug<3.0.0 + APScheduler>=3.6.3,<3.11.0 Babel>=1.3,<3.0 - Flask-Babel>=0.11.1,<2.1.0 - Flask-Login>=0.3.2,<0.6.2 + Flask-Babel>=0.11.1,<3.2.0 + Flask-Login>=0.3.2,<0.6.3 Flask-Principal>=0.3.2,<0.5.1 - backports_abc>=0.4 - Flask>=1.0.2,<2.1.0 + Flask>=1.0.2,<2.4.0 iso-639>=0.4.5,<0.5.0 - PyPDF2>=1.20,<2.11.0 + PyPDF>=3.0.0,<3.16.0 pytz>=2016.10 - requests>=2.11.1,<2.28.0 - SQLAlchemy>=1.3.0,<1.5.0 - tornado>=4.1,<6.2 + requests>=2.28.0,<2.32.0 + SQLAlchemy>=1.3.0,<2.0.0 + tornado>=6.3,<6.4 Wand>=0.4.4,<0.7.0 unidecode>=0.04.19,<1.4.0 - lxml>=3.8.0,<4.9.0 - flask-wtf>=0.14.2,<1.1.0 + lxml>=3.8.0,<5.0.0 + flask-wtf>=0.14.2,<1.2.0 chardet>=3.0.0,<4.1.0 advocate>=1.0.0,<1.1.0 + Flask-Limiter>=2.3.0,<3.5.0 +[options.packages.find] +where = src +include = cps/services* + [options.extras_require] gdrive = - google-api-python-client>=1.7.11,<2.50.0 - gevent>20.6.0,<22.0.0 - greenlet>=0.4.17,<1.2.0 - httplib2>=0.9.2,<0.21.0 + google-api-python-client>=1.7.11,<2.98.0 + gevent>20.6.0,<24.0.0 + greenlet>=0.4.17,<2.1.0 + httplib2>=0.9.2,<0.23.0 oauth2client>=4.0.0,<4.1.4 uritemplate>=3.0.0,<4.2.0 - pyasn1-modules>=0.0.8,<0.3.0 - pyasn1>=0.1.9,<0.5.0 - PyDrive2>=1.3.1,<1.11.0 - PyYAML>=3.12 - rsa>=3.4.2,<4.9.0 + pyasn1-modules>=0.0.8,<0.4.0 + pyasn1>=0.1.9,<0.6.0 + PyDrive2>=1.3.1,<1.18.0 + PyYAML>=3.12,<6.1 + rsa>=3.4.2,<4.10.0 gmail = - google-auth-oauthlib>=0.4.3,<0.6.0 - google-api-python-client>=1.7.11,<2.50.0 + google-auth-oauthlib>=0.4.3,<1.1.0 + google-api-python-client>=1.7.11,<2.98.0 goodreads = goodreads>=0.3.2,<0.4.0 - python-Levenshtein>=0.12.0,<0.13.0 + python-Levenshtein>=0.12.0,<0.22.0 ldap = python-ldap>=3.0.0,<3.5.0 Flask-SimpleLDAP>=1.4.0,<1.5.0 oauth = - Flask-Dance>=2.0.0,<5.2.0 - SQLAlchemy-Utils>=0.33.5,<0.39.0 + Flask-Dance>=2.0.0,<7.1.0 + SQLAlchemy-Utils>=0.33.5,<0.42.0 metadata = rarfile>=3.2 scholarly>=1.2.0,<1.8 markdown2>=2.0.0,<2.5.0 html2text>=2020.1.16,<2022.1.1 python-dateutil>=2.1,<2.9.0 - beautifulsoup4>=4.0.1,<4.12.0 - cchardet>=2.0.0,<2.2.0 + beautifulsoup4>=4.0.1,<4.13.0 + faust-cchardet>=2.1.18,<2.1.20 + py7zr>=0.15.0,<0.21.0 comics = - natsort>=2.2.0,<8.2.0 - comicapi>=2.2.0,<2.3.0 + natsort>=2.2.0,<8.4.0 + comicapi>=2.2.0,<3.3.0 kobo = - jsonschema>=3.2.0,<4.9.0 + jsonschema>=3.2.0,<4.20.0 diff --git a/setup.py b/setup.py index 6bde2211..8dcbee25 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,6 @@ # """Calibre-web distribution package setuptools installer.""" from setuptools import setup -from setuptools import find_packages import os import re import codecs @@ -40,7 +39,5 @@ def find_version(*file_paths): raise RuntimeError("Unable to find version string.") setup( - packages=find_packages("src"), - package_dir = {'': 'src'}, version=find_version("src", "calibreweb", "cps", "constants.py") ) diff --git a/test/Calibre-Web TestSummary_Linux.html b/test/Calibre-Web TestSummary_Linux.html index 089dab8c..7ca3dad5 100644 --- a/test/Calibre-Web TestSummary_Linux.html +++ b/test/Calibre-Web TestSummary_Linux.html @@ -37,20 +37,20 @@
-

Start Time: 2022-09-25 22:15:18

+

Start Time: 2023-10-16 19:38:22

-

Stop Time: 2022-09-26 04:46:12

+

Stop Time: 2023-10-17 02:18:49

-

Duration: 5h 35 min

+

Duration: 5h 37 min

@@ -235,14 +235,14 @@
- - - + + + @@ -250,7 +250,7 @@ @@ -259,7 +259,7 @@ @@ -268,7 +268,7 @@ @@ -277,7 +277,7 @@ @@ -286,7 +286,7 @@ @@ -295,7 +295,7 @@ @@ -304,7 +304,7 @@ @@ -313,7 +313,7 @@ @@ -322,7 +322,7 @@ @@ -331,7 +331,7 @@ @@ -340,7 +340,7 @@ @@ -348,6 +348,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -365,13 +611,13 @@ - + @@ -380,7 +626,7 @@ - + @@ -389,7 +635,7 @@ - + @@ -398,7 +644,7 @@ - + @@ -416,13 +662,13 @@ - + @@ -431,7 +677,7 @@ - + @@ -449,13 +695,13 @@ - + @@ -473,13 +719,13 @@ - + @@ -488,7 +734,7 @@ - + @@ -497,7 +743,7 @@ - + @@ -506,7 +752,7 @@ - + @@ -515,7 +761,7 @@ - + @@ -524,7 +770,7 @@ - + @@ -533,7 +779,7 @@ - + @@ -542,7 +788,7 @@ - + @@ -551,7 +797,7 @@ - + @@ -560,7 +806,7 @@ - + @@ -569,7 +815,7 @@ - + @@ -578,7 +824,7 @@ - + @@ -587,7 +833,7 @@ - + @@ -596,7 +842,7 @@ - + @@ -605,7 +851,7 @@ - + @@ -623,13 +869,13 @@ - + @@ -638,7 +884,7 @@ - + @@ -647,7 +893,7 @@ - + @@ -656,7 +902,7 @@ - + @@ -665,7 +911,7 @@ - + @@ -674,7 +920,7 @@ - + @@ -692,13 +938,13 @@ - + @@ -707,7 +953,7 @@ - + @@ -716,7 +962,7 @@ - + @@ -734,13 +980,13 @@ - + @@ -749,7 +995,7 @@ - + @@ -758,7 +1004,7 @@ - + @@ -770,19 +1016,19 @@ - - + + - + - + @@ -791,7 +1037,7 @@ - + @@ -800,7 +1046,7 @@ - + @@ -809,7 +1055,7 @@ - + @@ -818,7 +1064,7 @@ - + @@ -827,7 +1073,7 @@ - + @@ -836,7 +1082,7 @@ - + @@ -845,7 +1091,7 @@ - + @@ -854,7 +1100,7 @@ - + @@ -863,7 +1109,7 @@ - + @@ -872,7 +1118,7 @@ - + @@ -881,7 +1127,7 @@ - + @@ -890,7 +1136,16 @@ - + + + + + + + + @@ -899,7 +1154,7 @@ - + @@ -908,7 +1163,42 @@ - + + + + + + + + + + + + + + + @@ -917,7 +1207,7 @@ - + @@ -926,7 +1216,7 @@ - + @@ -938,19 +1228,19 @@ + - - + - + @@ -959,7 +1249,7 @@ - + @@ -968,7 +1258,7 @@ - + @@ -977,7 +1267,7 @@ - + @@ -986,7 +1276,7 @@ - + @@ -995,7 +1285,7 @@ - + @@ -1004,7 +1294,7 @@ - + @@ -1013,7 +1303,7 @@ - + @@ -1022,7 +1312,7 @@ - + @@ -1031,7 +1321,7 @@ - + @@ -1040,7 +1330,7 @@ - + @@ -1049,7 +1339,7 @@ - + @@ -1058,7 +1348,7 @@ - + @@ -1067,7 +1357,7 @@ - + @@ -1076,7 +1366,7 @@ - + @@ -1085,7 +1375,7 @@ - + @@ -1094,7 +1384,7 @@ - + @@ -1103,7 +1393,7 @@ - + @@ -1112,7 +1402,7 @@ - + @@ -1121,19 +1411,45 @@ - + + + + + + + + + @@ -1156,7 +1472,7 @@ - + @@ -1165,7 +1481,7 @@ - + @@ -1174,7 +1490,7 @@ - + @@ -1183,7 +1499,7 @@ - + @@ -1192,7 +1508,7 @@ - + @@ -1201,7 +1517,16 @@ - + + + + + + + + @@ -1210,7 +1535,7 @@ - + @@ -1219,7 +1544,7 @@ - + @@ -1228,7 +1553,7 @@ - + @@ -1237,7 +1562,7 @@ - + @@ -1246,7 +1571,7 @@ - + @@ -1255,7 +1580,7 @@ - + @@ -1264,7 +1589,7 @@ - + @@ -1273,7 +1598,7 @@ - + @@ -1282,7 +1607,7 @@ - + @@ -1300,13 +1625,13 @@ - + @@ -1315,7 +1640,7 @@ - + @@ -1324,7 +1649,7 @@ - + @@ -1333,7 +1658,7 @@ - + @@ -1342,7 +1667,7 @@ - + @@ -1351,7 +1676,7 @@ - + @@ -1369,13 +1694,13 @@ - + @@ -1384,7 +1709,7 @@ - + @@ -1393,7 +1718,7 @@ - + @@ -1402,7 +1727,7 @@ - + @@ -1411,7 +1736,7 @@ - + @@ -1420,7 +1745,7 @@ - + @@ -1438,13 +1763,13 @@ - + @@ -1453,7 +1778,7 @@ - + @@ -1462,7 +1787,7 @@ - + @@ -1471,7 +1796,7 @@ - + @@ -1480,7 +1805,7 @@ - + @@ -1489,7 +1814,7 @@ - + @@ -1498,7 +1823,7 @@ - + @@ -1507,7 +1832,7 @@ - + @@ -1516,7 +1841,7 @@ - + @@ -1525,7 +1850,7 @@ - + @@ -1534,7 +1859,7 @@ - + @@ -1543,7 +1868,7 @@ - + @@ -1552,7 +1877,7 @@ - + @@ -1561,7 +1886,7 @@ - + @@ -1570,7 +1895,7 @@ - + @@ -1579,7 +1904,7 @@ - + @@ -1588,7 +1913,7 @@ - + @@ -1597,7 +1922,7 @@ - + @@ -1607,40 +1932,40 @@ - + + - - + - + @@ -1674,7 +1999,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1683,7 +2008,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1692,7 +2017,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1701,7 +2026,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1710,7 +2035,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1719,7 +2044,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1728,7 +2053,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1737,7 +2062,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1746,7 +2071,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1755,7 +2080,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1764,7 +2089,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1773,7 +2098,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1782,7 +2107,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1791,7 +2116,7 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + @@ -1800,26 +2125,26 @@ AssertionError: 0.0 not greater than or equal to 0.05 - + + @@ -1838,7 +2163,7 @@ IndexError: list index out of range - + @@ -1856,13 +2181,13 @@ IndexError: list index out of range - + @@ -1880,13 +2205,13 @@ IndexError: list index out of range - + @@ -1895,7 +2220,7 @@ IndexError: list index out of range - + @@ -1904,7 +2229,7 @@ IndexError: list index out of range - + @@ -1922,13 +2247,13 @@ IndexError: list index out of range - + @@ -1937,7 +2262,7 @@ IndexError: list index out of range - + @@ -1946,7 +2271,7 @@ IndexError: list index out of range - + @@ -1955,7 +2280,7 @@ IndexError: list index out of range - + @@ -1964,7 +2289,7 @@ IndexError: list index out of range - + @@ -1973,7 +2298,7 @@ IndexError: list index out of range - + @@ -1982,7 +2307,7 @@ IndexError: list index out of range - + @@ -2000,13 +2325,13 @@ IndexError: list index out of range - + @@ -2024,13 +2349,13 @@ IndexError: list index out of range - + @@ -2039,7 +2364,7 @@ IndexError: list index out of range - + @@ -2057,13 +2382,13 @@ IndexError: list index out of range - + @@ -2072,19 +2397,19 @@ IndexError: list index out of range - + + @@ -2116,13 +2441,13 @@ IndexError: list index out of range - + @@ -2140,13 +2465,13 @@ IndexError: list index out of range - + @@ -2155,7 +2480,7 @@ IndexError: list index out of range - + @@ -2164,7 +2489,7 @@ IndexError: list index out of range - + @@ -2176,19 +2501,19 @@ IndexError: list index out of range - - + + - + @@ -2197,7 +2522,7 @@ IndexError: list index out of range - + @@ -2206,7 +2531,16 @@ IndexError: list index out of range - + + + + + + + + @@ -2215,7 +2549,7 @@ IndexError: list index out of range - + @@ -2224,7 +2558,7 @@ IndexError: list index out of range - + @@ -2233,7 +2567,7 @@ IndexError: list index out of range - + @@ -2242,7 +2576,7 @@ IndexError: list index out of range - + @@ -2251,7 +2585,7 @@ IndexError: list index out of range - + @@ -2260,7 +2594,7 @@ IndexError: list index out of range - + @@ -2269,7 +2603,7 @@ IndexError: list index out of range - + @@ -2278,7 +2612,7 @@ IndexError: list index out of range - + @@ -2296,13 +2630,13 @@ IndexError: list index out of range - + @@ -2311,7 +2645,7 @@ IndexError: list index out of range - + @@ -2320,7 +2654,7 @@ IndexError: list index out of range - + @@ -2329,7 +2663,7 @@ IndexError: list index out of range - + @@ -2338,7 +2672,7 @@ IndexError: list index out of range - + @@ -2347,7 +2681,7 @@ IndexError: list index out of range - + @@ -2365,13 +2699,13 @@ IndexError: list index out of range - + @@ -2380,7 +2714,7 @@ IndexError: list index out of range - + @@ -2389,7 +2723,7 @@ IndexError: list index out of range - + @@ -2398,7 +2732,7 @@ IndexError: list index out of range - + @@ -2407,7 +2741,7 @@ IndexError: list index out of range - + @@ -2416,7 +2750,7 @@ IndexError: list index out of range - + @@ -2425,7 +2759,7 @@ IndexError: list index out of range - + @@ -2434,7 +2768,7 @@ IndexError: list index out of range - + @@ -2443,7 +2777,7 @@ IndexError: list index out of range - + @@ -2452,7 +2786,7 @@ IndexError: list index out of range - + @@ -2461,7 +2795,7 @@ IndexError: list index out of range - + @@ -2470,7 +2804,7 @@ IndexError: list index out of range - + @@ -2479,7 +2813,7 @@ IndexError: list index out of range - + @@ -2489,6 +2823,57 @@ IndexError: list index out of range + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2497,13 +2882,13 @@ IndexError: list index out of range - + @@ -2512,7 +2897,7 @@ IndexError: list index out of range - + @@ -2521,7 +2906,7 @@ IndexError: list index out of range - + @@ -2530,7 +2915,7 @@ IndexError: list index out of range - + @@ -2539,7 +2924,7 @@ IndexError: list index out of range - + @@ -2548,7 +2933,7 @@ IndexError: list index out of range - + @@ -2557,7 +2942,7 @@ IndexError: list index out of range - + @@ -2566,7 +2951,7 @@ IndexError: list index out of range - + @@ -2575,7 +2960,7 @@ IndexError: list index out of range - + @@ -2584,7 +2969,7 @@ IndexError: list index out of range - + @@ -2602,13 +2987,13 @@ IndexError: list index out of range - + @@ -2617,7 +3002,7 @@ IndexError: list index out of range - + @@ -2626,7 +3011,7 @@ IndexError: list index out of range - + @@ -2635,7 +3020,7 @@ IndexError: list index out of range - + @@ -2644,19 +3029,19 @@ IndexError: list index out of range - + + @@ -2679,7 +3064,7 @@ IndexError: list index out of range - + @@ -2688,7 +3073,7 @@ IndexError: list index out of range - + @@ -2697,7 +3082,7 @@ IndexError: list index out of range - + @@ -2709,19 +3094,19 @@ IndexError: list index out of range - - + + - + @@ -2730,7 +3115,7 @@ IndexError: list index out of range - + @@ -2739,7 +3124,7 @@ IndexError: list index out of range - + @@ -2748,7 +3133,7 @@ IndexError: list index out of range - + @@ -2757,7 +3142,7 @@ IndexError: list index out of range - + @@ -2766,7 +3151,7 @@ IndexError: list index out of range - + @@ -2775,7 +3160,7 @@ IndexError: list index out of range - + @@ -2784,7 +3169,7 @@ IndexError: list index out of range - + @@ -2793,7 +3178,7 @@ IndexError: list index out of range - + @@ -2802,7 +3187,7 @@ IndexError: list index out of range - + @@ -2811,7 +3196,7 @@ IndexError: list index out of range - + @@ -2820,7 +3205,7 @@ IndexError: list index out of range - + @@ -2829,7 +3214,7 @@ IndexError: list index out of range - + @@ -2838,7 +3223,16 @@ IndexError: list index out of range - + + + + + + + + @@ -2847,7 +3241,16 @@ IndexError: list index out of range - + + + + + + + + @@ -2865,13 +3268,13 @@ IndexError: list index out of range - + @@ -2880,7 +3283,7 @@ IndexError: list index out of range - + @@ -2898,13 +3301,13 @@ IndexError: list index out of range - + @@ -2913,7 +3316,7 @@ IndexError: list index out of range - + @@ -2925,19 +3328,19 @@ IndexError: list index out of range - - + + - + @@ -2946,7 +3349,7 @@ IndexError: list index out of range - + @@ -2955,7 +3358,7 @@ IndexError: list index out of range - + @@ -2964,7 +3367,7 @@ IndexError: list index out of range - + @@ -2973,7 +3376,7 @@ IndexError: list index out of range - + @@ -2982,7 +3385,7 @@ IndexError: list index out of range - + @@ -2991,7 +3394,7 @@ IndexError: list index out of range - + @@ -3000,7 +3403,7 @@ IndexError: list index out of range - + @@ -3009,7 +3412,7 @@ IndexError: list index out of range - + @@ -3018,7 +3421,7 @@ IndexError: list index out of range - + @@ -3027,7 +3430,7 @@ IndexError: list index out of range - + @@ -3036,7 +3439,7 @@ IndexError: list index out of range - + @@ -3045,7 +3448,7 @@ IndexError: list index out of range - + @@ -3054,7 +3457,7 @@ IndexError: list index out of range - + @@ -3063,7 +3466,7 @@ IndexError: list index out of range - + @@ -3072,7 +3475,7 @@ IndexError: list index out of range - + @@ -3081,7 +3484,7 @@ IndexError: list index out of range - + @@ -3090,7 +3493,7 @@ IndexError: list index out of range - + @@ -3099,7 +3502,7 @@ IndexError: list index out of range - + @@ -3108,7 +3511,16 @@ IndexError: list index out of range - + + + + + + + + @@ -3117,7 +3529,7 @@ IndexError: list index out of range - + @@ -3126,7 +3538,7 @@ IndexError: list index out of range - + @@ -3135,7 +3547,7 @@ IndexError: list index out of range - + @@ -3153,13 +3565,13 @@ IndexError: list index out of range - + @@ -3177,13 +3589,13 @@ IndexError: list index out of range - + @@ -3192,7 +3604,7 @@ IndexError: list index out of range - + @@ -3201,7 +3613,7 @@ IndexError: list index out of range - + @@ -3211,21 +3623,30 @@ IndexError: list index out of range - + + - - + - + + + + + + + + @@ -3234,7 +3655,7 @@ IndexError: list index out of range - + @@ -3243,7 +3664,7 @@ IndexError: list index out of range - + @@ -3252,16 +3673,42 @@ IndexError: list index out of range - + - + - + @@ -3279,13 +3726,13 @@ IndexError: list index out of range - + @@ -3303,13 +3750,13 @@ IndexError: list index out of range - + @@ -3318,7 +3765,7 @@ IndexError: list index out of range - + @@ -3327,7 +3774,7 @@ IndexError: list index out of range - + @@ -3336,7 +3783,7 @@ IndexError: list index out of range - + @@ -3345,7 +3792,7 @@ IndexError: list index out of range - + @@ -3354,7 +3801,7 @@ IndexError: list index out of range - + @@ -3363,7 +3810,7 @@ IndexError: list index out of range - + @@ -3372,7 +3819,7 @@ IndexError: list index out of range - + @@ -3390,13 +3837,13 @@ IndexError: list index out of range - + @@ -3405,7 +3852,7 @@ IndexError: list index out of range - + @@ -3414,7 +3861,7 @@ IndexError: list index out of range - + @@ -3432,13 +3879,13 @@ IndexError: list index out of range - + @@ -3447,7 +3894,7 @@ IndexError: list index out of range - + @@ -3456,7 +3903,7 @@ IndexError: list index out of range - + @@ -3465,7 +3912,7 @@ IndexError: list index out of range - + @@ -3474,7 +3921,7 @@ IndexError: list index out of range - + @@ -3483,7 +3930,7 @@ IndexError: list index out of range - + @@ -3492,7 +3939,7 @@ IndexError: list index out of range - + @@ -3501,7 +3948,7 @@ IndexError: list index out of range - + @@ -3510,7 +3957,7 @@ IndexError: list index out of range - + @@ -3519,7 +3966,7 @@ IndexError: list index out of range - + @@ -3528,7 +3975,7 @@ IndexError: list index out of range - + @@ -3537,7 +3984,7 @@ IndexError: list index out of range - + @@ -3546,7 +3993,7 @@ IndexError: list index out of range - + @@ -3555,19 +4002,19 @@ IndexError: list index out of range - + + @@ -3590,7 +4037,7 @@ IndexError: list index out of range - + @@ -3608,13 +4055,13 @@ IndexError: list index out of range - + @@ -3624,21 +4071,21 @@ IndexError: list index out of range - + - - + + - + @@ -3647,7 +4094,7 @@ IndexError: list index out of range - + @@ -3656,7 +4103,7 @@ IndexError: list index out of range - + @@ -3665,7 +4112,7 @@ IndexError: list index out of range - + @@ -3674,7 +4121,7 @@ IndexError: list index out of range - + @@ -3683,7 +4130,7 @@ IndexError: list index out of range - + @@ -3692,7 +4139,7 @@ IndexError: list index out of range - + @@ -3701,11 +4148,31 @@ IndexError: list index out of range - + - + @@ -3719,13 +4186,13 @@ IndexError: list index out of range - + @@ -3734,7 +4201,7 @@ IndexError: list index out of range - + @@ -3743,7 +4210,7 @@ IndexError: list index out of range - + @@ -3752,7 +4219,7 @@ IndexError: list index out of range - + @@ -3761,7 +4228,7 @@ IndexError: list index out of range - + @@ -3770,7 +4237,7 @@ IndexError: list index out of range - + @@ -3779,19 +4246,19 @@ IndexError: list index out of range - + + @@ -3814,7 +4281,7 @@ IndexError: list index out of range - + @@ -3826,19 +4293,19 @@ IndexError: list index out of range - - + + - + @@ -3847,7 +4314,7 @@ IndexError: list index out of range - + @@ -3856,7 +4323,7 @@ IndexError: list index out of range - + @@ -3865,7 +4332,16 @@ IndexError: list index out of range - + + + + + + + + @@ -3883,13 +4359,13 @@ IndexError: list index out of range - + @@ -3898,7 +4374,7 @@ IndexError: list index out of range - + @@ -3907,7 +4383,7 @@ IndexError: list index out of range - + @@ -3916,7 +4392,7 @@ IndexError: list index out of range - + @@ -3925,7 +4401,7 @@ IndexError: list index out of range - + @@ -3934,7 +4410,7 @@ IndexError: list index out of range - + @@ -3943,7 +4419,7 @@ IndexError: list index out of range - + @@ -3952,7 +4428,7 @@ IndexError: list index out of range - + @@ -3961,7 +4437,7 @@ IndexError: list index out of range - + @@ -3970,7 +4446,7 @@ IndexError: list index out of range - + @@ -3979,7 +4455,7 @@ IndexError: list index out of range - + @@ -3988,7 +4464,7 @@ IndexError: list index out of range - + @@ -3997,7 +4473,7 @@ IndexError: list index out of range - + @@ -4006,7 +4482,7 @@ IndexError: list index out of range - + @@ -4015,7 +4491,7 @@ IndexError: list index out of range - + @@ -4024,7 +4500,7 @@ IndexError: list index out of range - + @@ -4033,7 +4509,7 @@ IndexError: list index out of range - + @@ -4042,7 +4518,7 @@ IndexError: list index out of range - + @@ -4060,13 +4536,13 @@ IndexError: list index out of range - + @@ -4084,13 +4560,13 @@ IndexError: list index out of range - + @@ -4099,7 +4575,7 @@ IndexError: list index out of range - + @@ -4108,7 +4584,7 @@ IndexError: list index out of range - + @@ -4117,7 +4593,7 @@ IndexError: list index out of range - + @@ -4126,7 +4602,7 @@ IndexError: list index out of range - + @@ -4135,7 +4611,7 @@ IndexError: list index out of range - + @@ -4144,7 +4620,7 @@ IndexError: list index out of range - + @@ -4153,7 +4629,7 @@ IndexError: list index out of range - + @@ -4162,7 +4638,7 @@ IndexError: list index out of range - + @@ -4171,7 +4647,7 @@ IndexError: list index out of range - + @@ -4180,7 +4656,7 @@ IndexError: list index out of range - + @@ -4189,7 +4665,7 @@ IndexError: list index out of range - + @@ -4198,7 +4674,7 @@ IndexError: list index out of range - + @@ -4207,7 +4683,7 @@ IndexError: list index out of range - + @@ -4216,7 +4692,7 @@ IndexError: list index out of range - + @@ -4225,7 +4701,7 @@ IndexError: list index out of range - + @@ -4234,7 +4710,7 @@ IndexError: list index out of range - + @@ -4243,7 +4719,7 @@ IndexError: list index out of range - + @@ -4252,7 +4728,7 @@ IndexError: list index out of range - + @@ -4261,7 +4737,7 @@ IndexError: list index out of range - + @@ -4270,7 +4746,7 @@ IndexError: list index out of range - + @@ -4288,13 +4764,13 @@ IndexError: list index out of range - + @@ -4303,7 +4779,7 @@ IndexError: list index out of range - + @@ -4312,7 +4788,7 @@ IndexError: list index out of range - + @@ -4321,7 +4797,7 @@ IndexError: list index out of range - + @@ -4330,7 +4806,7 @@ IndexError: list index out of range - + @@ -4339,7 +4815,7 @@ IndexError: list index out of range - + @@ -4348,7 +4824,7 @@ IndexError: list index out of range - + @@ -4357,7 +4833,7 @@ IndexError: list index out of range - + @@ -4366,7 +4842,7 @@ IndexError: list index out of range - + @@ -4375,7 +4851,7 @@ IndexError: list index out of range - + @@ -4384,7 +4860,7 @@ IndexError: list index out of range - + @@ -4393,7 +4869,7 @@ IndexError: list index out of range - + @@ -4402,7 +4878,7 @@ IndexError: list index out of range - + @@ -4411,7 +4887,7 @@ IndexError: list index out of range - + @@ -4420,7 +4896,7 @@ IndexError: list index out of range - + @@ -4429,7 +4905,7 @@ IndexError: list index out of range - + @@ -4438,7 +4914,7 @@ IndexError: list index out of range - + @@ -4447,7 +4923,7 @@ IndexError: list index out of range - + @@ -4456,7 +4932,7 @@ IndexError: list index out of range - + @@ -4465,7 +4941,7 @@ IndexError: list index out of range - + @@ -4474,7 +4950,7 @@ IndexError: list index out of range - + @@ -4483,7 +4959,7 @@ IndexError: list index out of range - + @@ -4492,7 +4968,7 @@ IndexError: list index out of range - + @@ -4501,7 +4977,7 @@ IndexError: list index out of range - + @@ -4510,7 +4986,7 @@ IndexError: list index out of range - + @@ -4519,7 +4995,7 @@ IndexError: list index out of range - + @@ -4528,7 +5004,7 @@ IndexError: list index out of range - + @@ -4537,7 +5013,7 @@ IndexError: list index out of range - + @@ -4546,7 +5022,7 @@ IndexError: list index out of range - + @@ -4555,7 +5031,7 @@ IndexError: list index out of range - + @@ -4564,7 +5040,7 @@ IndexError: list index out of range - + @@ -4573,7 +5049,7 @@ IndexError: list index out of range - + @@ -4582,7 +5058,7 @@ IndexError: list index out of range - + @@ -4591,7 +5067,7 @@ IndexError: list index out of range - + @@ -4600,7 +5076,7 @@ IndexError: list index out of range - + @@ -4618,13 +5094,13 @@ IndexError: list index out of range - + @@ -4633,7 +5109,7 @@ IndexError: list index out of range - + @@ -4642,7 +5118,7 @@ IndexError: list index out of range - + @@ -4651,7 +5127,7 @@ IndexError: list index out of range - + @@ -4660,7 +5136,7 @@ IndexError: list index out of range - + @@ -4669,7 +5145,7 @@ IndexError: list index out of range - + @@ -4678,7 +5154,7 @@ IndexError: list index out of range - + @@ -4687,7 +5163,7 @@ IndexError: list index out of range - + @@ -4696,7 +5172,7 @@ IndexError: list index out of range - + @@ -4705,7 +5181,7 @@ IndexError: list index out of range - + @@ -4714,7 +5190,7 @@ IndexError: list index out of range - + @@ -4723,7 +5199,7 @@ IndexError: list index out of range - + @@ -4732,7 +5208,7 @@ IndexError: list index out of range - + @@ -4741,7 +5217,7 @@ IndexError: list index out of range - + @@ -4750,7 +5226,7 @@ IndexError: list index out of range - + @@ -4759,7 +5235,7 @@ IndexError: list index out of range - + @@ -4770,11 +5246,11 @@ IndexError: list index out of range - - - - - + + + + +
{{_('Edit')}}
{{_('Delete User')}}

{{_('Delete User')}}
TestCli1212TestBackupMetadata2222 0 0 0 - Detail + Detail
-
TestCli - test_already_started
+
TestBackupMetadata - test_backup_all
PASS
-
TestCli - test_bind_to_single_interface
+
TestBackupMetadata - test_backup_change_book_author
PASS
-
TestCli - test_change_password
+
TestBackupMetadata - test_backup_change_book_description
PASS
-
TestCli - test_cli_SSL_files
+
TestBackupMetadata - test_backup_change_book_identifier
PASS
-
TestCli - test_cli_different_folder
+
TestBackupMetadata - test_backup_change_book_language
PASS
-
TestCli - test_cli_different_settings_database
+
TestBackupMetadata - test_backup_change_book_publisher
PASS
-
TestCli - test_dryrun_update
+
TestBackupMetadata - test_backup_change_book_publishing_date
PASS
-
TestCli - test_enable_reconnect
+
TestBackupMetadata - test_backup_change_book_rating
PASS
-
TestCli - test_environ_port_setting
+
TestBackupMetadata - test_backup_change_book_series_index
PASS
-
TestCli - test_no_database
+
TestBackupMetadata - test_backup_change_book_tags
PASS
-
TestCli - test_settingsdb_not_writeable
+
TestBackupMetadata - test_backup_change_book_title
PASS
+
TestBackupMetadata - test_backup_change_custom_Comment
+
PASS
+
TestBackupMetadata - test_backup_change_custom_Enum
+
PASS
+
TestBackupMetadata - test_backup_change_custom_bool
+
PASS
+
TestBackupMetadata - test_backup_change_custom_categories
+
PASS
+
TestBackupMetadata - test_backup_change_custom_date
+
PASS
+
TestBackupMetadata - test_backup_change_custom_float
+
PASS
+
TestBackupMetadata - test_backup_change_custom_int
+
PASS
+
TestBackupMetadata - test_backup_change_custom_rating
+
PASS
+
TestBackupMetadata - test_backup_change_custom_text
+
PASS
+
TestBackupMetadata - test_gdrive
+
PASS
+
TestBackupMetadata - test_upload_book
+
PASS
TestBackupMetadataGdrive11000 + Detail +
+
TestBackupMetadataGdrive - test_backup_gdrive
+
PASS
TestCli1313000 + Detail +
+
TestCli - test_already_started
+
PASS
+
TestCli - test_bind_to_single_interface
+
PASS
+
TestCli - test_change_password
+
PASS
+
TestCli - test_cli_SSL_files
+
PASS
+
TestCli - test_cli_different_folder
+
PASS
+
TestCli - test_cli_different_settings_database
+
PASS
+
TestCli - test_dryrun_update
+
PASS
+
TestCli - test_enable_reconnect
+
PASS
+
TestCli - test_environ_port_setting
+
PASS
+
TestCli - test_logfile
+
PASS
+
TestCli - test_no_database
+
PASS
+
TestCli - test_settingsdb_not_writeable
+
PASS
TestCli - test_writeonly_static_files
0 0 - Detail + Detail
TestCliGdrivedb - test_cli_gdrive_folder
TestCliGdrivedb - test_cli_gdrive_location
TestCliGdrivedb - test_gdrive_db_nonwrite
TestCliGdrivedb - test_no_database
0 0 - Detail + Detail
TestCoverEditBooks - test_invalid_jpg_hdd
TestCoverEditBooks - test_upload_jpg
0 0 - Detail + Detail
TestDeleteDatabase - test_delete_books_in_database
0 0 - Detail + Detail
TestEbookConvertCalibre - test_calibre_log
TestEbookConvertCalibre - test_convert_deactivate
TestEbookConvertCalibre - test_convert_email
TestEbookConvertCalibre - test_convert_failed_and_email
TestEbookConvertCalibre - test_convert_only
TestEbookConvertCalibre - test_convert_options
TestEbookConvertCalibre - test_convert_parameter
TestEbookConvertCalibre - test_convert_wrong_excecutable
TestEbookConvertCalibre - test_convert_xss
TestEbookConvertCalibre - test_email_failed
TestEbookConvertCalibre - test_email_only
TestEbookConvertCalibre - test_kindle_send_not_configured
TestEbookConvertCalibre - test_ssl_smtp_setup_error
TestEbookConvertCalibre - test_starttls_smtp_setup_error
TestEbookConvertCalibre - test_user_convert_xss
0 0 - Detail + Detail
TestEbookConvertCalibreGDrive - test_convert_email
TestEbookConvertCalibreGDrive - test_convert_failed_and_email
TestEbookConvertCalibreGDrive - test_convert_only
TestEbookConvertCalibreGDrive - test_convert_parameter
TestEbookConvertCalibreGDrive - test_email_failed
TestEbookConvertCalibreGDrive - test_email_only
0 0 - Detail + Detail
TestEbookConvertKepubify - test_convert_deactivate
TestEbookConvertKepubify - test_convert_only
TestEbookConvertKepubify - test_convert_wrong_excecutable
0 0 - Detail + Detail
TestEbookConvertGDriveKepubify - test_convert_deactivate
TestEbookConvertGDriveKepubify - test_convert_only
TestEbookConvertGDriveKepubify - test_convert_wrong_excecutable
TestEditAdditionalBooks17162018 0 012 - Detail + Detail
TestEditAdditionalBooks - test_cbz_comicinfo
TestEditAdditionalBooks - test_change_upload_formats
TestEditAdditionalBooks - test_delete_book
TestEditAdditionalBooks - test_delete_role
TestEditAdditionalBooks - test_details_popup
TestEditAdditionalBooks - test_edit_book_identifier
TestEditAdditionalBooks - test_edit_book_identifier_capital
TestEditAdditionalBooks - test_edit_book_identifier_standard
TestEditAdditionalBooks - test_edit_special_book_identifier
TestEditAdditionalBooks - test_title_sort
TestEditAdditionalBooks - test_upload_cbz_coverformats
TestEditAdditionalBooks - test_upload_edit_role
+
TestEditAdditionalBooks - test_upload_metadata_cb7
+
PASS
TestEditAdditionalBooks - test_upload_metadata_cbr
TestEditAdditionalBooks - test_upload_metadata_cbt
+
TestEditAdditionalBooks - test_writeonly_calibre_database
+
+
+ SKIP +
+ + + +
+
TestEditAdditionalBooks - test_writeonly_path
+
PASS
TestEditAdditionalBooks - test_xss_author_edit
TestEditAdditionalBooks - test_xss_comment_edit
TestEditAdditionalBooks - test_xss_custom_comment_edit
TestEditBooks38 3635 0 012 - Detail + Detail
TestEditBooks - test_download_book
TestEditBooks - test_edit_author
TestEditBooks - test_edit_category
TestEditBooks - test_edit_comments
TestEditBooks - test_edit_custom_bool
TestEditBooks - test_edit_custom_categories
TestEditBooks - test_edit_custom_comment
TestEditBooks - test_edit_custom_date
TestEditBooks - test_edit_custom_float
TestEditBooks - test_edit_custom_int
TestEditBooks - test_edit_custom_rating
TestEditBooks - test_edit_custom_single_select
TestEditBooks - test_edit_custom_text
TestEditBooks - test_edit_language
TestEditBooks - test_edit_publisher
TestEditBooks - test_edit_publishing_date
TestEditBooks - test_edit_rating
TestEditBooks - test_edit_series
TestEditBooks - test_edit_title
+
TestEditBooks - test_rename_upper_lowercase
+
+
+ SKIP +
+ + + +
TestEditBooks - test_rename_uppercase_lowercase
- SKIP + SKIP
-
TestEditBooks - test_typeahead_author
TestEditBooks - test_typeahead_functions
TestEditBooks - test_typeahead_language
TestEditBooks - test_typeahead_publisher
TestEditBooks - test_typeahead_series
TestEditBooks - test_typeahead_tag
+
TestEditBooks - test_upload_book_cb7
+
PASS
TestEditBooks - test_upload_book_cbr
TestEditBooks - test_upload_book_cbt
TestEditBooks - test_upload_book_cbz
TestEditBooks - test_upload_book_epub
TestEditBooks - test_upload_book_fb2
TestEditBooks - test_upload_book_lit
TestEditBooks - test_upload_book_mobi
TestEditBooks - test_upload_book_pdf
TestEditBooks - test_upload_cbz_coverformats
TestEditBooks - test_upload_cover_hdd
0 0 - Detail + Detail
TestEditAuthors - test_change_capital_co_author
TestEditAuthors - test_change_capital_one_author_one_book
TestEditAuthors - test_change_capital_one_author_two_books
TestEditAuthors - test_change_capital_rename_co_author
TestEditAuthors - test_change_capital_rename_two_co_authors
TestEditAuthors - test_rename_capital_on_upload
0 0 - Detail + Detail
TestEditAuthorsGdrive - test_change_capital_co_author
TestEditAuthorsGdrive - test_change_capital_one_author_one_book
TestEditAuthorsGdrive - test_change_capital_one_author_two_books
TestEditAuthorsGdrive - test_change_capital_rename_co_author
TestEditAuthorsGdrive - test_change_capital_rename_two_co_authors
TestEditAuthorsGdrive - test_rename_capital_on_upload
0 0 - Detail + Detail
TestEditBooksList - test_bookslist_edit_author
TestEditBooksList - test_bookslist_edit_categories
TestEditBooksList - test_bookslist_edit_comment
TestEditBooksList - test_bookslist_edit_cust_category
TestEditBooksList - test_bookslist_edit_cust_comment
TestEditBooksList - test_bookslist_edit_cust_enum
TestEditBooksList - test_bookslist_edit_cust_float
TestEditBooksList - test_bookslist_edit_cust_int
TestEditBooksList - test_bookslist_edit_cust_ratings
TestEditBooksList - test_bookslist_edit_cust_text
TestEditBooksList - test_bookslist_edit_languages
TestEditBooksList - test_bookslist_edit_publisher
TestEditBooksList - test_bookslist_edit_series
TestEditBooksList - test_bookslist_edit_seriesindex
TestEditBooksList - test_bookslist_edit_title
TestEditBooksList - test_list_visibility
TestEditBooksList - test_restricted_rights
TestEditBooksList - test_search_books_list
TestLoadMetadata 1 00 1 00 - Detail + Detail
TestLoadMetadata - test_load_metadata
- FAIL + ERROR
-
1 0 - Detail + Detail
TestEditBooksOnGdrive - test_download_book
TestEditBooksOnGdrive - test_edit_author
TestEditBooksOnGdrive - test_edit_category
TestEditBooksOnGdrive - test_edit_comments
TestEditBooksOnGdrive - test_edit_custom_bool
TestEditBooksOnGdrive - test_edit_custom_categories
TestEditBooksOnGdrive - test_edit_custom_float
TestEditBooksOnGdrive - test_edit_custom_int
TestEditBooksOnGdrive - test_edit_custom_rating
TestEditBooksOnGdrive - test_edit_custom_single_select
TestEditBooksOnGdrive - test_edit_custom_text
TestEditBooksOnGdrive - test_edit_language
TestEditBooksOnGdrive - test_edit_publisher
TestEditBooksOnGdrive - test_edit_rating
TestEditBooksOnGdrive - test_edit_series
TestEditBooksOnGdrive - test_edit_title
- ERROR + ERROR
-
TestEditBooksOnGdrive - test_upload_book_lit
TestEditBooksOnGdrive - test_watch_metadata
0 0 - Detail + Detail
TestLoadMetadataScholar - test_load_metadata
0 0 - Detail + Detail
TestSTARTTLS - test_STARTTLS
TestSTARTTLS - test_STARTTLS_SSL_setup_error
TestSTARTTLS - test_STARTTLS_resend_password
0 0 - Detail + Detail
TestSSL - test_SSL_None_setup_error
TestSSL - test_SSL_STARTTLS_setup_error
TestSSL - test_SSL_logging_email
TestSSL - test_SSL_non_admin_user
TestSSL - test_SSL_only
TestSSL - test_email_limit
TestSSL - test_filepicker_two_file
0 0 - Detail + Detail
TestBookDatabase - test_invalid_book_path
0 0 - Detail + Detail
TestErrorReadColumn - test_invalid_custom_column
TestErrorReadColumn - test_invalid_custom_read_column
0 1 - Detail + Detail
TestFilePicker - test_filepicker_limited_file
TestFilePicker - test_filepicker_new_file
- SKIP + SKIP
-
TestFilePicker - test_two_filepickers
0 0 - Detail + Detail
TestSetupGdrive - test_config_gdrive
0 0 - Detail + Detail
TestGoodreads - test_author_page
TestGoodreads - test_author_page_invalid
TestGoodreads - test_goodreads_about
TestKoboSync11111212 0 0 0 - Detail + Detail
TestKoboSync - test_book_download
TestKoboSync - test_kobo_about
+
TestKoboSync - test_kobo_limit
+
PASS
TestKoboSync - test_kobo_sync_selected_shelfs
TestKoboSync - test_kobo_upload_book
TestKoboSync - test_shelves_add_remove_books
TestKoboSync - test_sync_changed_book
TestKoboSync - test_sync_invalid
TestKoboSync - test_sync_reading_state
TestKoboSync - test_sync_shelf
TestKoboSync - test_sync_unchanged
TestKoboSync - test_sync_upload
0 0 - Detail + Detail
TestKoboSyncBig - test_download_cover
TestKoboSyncBig - test_kobo_sync_multi_user
TestKoboSyncBig - test_kobo_sync_selected_shelves
TestKoboSyncBig - test_sync_changed_book
TestKoboSyncBig - test_sync_reading_state
TestKoboSyncBig - test_sync_shelf
0 0 - Detail + Detail
TestLdapLogin - test_LDAP_SSL
TestLdapLogin - test_LDAP_SSL_CERTIFICATE
TestLdapLogin - test_LDAP_STARTTLS
TestLdapLogin - test_LDAP_fallback_Login
TestLdapLogin - test_LDAP_import
TestLdapLogin - test_LDAP_import_memberfield
TestLdapLogin - test_LDAP_login
TestLdapLogin - test_invalid_LDAP
TestLdapLogin - test_ldap_about
TestLdapLogin - test_ldap_authentication
TestLdapLogin - test_ldap_kobo_sync
TestLdapLogin - test_ldap_opds_anonymous
TestLdapLogin - test_ldap_opds_download_book
TestSecurity44000 + Detail +
+
TestSecurity - test_login_limit
+
PASS
+
TestSecurity - test_opds_limit
+
PASS
+
TestSecurity - test_password_strength
+
PASS
+
TestSecurity - test_register_limit
+
PASS
TestCalibreWebListOrders 10 0 0 - Detail + Detail
TestCalibreWebListOrders - test_author_sort
TestCalibreWebListOrders - test_download_sort
TestCalibreWebListOrders - test_format_sort
TestCalibreWebListOrders - test_lang_sort
TestCalibreWebListOrders - test_order_authors_all_links
TestCalibreWebListOrders - test_order_series_all_links
TestCalibreWebListOrders - test_publisher_sort
TestCalibreWebListOrders - test_ratings_sort
TestCalibreWebListOrders - test_series_sort
TestCalibreWebListOrders - test_tags_sort
0 1 - Detail + Detail
TestLogging - test_access_log_recover
TestLogging - test_debug_log
TestLogging - test_debuginfo_download
TestLogging - test_failed_login
TestLogging - test_failed_register
- SKIP + SKIP
-
TestLogging - test_logbook_download
TestLogging - test_logfile_change
TestLogging - test_logfile_recover
TestLogging - test_logviewer
TestLogin15151717 0 0 0 - Detail + Detail
TestLogin - test_digest_login
TestLogin - test_login_capital_letters_user_unicode_password
TestLogin - test_login_cookie_steal
TestLogin - test_login_delete_admin
TestLogin - test_login_empty_password
TestLogin - test_login_locale_select
TestLogin - test_login_protected
TestLogin - test_login_remember_me
TestLogin - test_login_rename_user
TestLogin - test_login_unicode_user_space_end_password
TestLogin - test_login_user_with_space_password_end_space
TestLogin - test_magic_remote_login
TestLogin - test_next
+
TestLogin - test_password_policy
+
PASS
TestLogin - test_proxy_login
+
TestLogin - test_proxy_login_opds
+
PASS
TestLogin - test_robots
0 0 - Detail + Detail
TestMergeBooksList - test_book_merge
TestMergeBooksList - test_delete_book
0 0 - Detail + Detail
TestOAuthLogin - test_oauth_about
TestOAuthLogin - test_visible_oauth
TestOPDSFeed23232424 0 0 0 - Detail + Detail
TestOPDSFeed - test_opds
TestOPDSFeed - test_opds_author
TestOPDSFeed - test_opds_books
TestOPDSFeed - test_opds_calibre_companion
TestOPDSFeed - test_opds_colon_password
TestOPDSFeed - test_opds_cover
TestOPDSFeed - test_opds_download_book
TestOPDSFeed - test_opds_formats
TestOPDSFeed - test_opds_guest_user
TestOPDSFeed - test_opds_hot
TestOPDSFeed - test_opds_language
TestOPDSFeed - test_opds_non_admin
TestOPDSFeed - test_opds_publisher
TestOPDSFeed - test_opds_random
TestOPDSFeed - test_opds_ratings
TestOPDSFeed - test_opds_read_unread
TestOPDSFeed - test_opds_search
TestOPDSFeed - test_opds_series
TestOPDSFeed - test_opds_shelf_access
+
TestOPDSFeed - test_opds_stats
+
PASS
TestOPDSFeed - test_opds_tags
TestOPDSFeed - test_opds_top_rated
TestOPDSFeed - test_opds_unicode_user
TestOPDSFeed - test_recently_added
0 0 - Detail + Detail
TestUploadPDF - test_upload_invalid_pdf
0 0 - Detail + Detail
TestPipInstall - test_command_start
TestPipInstall - test_foldername_database_location
TestPipInstall - test_module_start
TestReader6 5501 0 0 - Detail + Detail
+
TestReader - test_comic_MACOS_files
+
PASS
TestReader - test_comic_reader
TestReader - test_epub_reader
TestReader - test_pdf_reader
TestReader - test_sound_listener
PASS +
+ FAIL +
+ + + +
TestReader - test_txt_reader
0 0 - Detail + Detail
TestReadOnlyDatabase - test_readonly_path
0 0 - Detail + Detail
TestRegister - test_forgot_password
TestRegister - test_illegal_email
TestRegister - test_limit_domain
TestRegister - test_register_no_server
TestRegister - test_registering_only_email
TestRegister - test_registering_user
TestRegister - test_registering_user_fail
TestRegister - test_user_change_password
0 0 - Detail + Detail
TestReverseProxy - test_logout
TestReverseProxy - test_move_page
TestReverseProxy - test_reverse_about
0 1 - Detail + Detail
TestShelf - test_access_shelf
TestShelf - test_add_shelf_from_search
TestShelf - test_adv_search_shelf
TestShelf - test_arrange_shelf
TestShelf - test_create_public_shelf
TestShelf - test_create_public_shelf_no_permission
TestShelf - test_delete_book_of_shelf
TestShelf - test_private_shelf
TestShelf - test_public_private_shelf
TestShelf - test_public_shelf
TestShelf - test_rename_shelf
TestShelf - test_shelf_action_non_shelf_edit_role
TestShelf - test_shelf_anonymous
TestShelf - test_shelf_database_change
- SKIP + SKIP
-
TestShelf - test_shelf_long_name
TestShelf - test_xss_shelf
0 0 - Detail + Detail
TestThumbnailsEnv - test_cover_cache_env_on_database_change
TestThumbnails 87061 0 1 - Detail + Detail
TestThumbnails - test_cache_non_writable
TestThumbnails - test_cache_of_deleted_book
TestThumbnails - test_cover_cache_on_database_change
TestThumbnails - test_cover_change_on_upload_new_cover
TestThumbnails - test_cover_for_series
TestThumbnails - test_cover_on_upload_book
TestThumbnails - test_remove_cover_from_cache
TestThumbnails - test_sideloaded_book
PASS +
+ FAIL +
+ + + +
0 1 - Detail + Detail
TestUpdater - test_check_update_nightly_errors
TestUpdater - test_check_update_nightly_request_errors
TestUpdater - test_check_update_stable_errors
TestUpdater - test_check_update_stable_versions
TestUpdater - test_perform_update
TestUpdater - test_perform_update_stable_errors
TestUpdater - test_perform_update_timeout
- SKIP + SKIP
-
TestUpdater - test_reconnect_database
TestUpdater - test_update_write_protect
TestUploadEPubs4455 0 0 0 - Detail + Detail
TestUploadEPubs - test_upload_epub_cover
TestUploadEPubs - test_upload_epub_cover_formats
TestUploadEPubs - test_upload_epub_duplicate
+
TestUploadEPubs - test_upload_epub_identifier
+
PASS
TestUploadEPubs - test_upload_epub_lang
0 0 - Detail + Detail
TestUserList - test_edit_user_email
TestUserList - test_list_visibility
TestUserList - test_user_list_admin_role
TestUserList - test_user_list_check_sort
TestUserList - test_user_list_denied_tags
TestUserList - test_user_list_download_role
TestUserList - test_user_list_edit_button
TestUserList - test_user_list_edit_email
TestUserList - test_user_list_edit_kindle
TestUserList - test_user_list_edit_language
TestUserList - test_user_list_edit_locale
TestUserList - test_user_list_edit_name
TestUserList - test_user_list_edit_visiblility
TestUserList - test_user_list_guest_edit
TestUserList - test_user_list_remove_admin
TestUserList - test_user_list_requests
TestUserList - test_user_list_search
TestUserList - test_user_list_sort
0 0 - Detail + Detail
TestUserLoad - test_user_change_vis
0 0 - Detail + Detail
TestUserTemplate - test_allow_column_restriction
TestUserTemplate - test_allow_tag_restriction
TestUserTemplate - test_archived_format_template
TestUserTemplate - test_author_user_template
TestUserTemplate - test_best_user_template
TestUserTemplate - test_category_user_template
TestUserTemplate - test_deny_column_restriction
TestUserTemplate - test_deny_tag_restriction
TestUserTemplate - test_detail_random_user_template
TestUserTemplate - test_download_user_template
TestUserTemplate - test_format_user_template
TestUserTemplate - test_hot_user_template
TestUserTemplate - test_language_user_template
TestUserTemplate - test_limit_book_languages
TestUserTemplate - test_list_user_template
TestUserTemplate - test_publisher_user_template
TestUserTemplate - test_random_user_template
TestUserTemplate - test_read_user_template
TestUserTemplate - test_recent_user_template
TestUserTemplate - test_series_user_template
TestUserTemplate - test_ui_language_settings
0 0 - Detail + Detail
TestCalibreWebVisibilitys - test_about
TestCalibreWebVisibilitys - test_admin_SMTP_Settings
TestCalibreWebVisibilitys - test_admin_add_user
TestCalibreWebVisibilitys - test_admin_change_password
TestCalibreWebVisibilitys - test_admin_change_visibility_archived
TestCalibreWebVisibilitys - test_admin_change_visibility_authors
TestCalibreWebVisibilitys - test_admin_change_visibility_category
TestCalibreWebVisibilitys - test_admin_change_visibility_file_formats
TestCalibreWebVisibilitys - test_admin_change_visibility_hot
TestCalibreWebVisibilitys - test_admin_change_visibility_language
TestCalibreWebVisibilitys - test_admin_change_visibility_publisher
TestCalibreWebVisibilitys - test_admin_change_visibility_random
TestCalibreWebVisibilitys - test_admin_change_visibility_rated
TestCalibreWebVisibilitys - test_admin_change_visibility_rating
TestCalibreWebVisibilitys - test_admin_change_visibility_read
TestCalibreWebVisibilitys - test_admin_change_visibility_series
TestCalibreWebVisibilitys - test_allow_columns
TestCalibreWebVisibilitys - test_allow_tags
TestCalibreWebVisibilitys - test_archive_books
TestCalibreWebVisibilitys - test_authors_max_settings
TestCalibreWebVisibilitys - test_change_title
TestCalibreWebVisibilitys - test_checked_logged_in
TestCalibreWebVisibilitys - test_hide_custom_column
TestCalibreWebVisibilitys - test_link_column_to_read_status
TestCalibreWebVisibilitys - test_random_books_available
TestCalibreWebVisibilitys - test_read_status_visible
TestCalibreWebVisibilitys - test_request_link_column_to_read_status
TestCalibreWebVisibilitys - test_restrict_columns
TestCalibreWebVisibilitys - test_restrict_tags
TestCalibreWebVisibilitys - test_save_views_recent
TestCalibreWebVisibilitys - test_search_functions
TestCalibreWebVisibilitys - test_search_order
TestCalibreWebVisibilitys - test_search_string
TestCalibreWebVisibilitys - test_user_email_available
TestCalibreWebVisibilitys - test_user_visibility_sidebar
0 0 - Detail + Detail
TestCalibreHelper - test_author_sort
TestCalibreHelper - test_author_sort_comma
TestCalibreHelper - test_author_sort_junior
TestCalibreHelper - test_author_sort_oneword
TestCalibreHelper - test_author_sort_roman
TestCalibreHelper - test_check_Limit_Length
TestCalibreHelper - test_check_char_replacement
TestCalibreHelper - test_check_chinese_Characters
TestCalibreHelper - test_check_deg_eur_replacement
TestCalibreHelper - test_check_doubleS
TestCalibreHelper - test_check_finish_Dot
TestCalibreHelper - test_check_high23
TestCalibreHelper - test_check_umlauts
TestCalibreHelper - test_random_password
TestCalibreHelper - test_split_authors
TestCalibreHelper - test_whitespaces
Total423414117462449229  
@@ -4802,13 +5278,13 @@ IndexError: list index out of range Platform - Linux 5.15.0-48-generic #54-Ubuntu SMP Fri Aug 26 13:26:29 UTC 2022 x86_64 x86_64 + Linux 6.2.0-34-generic #34~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 7 13:12:03 UTC 2 x86_64 x86_64 Basic Python - 3.10.6 + 3.10.12 Basic @@ -4820,19 +5296,13 @@ IndexError: list index out of range APScheduler - 3.9.1 + 3.10.4 Basic Babel - 2.10.3 - Basic - - - - backports-abc - 0.5 + 2.13.0 Basic @@ -4844,19 +5314,25 @@ IndexError: list index out of range Flask - 2.0.3 + 2.3.3 Basic - Flask-Babel - 2.0.0 + flask-babel + 3.1.0 + Basic + + + + Flask-Limiter + 3.4.1 Basic Flask-Login - 0.6.1 + 0.6.2 Basic @@ -4868,13 +5344,13 @@ IndexError: list index out of range Flask-WTF - 1.0.1 + 1.1.2 Basic greenlet - 1.1.3 + 3.0.0 Basic @@ -4892,73 +5368,103 @@ IndexError: list index out of range lxml - 4.8.0 + 4.9.3 Basic pyasn1 - 0.4.8 + 0.5.0 Basic - PyPDF2 - 2.10.9 + pypdf + 3.15.5 Basic pytz - 2022.2.1 + 2023.3.post1 Basic requests - 2.27.1 + 2.31.0 Basic SQLAlchemy - 1.4.41 + 1.4.49 Basic tornado - 6.1 + 6.3.3 Basic Unidecode - 1.3.4 + 1.3.7 Basic Wand - 0.6.10 + 0.6.11 Basic Werkzeug - 2.0.3 + 2.3.7 Basic google-api-python-client - 2.62.0 + 2.103.0 + TestBackupMetadataGdrive + + + + httplib2 + 0.22.0 + TestBackupMetadataGdrive + + + + oauth2client + 4.1.3 + TestBackupMetadataGdrive + + + + PyDrive2 + 1.17.0 + TestBackupMetadataGdrive + + + + PyYAML + 6.0.1 + TestBackupMetadataGdrive + + + + google-api-python-client + 2.103.0 TestCliGdrivedb httplib2 - 0.20.4 + 0.22.0 TestCliGdrivedb @@ -4970,25 +5476,25 @@ IndexError: list index out of range PyDrive2 - 1.14.0 + 1.17.0 TestCliGdrivedb PyYAML - 6.0 + 6.0.1 TestCliGdrivedb google-api-python-client - 2.62.0 + 2.103.0 TestEbookConvertCalibreGDrive httplib2 - 0.20.4 + 0.22.0 TestEbookConvertCalibreGDrive @@ -5000,25 +5506,25 @@ IndexError: list index out of range PyDrive2 - 1.14.0 + 1.17.0 TestEbookConvertCalibreGDrive PyYAML - 6.0 + 6.0.1 TestEbookConvertCalibreGDrive google-api-python-client - 2.62.0 + 2.103.0 TestEbookConvertGDriveKepubify httplib2 - 0.20.4 + 0.22.0 TestEbookConvertGDriveKepubify @@ -5030,37 +5536,49 @@ IndexError: list index out of range PyDrive2 - 1.14.0 + 1.17.0 TestEbookConvertGDriveKepubify PyYAML - 6.0 + 6.0.1 TestEbookConvertGDriveKepubify comicapi - 2.2.1 + 3.2.0 + TestEditAdditionalBooks + + + + py7zr + 0.20.6 TestEditAdditionalBooks rarfile - 4.0 + 4.1 TestEditAdditionalBooks + + py7zr + 0.20.6 + TestEditBooks + + google-api-python-client - 2.62.0 + 2.103.0 TestEditAuthorsGdrive httplib2 - 0.20.4 + 0.22.0 TestEditAuthorsGdrive @@ -5072,31 +5590,31 @@ IndexError: list index out of range PyDrive2 - 1.14.0 + 1.17.0 TestEditAuthorsGdrive PyYAML - 6.0 + 6.0.1 TestEditAuthorsGdrive beautifulsoup4 - 4.11.1 + 4.12.2 TestLoadMetadata google-api-python-client - 2.62.0 + 2.103.0 TestEditBooksOnGdrive httplib2 - 0.20.4 + 0.22.0 TestEditBooksOnGdrive @@ -5108,37 +5626,37 @@ IndexError: list index out of range PyDrive2 - 1.14.0 + 1.17.0 TestEditBooksOnGdrive PyYAML - 6.0 + 6.0.1 TestEditBooksOnGdrive beautifulsoup4 - 4.11.1 + 4.12.2 TestLoadMetadataScholar scholarly - 1.7.2 + 1.7.11 TestLoadMetadataScholar google-api-python-client - 2.62.0 + 2.103.0 TestSetupGdrive httplib2 - 0.20.4 + 0.22.0 TestSetupGdrive @@ -5150,13 +5668,13 @@ IndexError: list index out of range PyDrive2 - 1.14.0 + 1.17.0 TestSetupGdrive PyYAML - 6.0 + 6.0.1 TestSetupGdrive @@ -5168,19 +5686,19 @@ IndexError: list index out of range python-Levenshtein - 0.12.2 + 0.23.0 TestGoodreads jsonschema - 4.16.0 + 4.19.1 TestKoboSync jsonschema - 4.16.0 + 4.19.1 TestKoboSyncBig @@ -5192,7 +5710,7 @@ IndexError: list index out of range jsonschema - 4.16.0 + 4.19.1 TestLdapLogin @@ -5204,13 +5722,13 @@ IndexError: list index out of range Flask-Dance - 6.1.1 + 7.0.0 TestOAuthLogin SQLAlchemy-Utils - 0.38.3 + 0.41.1 TestOAuthLogin @@ -5222,7 +5740,7 @@ IndexError: list index out of range